C4 (#7486)
This commit is contained in:
@@ -201,6 +201,7 @@ namespace Content.Client.Entry
|
|||||||
"GasAnalyzable",
|
"GasAnalyzable",
|
||||||
"GasCanister",
|
"GasCanister",
|
||||||
"GasPort",
|
"GasPort",
|
||||||
|
"Sticky",
|
||||||
"GasPortable",
|
"GasPortable",
|
||||||
"AtmosPipeColor",
|
"AtmosPipeColor",
|
||||||
"AtmosUnsafeUnanchor",
|
"AtmosUnsafeUnanchor",
|
||||||
|
|||||||
36
Content.Client/Sticky/Visualizers/StickyVisualizerSystem.cs
Normal file
36
Content.Client/Sticky/Visualizers/StickyVisualizerSystem.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Shared.Sticky.Components;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Client.Sticky.Visualizers;
|
||||||
|
|
||||||
|
public sealed class StickyVisualizerSystem : VisualizerSystem<StickyVisualizerComponent>
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<StickyVisualizerComponent, ComponentInit>(OnInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, StickyVisualizerComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
if (!TryComp(uid, out SpriteComponent? sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.DefaultDrawDepth = sprite.DrawDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAppearanceChange(EntityUid uid, StickyVisualizerComponent component, ref AppearanceChangeEvent args)
|
||||||
|
{
|
||||||
|
base.OnAppearanceChange(uid, component, ref args);
|
||||||
|
|
||||||
|
if (!TryComp(uid, out SpriteComponent? sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!args.Component.TryGetData(StickyVisuals.IsStuck, out bool isStuck))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var drawDepth = isStuck ? component.StuckDrawDepth : component.DefaultDrawDepth;
|
||||||
|
sprite.DrawDepth = drawDepth;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,5 +32,12 @@ namespace Content.Server.Explosion.Components
|
|||||||
|
|
||||||
[DataField("beepParams")]
|
[DataField("beepParams")]
|
||||||
public AudioParams BeepParams = AudioParams.Default.WithVolume(-2f);
|
public AudioParams BeepParams = AudioParams.Default.WithVolume(-2f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should timer be started when it was stuck to another entity.
|
||||||
|
/// Used for C4 charges and similar behaviour.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("startOnStick")]
|
||||||
|
public bool StartOnStick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Explosion.Components;
|
using Content.Server.Explosion.Components;
|
||||||
|
using Content.Server.Sticky.Events;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
@@ -16,6 +17,22 @@ public sealed partial class TriggerSystem
|
|||||||
SubscribeLocalEvent<OnUseTimerTriggerComponent, UseInHandEvent>(OnTimerUse);
|
SubscribeLocalEvent<OnUseTimerTriggerComponent, UseInHandEvent>(OnTimerUse);
|
||||||
SubscribeLocalEvent<OnUseTimerTriggerComponent, ExaminedEvent>(OnExamined);
|
SubscribeLocalEvent<OnUseTimerTriggerComponent, ExaminedEvent>(OnExamined);
|
||||||
SubscribeLocalEvent<OnUseTimerTriggerComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAltVerbs);
|
SubscribeLocalEvent<OnUseTimerTriggerComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAltVerbs);
|
||||||
|
SubscribeLocalEvent<OnUseTimerTriggerComponent, EntityStuckEvent>(OnStuck);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStuck(EntityUid uid, OnUseTimerTriggerComponent component, EntityStuckEvent args)
|
||||||
|
{
|
||||||
|
if (!component.StartOnStick)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HandleTimerTrigger(
|
||||||
|
uid,
|
||||||
|
args.User,
|
||||||
|
component.Delay,
|
||||||
|
component.BeepInterval,
|
||||||
|
component.InitialBeepDelay,
|
||||||
|
component.BeepSound,
|
||||||
|
component.BeepParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamined(EntityUid uid, OnUseTimerTriggerComponent component, ExaminedEvent args)
|
private void OnExamined(EntityUid uid, OnUseTimerTriggerComponent component, ExaminedEvent args)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Doors.Systems;
|
|||||||
using Content.Server.Explosion.Components;
|
using Content.Server.Explosion.Components;
|
||||||
using Content.Server.Flash;
|
using Content.Server.Flash;
|
||||||
using Content.Server.Flash.Components;
|
using Content.Server.Flash.Components;
|
||||||
|
using Content.Server.Sticky.Events;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
|
|||||||
76
Content.Server/Sticky/Components/StickyComponent.cs
Normal file
76
Content.Server/Sticky/Components/StickyComponent.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using Content.Shared.Whitelist;
|
||||||
|
|
||||||
|
namespace Content.Server.Sticky.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Items that can be stick to other structures or entities.
|
||||||
|
/// For example paper stickers or C4 charges.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class StickyComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// What target entities are valid to be surface for sticky entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("whitelist")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public EntityWhitelist? Whitelist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much time does it take to stick entity to target.
|
||||||
|
/// If zero will stick entity immediately.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("stickDelay")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan StickDelay = TimeSpan.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether users can unstick item when it was stuck to surface.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("canUnstick")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool CanUnstick = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much time does it take to unstick entity.
|
||||||
|
/// If zero will unstick entity immediately.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("unstickDelay")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan UnstickDelay = TimeSpan.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup message shown when player started sticking entity to another entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("stickPopupStart")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string? StickPopupStart;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup message shown when player successfully stuck entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("stickPopupSuccess")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string? StickPopupSuccess;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup message shown when player started unsticking entity from another entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("unstickPopupStart")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string? UnstickPopupStart;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Popup message shown when player successfully unstuck entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("unstickPopupSuccess")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string? UnstickPopupSuccess;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that is used as surface for sticky entity.
|
||||||
|
/// Null if entity doesn't stuck to anything.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
public EntityUid? StuckTo;
|
||||||
|
}
|
||||||
45
Content.Server/Sticky/Events/EntityStuckEvent.cs
Normal file
45
Content.Server/Sticky/Events/EntityStuckEvent.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
namespace Content.Server.Sticky.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Risen on sticky entity when it was stuck to other entity.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EntityStuckEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that was used as a surface for sticky object.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid Target;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that stuck sticky object on target.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid User;
|
||||||
|
|
||||||
|
public EntityStuckEvent(EntityUid target, EntityUid user)
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
User = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Risen on sticky entity when it was unstuck from other entity.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EntityUnstuckEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that was used as a surface for sticky object.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid Target;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that unstuck sticky object on target.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid User;
|
||||||
|
|
||||||
|
public EntityUnstuckEvent(EntityUid target, EntityUid user)
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
User = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
231
Content.Server/Sticky/Systems/StickySystem.cs
Normal file
231
Content.Server/Sticky/Systems/StickySystem.cs
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
using Content.Server.DoAfter;
|
||||||
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.Sticky.Components;
|
||||||
|
using Content.Server.Sticky.Events;
|
||||||
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Sticky.Components;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
|
namespace Content.Server.Sticky.Systems;
|
||||||
|
|
||||||
|
public sealed class StickySystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||||
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
|
|
||||||
|
private const string StickerSlotId = "stickers_container";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<StickSuccessfulEvent>(OnStickSuccessful);
|
||||||
|
SubscribeLocalEvent<UnstickSuccessfulEvent>(OnUnstickSuccessful);
|
||||||
|
SubscribeLocalEvent<StickyComponent, AfterInteractEvent>(OnAfterInteract);
|
||||||
|
SubscribeLocalEvent<StickyComponent, GetVerbsEvent<Verb>>(AddUnstickVerb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAfterInteract(EntityUid uid, StickyComponent component, AfterInteractEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled || !args.CanReach || args.Target == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// try stick object to a clicked target entity
|
||||||
|
args.Handled = StartSticking(uid, args.User, args.Target.Value, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddUnstickVerb(EntityUid uid, StickyComponent component, GetVerbsEvent<Verb> args)
|
||||||
|
{
|
||||||
|
if (component.StuckTo == null || !component.CanUnstick)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Verbs.Add(new Verb
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("comp-sticky-unstick-verb-text"),
|
||||||
|
IconTexture = "/Textures/Interface/VerbIcons/eject.svg.192dpi.png",
|
||||||
|
Act = () => StartUnsticking(uid, args.User, component)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool StartSticking(EntityUid uid, EntityUid user, EntityUid target, StickyComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return false;
|
||||||
|
if (component.Whitelist != null && !component.Whitelist.IsValid(target))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check if delay is not zero to start do after
|
||||||
|
var delay = (float) component.StickDelay.TotalSeconds;
|
||||||
|
if (delay > 0)
|
||||||
|
{
|
||||||
|
// show message to user
|
||||||
|
if (component.StickPopupStart != null)
|
||||||
|
{
|
||||||
|
var msg = Loc.GetString(component.StickPopupStart);
|
||||||
|
_popupSystem.PopupEntity(msg, user, Filter.Entities(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
// start sticking object to target
|
||||||
|
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: target)
|
||||||
|
{
|
||||||
|
BroadcastFinishedEvent = new StickSuccessfulEvent(uid, user, target),
|
||||||
|
BreakOnStun = true,
|
||||||
|
BreakOnTargetMove = true,
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
NeedHand = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if delay is zero - stick entity immediately
|
||||||
|
StickToEntity(uid, target, user, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStickSuccessful(StickSuccessfulEvent ev)
|
||||||
|
{
|
||||||
|
// check if entity still has sticky component
|
||||||
|
if (!TryComp(ev.Uid, out StickyComponent? component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
StickToEntity(ev.Uid, ev.Target, ev.User, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartUnsticking(EntityUid uid, EntityUid user, StickyComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var delay = (float) component.UnstickDelay.TotalSeconds;
|
||||||
|
if (delay > 0)
|
||||||
|
{
|
||||||
|
// show message to user
|
||||||
|
if (component.UnstickPopupStart != null)
|
||||||
|
{
|
||||||
|
var msg = Loc.GetString(component.UnstickPopupStart);
|
||||||
|
_popupSystem.PopupEntity(msg, user, Filter.Entities(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
// start unsticking object
|
||||||
|
_doAfterSystem.DoAfter(new DoAfterEventArgs(user, delay, target: uid)
|
||||||
|
{
|
||||||
|
BroadcastFinishedEvent = new UnstickSuccessfulEvent(uid, user),
|
||||||
|
BreakOnStun = true,
|
||||||
|
BreakOnTargetMove = true,
|
||||||
|
BreakOnUserMove = true,
|
||||||
|
NeedHand = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if delay is zero - unstick entity immediately
|
||||||
|
UnstickFromEntity(uid, user, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnstickSuccessful(UnstickSuccessfulEvent ev)
|
||||||
|
{
|
||||||
|
// check if entity still has sticky component
|
||||||
|
if (!TryComp(ev.Uid, out StickyComponent? component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
UnstickFromEntity(ev.Uid, ev.User, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StickToEntity(EntityUid uid, EntityUid target, EntityUid user, StickyComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add container to entity and insert sticker into it
|
||||||
|
var container = _containerSystem.EnsureContainer<Container>(target, StickerSlotId);
|
||||||
|
container.ShowContents = true;
|
||||||
|
if (!container.Insert(uid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// show message to user
|
||||||
|
if (component.StickPopupSuccess != null)
|
||||||
|
{
|
||||||
|
var msg = Loc.GetString(component.StickPopupSuccess);
|
||||||
|
_popupSystem.PopupEntity(msg, user, Filter.Entities(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
// send information to appearance that entity is stuck
|
||||||
|
if (TryComp(uid, out AppearanceComponent? appearance))
|
||||||
|
{
|
||||||
|
appearance.SetData(StickyVisuals.IsStuck, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
component.StuckTo = target;
|
||||||
|
RaiseLocalEvent(uid, new EntityStuckEvent(target, user));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnstickFromEntity(EntityUid uid, EntityUid user, StickyComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return;
|
||||||
|
if (component.StuckTo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// try to remove sticky item from target container
|
||||||
|
var target = component.StuckTo.Value;
|
||||||
|
if (!_containerSystem.TryGetContainer(target, StickerSlotId, out var container) || !container.Remove(uid))
|
||||||
|
return;
|
||||||
|
// delete container if it's now empty
|
||||||
|
if (container.ContainedEntities.Count == 0)
|
||||||
|
container.Shutdown();
|
||||||
|
|
||||||
|
// try place dropped entity into user hands
|
||||||
|
_handsSystem.PickupOrDrop(user, uid);
|
||||||
|
|
||||||
|
// send information to appearance that entity isn't stuck
|
||||||
|
if (TryComp(uid, out AppearanceComponent? appearance))
|
||||||
|
{
|
||||||
|
appearance.SetData(StickyVisuals.IsStuck, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show message to user
|
||||||
|
if (component.UnstickPopupSuccess != null)
|
||||||
|
{
|
||||||
|
var msg = Loc.GetString(component.UnstickPopupSuccess);
|
||||||
|
_popupSystem.PopupEntity(msg, user, Filter.Entities(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
component.StuckTo = null;
|
||||||
|
RaiseLocalEvent(uid, new EntityUnstuckEvent(target, user));
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class StickSuccessfulEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public readonly EntityUid Uid;
|
||||||
|
public readonly EntityUid User;
|
||||||
|
public readonly EntityUid Target;
|
||||||
|
|
||||||
|
public StickSuccessfulEvent(EntityUid uid, EntityUid user, EntityUid target)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
User = user;
|
||||||
|
Target = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class UnstickSuccessfulEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public readonly EntityUid Uid;
|
||||||
|
public readonly EntityUid User;
|
||||||
|
|
||||||
|
public UnstickSuccessfulEvent(EntityUid uid, EntityUid user)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
User = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Sticky.Components;
|
||||||
|
using DrawDepth;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class StickyVisualizerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// What sprite draw depth set when entity stuck.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("stuckDrawDepth")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int StuckDrawDepth = (int) DrawDepth.Overdoors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// What sprite draw depth set when entity unstuck.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int DefaultDrawDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum StickyVisuals : byte
|
||||||
|
{
|
||||||
|
IsStuck
|
||||||
|
}
|
||||||
9
Resources/Locale/en-US/sticky/sticky-component.ftl
Normal file
9
Resources/Locale/en-US/sticky/sticky-component.ftl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Bomb planting strings
|
||||||
|
|
||||||
|
comp-sticky-start-stick-bomb = You start planting the bomb...
|
||||||
|
comp-sticky-success-stick-bomb = You planted the bomb
|
||||||
|
comp-sticky-start-unstick-bomb = You start carefully removing the bomb...
|
||||||
|
comp-sticky-success-unstick-bomb = You removed the bomb
|
||||||
|
|
||||||
|
# General strings
|
||||||
|
comp-sticky-unstick-verb-text = Unstick
|
||||||
@@ -169,6 +169,17 @@
|
|||||||
- id: PlushieNuke
|
- id: PlushieNuke
|
||||||
- id: PlushieLizard
|
- id: PlushieLizard
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingBackpackDuffelSyndicate
|
||||||
|
id: ClothingBackpackDuffelSyndicateC4tBundle
|
||||||
|
name: syndicate C-4 bundle
|
||||||
|
description: "Contains a lot of C-4 charges."
|
||||||
|
components:
|
||||||
|
- type: StorageFill
|
||||||
|
contents:
|
||||||
|
- id: C4
|
||||||
|
amount: 8
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingBackpackDuffelSyndicate
|
parent: ClothingBackpackDuffelSyndicate
|
||||||
id: ClothingBackpackDuffelSyndicateHardsuitBundle
|
id: ClothingBackpackDuffelSyndicateHardsuitBundle
|
||||||
|
|||||||
@@ -90,17 +90,21 @@
|
|||||||
itemId: MobGrenadePenguin
|
itemId: MobGrenadePenguin
|
||||||
price: 6
|
price: 6
|
||||||
|
|
||||||
#- type: uplinkListing
|
- type: uplinkListing
|
||||||
# id: UplinkExplosiveC4
|
id: UplinkC4
|
||||||
# category: Weapons
|
category: Explosives
|
||||||
# itemId: ExplosiveC4
|
itemId: C4
|
||||||
# price: 5
|
price: 2
|
||||||
|
description: >
|
||||||
|
C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, airlocks or sabotage equipment.
|
||||||
|
It can be attached to almost all objects and has a modifiable timer with a minimum setting of 10 seconds.
|
||||||
|
|
||||||
#- type: uplinkListing
|
- type: uplinkListing
|
||||||
# id: UplinkDuffelExplosiveC4
|
id: UplinkC4Bundle
|
||||||
# category: Weapons
|
category: Explosives
|
||||||
# itemId: DuffelExplosiveC4
|
itemId: ClothingBackpackDuffelSyndicateC4tBundle
|
||||||
# price: 15
|
price: 12 # 25% off
|
||||||
|
description: Because sometimes quantity is quality. Contains 8 C-4 plastic explosives.
|
||||||
|
|
||||||
# Ammo
|
# Ammo
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
- type: entity
|
||||||
|
name: composition C-4
|
||||||
|
description: Used to put holes in specific areas without too much extra hole. A saboteur's favorite.
|
||||||
|
parent: BaseItem
|
||||||
|
id: C4
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Weapons/Bombs/c4.rsi
|
||||||
|
state: icon
|
||||||
|
- type: Item
|
||||||
|
sprite: Objects/Weapons/Bombs/c4.rsi
|
||||||
|
size: 10
|
||||||
|
- type: OnUseTimerTrigger
|
||||||
|
delay: 10
|
||||||
|
delayOptions: [10, 30, 60, 120, 300]
|
||||||
|
initialBeepDelay: 0
|
||||||
|
beepSound: /Audio/Machines/Nuke/general_beep.ogg
|
||||||
|
startOnStick: true
|
||||||
|
- type: Sticky
|
||||||
|
stickDelay: 5
|
||||||
|
unstickDelay: 5
|
||||||
|
stickPopupStart: comp-sticky-start-stick-bomb
|
||||||
|
stickPopupSuccess: comp-sticky-success-stick-bomb
|
||||||
|
unstickPopupStart: comp-sticky-start-unstick-bomb
|
||||||
|
unstickPopupSuccess: comp-sticky-success-unstick-bomb
|
||||||
|
- type: Explosive # Powerful explosion in a very small radius. Doesn't break underplating.
|
||||||
|
explosionType: Default
|
||||||
|
maxIntensity: 300
|
||||||
|
intensitySlope: 100
|
||||||
|
totalIntensity: 300
|
||||||
|
canCreateVacuum: false
|
||||||
|
- type: ExplodeOnTrigger
|
||||||
|
- type: Damageable
|
||||||
|
damageContainer: Inorganic
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 10
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: ["Destruction"]
|
||||||
|
- type: StickyVisualizer
|
||||||
|
- type: Appearance
|
||||||
|
visuals:
|
||||||
|
- type: GenericEnumVisualizer
|
||||||
|
key: enum.Trigger.TriggerVisuals.VisualState
|
||||||
|
states:
|
||||||
|
enum.Trigger.TriggerVisualState.Primed: primed
|
||||||
|
enum.Trigger.TriggerVisualState.Unprimed: complete
|
||||||
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/icon.png
Normal file
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 497 B |
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/inhand-left.png
Normal file
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/inhand-left.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 377 B |
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/inhand-right.png
Normal file
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/inhand-right.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 413 B |
31
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/meta.json
Normal file
31
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/meta.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/b13d244d761a07e200a9a41730bd446e776020d5",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "primed",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/primed.png
Normal file
BIN
Resources/Textures/Objects/Weapons/Bombs/c4.rsi/primed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 552 B |
Reference in New Issue
Block a user