Make parcelwrap able to wrap humanoids (#40911)
* parcel * help, I'm being forced to add admin abuse features * review
This commit is contained in:
@@ -10,58 +10,64 @@ namespace Content.Shared.ParcelWrap.Components;
|
|||||||
/// This component gives its owning entity the ability to wrap items into parcels.
|
/// This component gives its owning entity the ability to wrap items into parcels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="Components.WrappedParcelComponent"/>
|
/// <seealso cref="Components.WrappedParcelComponent"/>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
[Access] // Readonly, except for VV editing
|
[Access] // Readonly, except for VV editing
|
||||||
public sealed partial class ParcelWrapComponent : Component
|
public sealed partial class ParcelWrapComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="EntityPrototype"/> of the parcel created by using this component.
|
/// The <see cref="EntityPrototype"/> of the parcel created by using this component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true), AutoNetworkedField]
|
||||||
public EntProtoId ParcelPrototype;
|
public EntProtoId ParcelPrototype;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, parcels created by this will have the same <see cref="ItemSizePrototype">size</see> as the item they
|
/// If true, parcels created by this will have the same <see cref="ItemSizePrototype">size</see> as the item they
|
||||||
/// contain. If false, parcels created by this will always have the size specified by <see cref="FallbackItemSize"/>.
|
/// contain. If false, parcels created by this will always have the size specified by <see cref="FallbackItemSize"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool WrappedItemsMaintainSize = true;
|
public bool WrappedItemsMaintainSize = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ItemSizePrototype">size</see> of parcels created by this component's entity. This is used if
|
/// The <see cref="ItemSizePrototype">size</see> of parcels created by this component's entity. This is used if
|
||||||
/// <see cref="WrappedItemsMaintainSize"/> is false, or if the item being wrapped somehow doesn't have a size.
|
/// <see cref="WrappedItemsMaintainSize"/> is false, or if the item being wrapped somehow doesn't have a size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public ProtoId<ItemSizePrototype> FallbackItemSize = "Ginormous";
|
public ProtoId<ItemSizePrototype> FallbackItemSize = "Ginormous";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, parcels created by this will have the same shape as the item they contain. If false, parcels created by
|
/// If true, parcels created by this will have the same shape as the item they contain. If false, parcels created by
|
||||||
/// this will have the default shape for their size.
|
/// this will have the default shape for their size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool WrappedItemsMaintainShape;
|
public bool WrappedItemsMaintainShape;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long it takes to use this to wrap something.
|
/// How long it takes to use this to wrap something.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true), AutoNetworkedField]
|
||||||
public TimeSpan WrapDelay = TimeSpan.FromSeconds(1);
|
public TimeSpan WrapDelay = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sound played when this is used to wrap something.
|
/// Sound played when this is used to wrap something.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public SoundSpecifier? WrapSound;
|
public SoundSpecifier? WrapSound;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the set of things which can be wrapped (unless it fails the <see cref="Blacklist"/>).
|
/// Defines the set of things which can be wrapped (unless it fails the <see cref="Blacklist"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntityWhitelist? Whitelist;
|
public EntityWhitelist? Whitelist;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the set of things which cannot be wrapped (even if it passes the <see cref="Whitelist"/>).
|
/// Defines the set of things which cannot be wrapped (even if it passes the <see cref="Whitelist"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntityWhitelist? Blacklist;
|
public EntityWhitelist? Blacklist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If a player trapped inside this parcel can escape from it by unwrapping it.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool CanSelfUnwrap = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.ParcelWrap.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to an entity to override the datafields in <see cref="ParcelWrapComponent"/> when it is being wrapped.
|
||||||
|
/// Use this for special, non-item parcel types, for example Urist-shaped parcels.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ParcelWrapOverrideComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="EntityPrototype"/> of the parcel created by wrapping this entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true), AutoNetworkedField]
|
||||||
|
public EntProtoId? ParcelPrototype;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long it takes to use this to wrap something.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true), AutoNetworkedField]
|
||||||
|
public TimeSpan? WrapDelay;
|
||||||
|
}
|
||||||
@@ -11,7 +11,8 @@ namespace Content.Shared.ParcelWrap.Components;
|
|||||||
/// destroying this entity and releasing <see cref="Contents"/>.
|
/// destroying this entity and releasing <see cref="Contents"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="ParcelWrapComponent"/>
|
/// <seealso cref="ParcelWrapComponent"/>
|
||||||
[RegisterComponent, NetworkedComponent, Access(typeof(ParcelWrappingSystem))]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
[Access(typeof(ParcelWrappingSystem))]
|
||||||
public sealed partial class WrappedParcelComponent : Component
|
public sealed partial class WrappedParcelComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -23,19 +24,19 @@ public sealed partial class WrappedParcelComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the entity to spawn when this parcel is unwrapped.
|
/// Specifies the entity to spawn when this parcel is unwrapped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntProtoId? UnwrapTrash;
|
public EntProtoId? UnwrapTrash;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How long it takes to unwrap this parcel.
|
/// How long it takes to unwrap this parcel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true), AutoNetworkedField]
|
||||||
public TimeSpan UnwrapDelay = TimeSpan.FromSeconds(1);
|
public TimeSpan UnwrapDelay = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sound played when unwrapping this parcel.
|
/// Sound played when unwrapping this parcel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public SoundSpecifier? UnwrapSound;
|
public SoundSpecifier? UnwrapSound;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -43,4 +44,11 @@ public sealed partial class WrappedParcelComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||||
public string ContainerId = "contents";
|
public string ContainerId = "contents";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If a player trapped inside this parcel can escape from it by unwrapping it.
|
||||||
|
/// This is set by the <see cref="ParcelWrapComponent" /> used to create the parcel.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool CanSelfUnwrap = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
using Content.Shared.ParcelWrap.Components;
|
using Content.Shared.ParcelWrap.Components;
|
||||||
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -59,9 +61,26 @@ public sealed partial class ParcelWrappingSystem
|
|||||||
|
|
||||||
private bool TryStartWrapDoAfter(EntityUid user, Entity<ParcelWrapComponent> wrapper, EntityUid target)
|
private bool TryStartWrapDoAfter(EntityUid user, Entity<ParcelWrapComponent> wrapper, EntityUid target)
|
||||||
{
|
{
|
||||||
|
var duration = wrapper.Comp.WrapDelay;
|
||||||
|
|
||||||
|
if (TryComp<ParcelWrapOverrideComponent>(target, out var overrideComp) && overrideComp.WrapDelay != null)
|
||||||
|
duration = overrideComp.WrapDelay.Value;
|
||||||
|
|
||||||
|
// In case the target is a player inform them with a popup.
|
||||||
|
if (target == user)
|
||||||
|
{
|
||||||
|
var selfMsg = Loc.GetString("parcel-wrap-popup-being-wrapped-self");
|
||||||
|
_popup.PopupClient(selfMsg, user, user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var othersMsg = Loc.GetString("parcel-wrap-popup-being-wrapped", ("user", Identity.Entity(user, EntityManager)));
|
||||||
|
_popup.PopupEntity(othersMsg, target, target, PopupType.MediumCaution);
|
||||||
|
}
|
||||||
|
|
||||||
return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
|
||||||
user,
|
user,
|
||||||
wrapper.Comp.WrapDelay,
|
duration,
|
||||||
new ParcelWrapItemDoAfterEvent(),
|
new ParcelWrapItemDoAfterEvent(),
|
||||||
wrapper, // Raise the event on the wrapper because that's what the event handler expects.
|
wrapper, // Raise the event on the wrapper because that's what the event handler expects.
|
||||||
target,
|
target,
|
||||||
@@ -81,18 +100,34 @@ public sealed partial class ParcelWrappingSystem
|
|||||||
/// <param name="target">The entity being wrapped.</param>
|
/// <param name="target">The entity being wrapped.</param>
|
||||||
private void WrapInternal(EntityUid user, Entity<ParcelWrapComponent> wrapper, EntityUid target)
|
private void WrapInternal(EntityUid user, Entity<ParcelWrapComponent> wrapper, EntityUid target)
|
||||||
{
|
{
|
||||||
if (_net.IsServer)
|
// Consume a `use` on the wrapper, and delete the wrapper if it's empty.
|
||||||
|
_charges.TryUseCharges(wrapper.Owner, 1);
|
||||||
|
if (_charges.IsEmpty(wrapper.Owner))
|
||||||
|
PredictedQueueDel(wrapper);
|
||||||
|
|
||||||
|
// Play a wrapping sound.
|
||||||
|
_audio.PlayPredicted(wrapper.Comp.WrapSound, target, user);
|
||||||
|
|
||||||
|
if (_net.IsClient)
|
||||||
|
return; // Predicted spawns can't be interacted with yet.
|
||||||
|
|
||||||
|
EntityUid spawned;
|
||||||
|
var targetTransform = Transform(target);
|
||||||
|
// Check if the target has a pre-defined parcel type to be used.
|
||||||
|
if (TryComp<ParcelWrapOverrideComponent>(target, out var overrideComp))
|
||||||
{
|
{
|
||||||
var spawned = Spawn(wrapper.Comp.ParcelPrototype, Transform(target).Coordinates);
|
spawned = Spawn(overrideComp.ParcelPrototype, targetTransform.Coordinates);
|
||||||
|
}
|
||||||
|
else // Create a parcel with the same size and generic sprites instead.
|
||||||
|
{
|
||||||
|
spawned = Spawn(wrapper.Comp.ParcelPrototype, targetTransform.Coordinates);
|
||||||
|
|
||||||
// If this wrap maintains the size when wrapping, set the parcel's size to the target's size. Otherwise use the
|
// If this wrap maintains the size when wrapping, set the parcel's size to the target's size. Otherwise use the
|
||||||
// wrap's fallback size.
|
// wrap's fallback size.
|
||||||
TryComp(target, out ItemComponent? targetItemComp);
|
TryComp(target, out ItemComponent? targetItemComp);
|
||||||
var size = wrapper.Comp.FallbackItemSize;
|
var size = wrapper.Comp.FallbackItemSize;
|
||||||
if (wrapper.Comp.WrappedItemsMaintainSize && targetItemComp is not null)
|
if (wrapper.Comp.WrappedItemsMaintainSize && targetItemComp is not null)
|
||||||
{
|
|
||||||
size = targetItemComp.Size;
|
size = targetItemComp.Size;
|
||||||
}
|
|
||||||
|
|
||||||
// ParcelWrap's spawned entity should always have an `ItemComp`. As of writing, the only use has it hardcoded on
|
// ParcelWrap's spawned entity should always have an `ItemComp`. As of writing, the only use has it hardcoded on
|
||||||
// its prototype.
|
// its prototype.
|
||||||
@@ -103,33 +138,28 @@ public sealed partial class ParcelWrappingSystem
|
|||||||
// If this wrap maintains the shape when wrapping and the item has a shape override, copy the shape override to
|
// If this wrap maintains the shape when wrapping and the item has a shape override, copy the shape override to
|
||||||
// the parcel.
|
// the parcel.
|
||||||
if (wrapper.Comp.WrappedItemsMaintainShape && targetItemComp is { Shape: { } shape })
|
if (wrapper.Comp.WrappedItemsMaintainShape && targetItemComp is { Shape: { } shape })
|
||||||
{
|
|
||||||
_item.SetShape(spawned, shape, item);
|
_item.SetShape(spawned, shape, item);
|
||||||
}
|
|
||||||
|
|
||||||
// If the target's in a container, try to put the parcel in its place in the container.
|
|
||||||
if (_container.TryGetContainingContainer((target, null, null), out var containerOfTarget))
|
|
||||||
{
|
|
||||||
_container.Remove(target, containerOfTarget);
|
|
||||||
_container.InsertOrDrop((spawned, null, null), containerOfTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the target into the parcel.
|
|
||||||
var parcel = EnsureComp<WrappedParcelComponent>(spawned);
|
|
||||||
if (!_container.Insert(target, parcel.Contents))
|
|
||||||
{
|
|
||||||
DebugTools.Assert(
|
|
||||||
$"Failed to insert target entity into newly spawned parcel. target={PrettyPrint.PrintUserFacing(target)}");
|
|
||||||
QueueDel(spawned);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume a `use` on the wrapper, and delete the wrapper if it's empty.
|
_transform.SetLocalRotation(spawned, targetTransform.LocalRotation);
|
||||||
_charges.TryUseCharges(wrapper.Owner, 1);
|
|
||||||
if (_net.IsServer && _charges.IsEmpty(wrapper.Owner))
|
|
||||||
QueueDel(wrapper);
|
|
||||||
|
|
||||||
// Play a wrapping sound.
|
// If the target is in a container, try to put the parcel in its place in the container.
|
||||||
_audio.PlayPredicted(wrapper.Comp.WrapSound, target, user);
|
if (_container.TryGetContainingContainer((target, null, null), out var containerOfTarget))
|
||||||
|
{
|
||||||
|
_container.Remove(target, containerOfTarget);
|
||||||
|
_container.InsertOrDrop((spawned, null, null), containerOfTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the target into the parcel.
|
||||||
|
var parcel = EnsureComp<WrappedParcelComponent>(spawned);
|
||||||
|
parcel.CanSelfUnwrap = wrapper.Comp.CanSelfUnwrap;
|
||||||
|
Dirty(spawned, parcel);
|
||||||
|
|
||||||
|
if (!_container.Insert(target, parcel.Contents))
|
||||||
|
{
|
||||||
|
DebugTools.Assert(
|
||||||
|
$"Failed to insert target entity into newly spawned parcel. target={PrettyPrint.PrintUserFacing(target)}");
|
||||||
|
PredictedDel(spawned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public sealed partial class ParcelWrappingSystem
|
|||||||
if (!args.CanAccess || !args.CanComplexInteract)
|
if (!args.CanAccess || !args.CanComplexInteract)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (entity.Comp.Contents.Contains(args.User))
|
if (!entity.Comp.CanSelfUnwrap && entity.Comp.Contents.Contains(args.User))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// "Capture" the values from `args` because C# doesn't like doing the capturing for `ref` values.
|
// "Capture" the values from `args` because C# doesn't like doing the capturing for `ref` values.
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ parcel-wrap-verb-wrap = Wrap
|
|||||||
parcel-wrap-verb-unwrap = Unwrap
|
parcel-wrap-verb-unwrap = Unwrap
|
||||||
|
|
||||||
parcel-wrap-popup-parcel-destroyed = The wrapping containing { THE($contents) } is destroyed!
|
parcel-wrap-popup-parcel-destroyed = The wrapping containing { THE($contents) } is destroyed!
|
||||||
|
parcel-wrap-popup-being-wrapped = {CAPITALIZE(THE($user))} is trying to parcel wrap you!
|
||||||
|
parcel-wrap-popup-being-wrapped-self = You start parcel wrapping yourself.
|
||||||
|
|
||||||
# Shown when parcel wrap is examined in details range
|
# Shown when parcel wrap is examined in details range
|
||||||
parcel-wrap-examine-detail-uses = { $uses ->
|
parcel-wrap-examine-detail-uses = { $uses ->
|
||||||
@@ -176,6 +176,9 @@
|
|||||||
factions:
|
factions:
|
||||||
- NanoTrasen
|
- NanoTrasen
|
||||||
- type: CreamPied
|
- type: CreamPied
|
||||||
|
- type: ParcelWrapOverride
|
||||||
|
parcelPrototype: WrappedParcelHumanoid
|
||||||
|
wrapDelay: 5
|
||||||
- type: Stripping
|
- type: Stripping
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- Item
|
- Item
|
||||||
|
- ParcelWrapOverride
|
||||||
blacklist:
|
blacklist:
|
||||||
components:
|
components:
|
||||||
- NukeDisk # Don't try to hide the disk.
|
- NukeDisk # Don't try to hide the disk.
|
||||||
@@ -38,48 +39,24 @@
|
|||||||
- type: ParcelWrap
|
- type: ParcelWrap
|
||||||
whitelist: null
|
whitelist: null
|
||||||
blacklist: null
|
blacklist: null
|
||||||
|
canSelfUnwrap: false # admins held me at gunpoint until I added this bool
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
abstract: true
|
||||||
id: WrappedParcel
|
id: BaseWrappedParcel
|
||||||
categories: [ HideSpawnMenu ]
|
|
||||||
name: wrapped parcel
|
name: wrapped parcel
|
||||||
description: Something wrapped up in paper. I wonder what's inside...
|
description: Something wrapped up in paper. I wonder what's inside...
|
||||||
components:
|
components:
|
||||||
|
- type: Physics
|
||||||
|
bodyType: Dynamic
|
||||||
|
- type: GravityAffected
|
||||||
|
- type: Clickable
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Pullable
|
||||||
- type: ContainerContainer
|
- type: ContainerContainer
|
||||||
containers:
|
containers:
|
||||||
contents: !type:ContainerSlot
|
contents: !type:ContainerSlot
|
||||||
paper_label: !type:ContainerSlot
|
paper_label: !type:ContainerSlot
|
||||||
- type: Appearance
|
|
||||||
- type: GenericVisualizer
|
|
||||||
visuals:
|
|
||||||
enum.WrappedParcelVisuals.Size:
|
|
||||||
enum.WrappedParcelVisuals.Layer:
|
|
||||||
"Tiny": { state: "parcel-tiny" }
|
|
||||||
"Small": { state: "parcel-small" }
|
|
||||||
"Medium": { state: "parcel-medium" }
|
|
||||||
"Large": { state: "parcel-medium" }
|
|
||||||
"Huge": { state: "parcel-large" }
|
|
||||||
"Ginormous": { state: "parcel-large" }
|
|
||||||
enum.PaperLabelVisuals.HasLabel:
|
|
||||||
enum.PaperLabelVisuals.Layer:
|
|
||||||
True: { visible: true }
|
|
||||||
False: { visible: false }
|
|
||||||
enum.PaperLabelVisuals.LabelType:
|
|
||||||
enum.PaperLabelVisuals.Layer:
|
|
||||||
Paper: { state: paper }
|
|
||||||
Bounty: { state: bounty }
|
|
||||||
CaptainsPaper: { state: captains_paper }
|
|
||||||
Invoice: { state: invoice }
|
|
||||||
- type: Sprite
|
|
||||||
sprite: Objects/Misc/ParcelWrap/wrapped_parcel.rsi
|
|
||||||
layers:
|
|
||||||
- state: parcel-medium
|
|
||||||
map: [ "enum.WrappedParcelVisuals.Layer" ]
|
|
||||||
- state: paper
|
|
||||||
visible: false
|
|
||||||
sprite: Objects/Misc/ParcelWrap/paper_labels.rsi
|
|
||||||
map: ["enum.PaperLabelVisuals.Layer"]
|
|
||||||
- type: WrappedParcel
|
- type: WrappedParcel
|
||||||
unwrapDelay: 0.5
|
unwrapDelay: 0.5
|
||||||
unwrapSound:
|
unwrapSound:
|
||||||
@@ -118,6 +95,67 @@
|
|||||||
tags:
|
tags:
|
||||||
- Recyclable # Parcel entity is recyclable, and when it's destroyed, it'll drop its contents.
|
- Recyclable # Parcel entity is recyclable, and when it's destroyed, it'll drop its contents.
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: [BaseItem, BaseWrappedParcel]
|
||||||
|
id: WrappedParcel
|
||||||
|
components:
|
||||||
|
- type: Appearance
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.WrappedParcelVisuals.Size:
|
||||||
|
enum.WrappedParcelVisuals.Layer:
|
||||||
|
"Tiny": { state: "parcel-tiny" }
|
||||||
|
"Small": { state: "parcel-small" }
|
||||||
|
"Medium": { state: "parcel-medium" }
|
||||||
|
"Large": { state: "parcel-medium" }
|
||||||
|
"Huge": { state: "parcel-large" }
|
||||||
|
"Ginormous": { state: "parcel-large" }
|
||||||
|
enum.PaperLabelVisuals.HasLabel:
|
||||||
|
enum.PaperLabelVisuals.Layer:
|
||||||
|
True: { visible: true }
|
||||||
|
False: { visible: false }
|
||||||
|
enum.PaperLabelVisuals.LabelType:
|
||||||
|
enum.PaperLabelVisuals.Layer:
|
||||||
|
Paper: { state: paper }
|
||||||
|
Bounty: { state: bounty }
|
||||||
|
CaptainsPaper: { state: captains_paper }
|
||||||
|
Invoice: { state: invoice }
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Misc/ParcelWrap/wrapped_parcel.rsi
|
||||||
|
layers:
|
||||||
|
- state: parcel-medium
|
||||||
|
map: [ "enum.WrappedParcelVisuals.Layer" ]
|
||||||
|
- state: paper
|
||||||
|
visible: false
|
||||||
|
sprite: Objects/Misc/ParcelWrap/paper_labels.rsi
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseWrappedParcel
|
||||||
|
id: WrappedParcelHumanoid
|
||||||
|
description: Something wrapped up in paper. It's suspiciously human-shaped.
|
||||||
|
components:
|
||||||
|
- type: Physics
|
||||||
|
fixedRotation: false
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Misc/ParcelWrap/wrapped_parcel.rsi
|
||||||
|
state: human
|
||||||
|
noRot: true
|
||||||
|
drawdepth: Mobs
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeCircle
|
||||||
|
radius: 0.35
|
||||||
|
density: 185
|
||||||
|
restitution: 0.0
|
||||||
|
mask:
|
||||||
|
- MobMask
|
||||||
|
layer:
|
||||||
|
- MobLayer
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
id: ParcelWrapTrash
|
id: ParcelWrapTrash
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC-BY-SA-4.0",
|
"license": "CC-BY-SA-4.0",
|
||||||
"copyright": "created for ss14 by ps3moira (github) based on package sprites from vgstation at https://github.com/vgstation-coders/vgstation13/pull/36993",
|
"copyright": "created for ss14 by ps3moira (github) based on package sprites from vgstation at https://github.com/vgstation-coders/vgstation13/pull/36993 | human by Davyei (Discord)",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
@@ -34,6 +34,10 @@
|
|||||||
{
|
{
|
||||||
"name": "tall-crate",
|
"name": "tall-crate",
|
||||||
"directions": 1
|
"directions": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "human",
|
||||||
|
"directions": 4
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user