Separate destructible component threshold into behaviors (#2818)

* WIP changes, add behaviors

* Fix behavior typing, namespace and test

* NO SPACES
This commit is contained in:
DrSmugleaf
2020-12-23 13:34:57 +01:00
committed by GitHub
parent ce029f461e
commit 764465f60c
57 changed files with 819 additions and 471 deletions

View File

@@ -2,6 +2,8 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Destructible;
using Content.Server.GameObjects.Components.Destructible.Thresholds;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior;
using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Damage;
using NUnit.Framework;
@@ -31,13 +33,17 @@ namespace Content.IntegrationTests.Tests.Destructible
20:
triggersOnce: false
50:
triggersOnce: false
behaviors:
- !type:DoActsBehavior
acts: [""Breakage""]
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
WoodPlank:
min: 1
max: 1
acts: [""Breakage""]
triggersOnce: false
- type: TestThresholdListener
";
@@ -77,7 +83,7 @@ namespace Content.IntegrationTests.Tests.Destructible
var sEntityManager = server.ResolveDependency<IEntityManager>();
var sMapManager = server.ResolveDependency<IMapManager>();
IEntity sDestructibleEntity = null;
IEntity sDestructibleEntity;
IDamageableComponent sDamageableComponent = null;
DestructibleComponent sDestructibleComponent = null;
TestThresholdListenerComponent sThresholdListenerComponent = null;
@@ -121,10 +127,7 @@ namespace Content.IntegrationTests.Tests.Destructible
var threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Acts, Is.EqualTo(0));
Assert.That(threshold.Sound, Is.Null.Or.Empty);
Assert.That(threshold.Spawn, Is.Null);
Assert.That(threshold.SoundCollection, Is.Null.Or.Empty);
Assert.That(threshold.Behaviors, Is.Empty);
Assert.That(threshold.Triggered, Is.True);
sThresholdListenerComponent.ThresholdsReached.Clear();
@@ -142,14 +145,19 @@ namespace Content.IntegrationTests.Tests.Destructible
threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Acts, Is.EqualTo((int) ThresholdActs.Breakage));
Assert.That(threshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(threshold.Spawn, Is.Not.Null);
Assert.That(threshold.Spawn.Count, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(threshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.SoundCollection, Is.Null.Or.Empty);
Assert.That(threshold.Behaviors, Has.Count.EqualTo(3));
var actsThreshold = (DoActsBehavior) threshold.Behaviors[0];
var soundThreshold = (PlaySoundBehavior) threshold.Behaviors[1];
var spawnThreshold = (SpawnEntitiesBehavior) threshold.Behaviors[2];
Assert.That(actsThreshold.Acts, Is.EqualTo(ThresholdActs.Breakage));
Assert.That(soundThreshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(spawnThreshold.Spawn, Is.Not.Null);
Assert.That(spawnThreshold.Spawn.Count, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.Triggered, Is.True);
sThresholdListenerComponent.ThresholdsReached.Clear();
@@ -192,14 +200,20 @@ namespace Content.IntegrationTests.Tests.Destructible
threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Acts, Is.EqualTo((int) ThresholdActs.Breakage));
Assert.That(threshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(threshold.Spawn, Is.Not.Null);
Assert.That(threshold.Spawn.Count, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(threshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.SoundCollection, Is.Null.Or.Empty);
Assert.That(threshold.Behaviors, Has.Count.EqualTo(3));
actsThreshold = (DoActsBehavior) threshold.Behaviors[0];
soundThreshold = (PlaySoundBehavior) threshold.Behaviors[1];
spawnThreshold = (SpawnEntitiesBehavior) threshold.Behaviors[2];
// Check that it matches the YAML prototype
Assert.That(actsThreshold.Acts, Is.EqualTo(ThresholdActs.Breakage));
Assert.That(soundThreshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(spawnThreshold.Spawn, Is.Not.Null);
Assert.That(spawnThreshold.Spawn.Count, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.Triggered, Is.True);
// Reset thresholds reached
@@ -227,11 +241,7 @@ namespace Content.IntegrationTests.Tests.Destructible
threshold = msg.Threshold;
// Check that it matches the YAML prototype
Assert.That(threshold.Acts, Is.EqualTo(0));
Assert.That(threshold.Sound, Is.Null.Or.Empty);
Assert.That(threshold.Spawn, Is.Null);
Assert.That(threshold.SoundCollection, Is.Null.Or.Empty);
Assert.That(threshold.Triggered, Is.True);
Assert.That(threshold.Behaviors, Is.Empty);
// Verify the second one, should be the highest one (50)
msg = sThresholdListenerComponent.ThresholdsReached[1];
@@ -242,15 +252,20 @@ namespace Content.IntegrationTests.Tests.Destructible
threshold = msg.Threshold;
Assert.That(threshold.Behaviors, Has.Count.EqualTo(3));
actsThreshold = (DoActsBehavior) threshold.Behaviors[0];
soundThreshold = (PlaySoundBehavior) threshold.Behaviors[1];
spawnThreshold = (SpawnEntitiesBehavior) threshold.Behaviors[2];
// Check that it matches the YAML prototype
Assert.That(threshold.Acts, Is.EqualTo((int) ThresholdActs.Breakage));
Assert.That(threshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(threshold.Spawn, Is.Not.Null);
Assert.That(threshold.Spawn.Count, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(threshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(threshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.SoundCollection, Is.Null.Or.Empty);
Assert.That(actsThreshold.Acts, Is.EqualTo(ThresholdActs.Breakage));
Assert.That(soundThreshold.Sound, Is.EqualTo("/Audio/Effects/woodhit.ogg"));
Assert.That(spawnThreshold.Spawn, Is.Not.Null);
Assert.That(spawnThreshold.Spawn.Count, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Key, Is.EqualTo("WoodPlank"));
Assert.That(spawnThreshold.Spawn.Single().Value.Min, Is.EqualTo(1));
Assert.That(spawnThreshold.Spawn.Single().Value.Max, Is.EqualTo(1));
Assert.That(threshold.Triggered, Is.True);
// Reset thresholds reached

View File

@@ -1,4 +0,0 @@
namespace Content.Server.GameObjects.Components.Destructible
{
public sealed class ActsFlags { }
}

View File

@@ -1,12 +1,11 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Destructible.Thresholds;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -19,9 +18,7 @@ namespace Content.Server.GameObjects.Components.Destructible
[RegisterComponent]
public class DestructibleComponent : Component
{
[Dependency] private readonly IRobustRandom _random = default!;
private ActSystem _actSystem = default!;
private DestructibleSystem _destructibleSystem = default!;
public override string Name => "Destructible";
@@ -47,7 +44,7 @@ namespace Content.Server.GameObjects.Components.Destructible
{
base.Initialize();
_actSystem = EntitySystem.Get<ActSystem>();
_destructibleSystem = EntitySystem.Get<DestructibleSystem>();
}
public override void HandleMessage(ComponentMessage message, IComponent? component)
@@ -83,7 +80,7 @@ namespace Content.Server.GameObjects.Components.Destructible
var thresholdMessage = new DestructibleThresholdReachedMessage(this, threshold, msg.Damageable.TotalDamage, damage);
SendMessage(thresholdMessage);
threshold.Trigger(Owner, _random, _actSystem);
threshold.Trigger(Owner, _destructibleSystem);
}
}

View File

@@ -1,4 +1,5 @@
using Robust.Shared.GameObjects;
using Content.Server.GameObjects.Components.Destructible.Thresholds;
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Destructible
{

View File

@@ -1,148 +0,0 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Stack;
using Content.Shared.Audio;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.Utility;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Destructible
{
public class Threshold : IExposeData
{
/// <summary>
/// Entities spawned on reaching this threshold, from a min to a max.
/// </summary>
[ViewVariables] public Dictionary<string, MinMax>? Spawn;
/// <summary>
/// Sound played upon destruction.
/// </summary>
[ViewVariables] public string Sound = string.Empty;
/// <summary>
/// Used instead of <see cref="Sound"/> if specified.
/// </summary>
[ViewVariables] public string SoundCollection = string.Empty;
/// <summary>
/// What acts this threshold should trigger upon activation.
/// See <see cref="ActSystem"/>.
/// </summary>
[ViewVariables] public int Acts;
/// <summary>
/// Whether or not this threshold has already been triggered.
/// </summary>
[ViewVariables] public bool Triggered;
/// <summary>
/// Whether or not this threshold only triggers once.
/// If false, it will trigger again once the entity is healed
/// and then damaged to reach this threshold once again.
/// It will not repeatedly trigger as damage rises beyond that.
/// </summary>
[ViewVariables] public bool TriggersOnce;
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref Spawn, "spawn", null);
serializer.DataField(ref Sound, "sound", string.Empty);
serializer.DataField(ref SoundCollection, "soundCollection", string.Empty);
serializer.DataField(ref Acts, "acts", 0, WithFormat.Flags<ActsFlags>());
serializer.DataField(ref Triggered, "triggered", false);
serializer.DataField(ref TriggersOnce, "triggersOnce", false);
}
/// <summary>
/// Triggers this threshold.
/// </summary>
/// <param name="owner">The entity that owns this threshold.</param>
/// <param name="random">
/// An instance of <see cref="IRobustRandom"/> to get randomness from, if relevant.
/// </param>
/// <param name="actSystem">
/// An instance of <see cref="ActSystem"/> to call acts on, if relevant.
/// </param>
public void Trigger(IEntity owner, IRobustRandom random, ActSystem actSystem)
{
Triggered = true;
PlaySound(owner);
DoSpawn(owner, random);
DoActs(owner, actSystem);
}
private void PlaySound(IEntity owner)
{
var pos = owner.Transform.Coordinates;
var actualSound = string.Empty;
if (SoundCollection != string.Empty)
{
actualSound = AudioHelpers.GetRandomFileFromSoundCollection(SoundCollection);
}
else if (Sound != string.Empty)
{
actualSound = Sound;
}
if (actualSound != string.Empty)
{
EntitySystem.Get<AudioSystem>().PlayAtCoords(actualSound, pos, AudioHelpers.WithVariation(0.125f));
}
}
private void DoSpawn(IEntity owner, IRobustRandom random)
{
if (Spawn == null)
{
return;
}
foreach (var (key, value) in Spawn)
{
var count = value.Min >= value.Max
? value.Min
: random.Next(value.Min, value.Max + 1);
if (count == 0) continue;
if (EntityPrototypeHelpers.HasComponent<StackComponent>(key))
{
var spawned = owner.EntityManager.SpawnEntity(key, owner.Transform.Coordinates);
var stack = spawned.GetComponent<StackComponent>();
stack.Count = count;
spawned.RandomOffset(0.5f);
}
else
{
for (var i = 0; i < count; i++)
{
var spawned = owner.EntityManager.SpawnEntity(key, owner.Transform.Coordinates);
spawned.RandomOffset(0.5f);
}
}
}
}
private void DoActs(IEntity owner, ActSystem acts)
{
if ((Acts & (int) ThresholdActs.Breakage) != 0)
{
acts.HandleBreakage(owner);
}
if ((Acts & (int) ThresholdActs.Destruction) != 0)
{
acts.HandleDestruction(owner);
}
}
}
}

View File

@@ -0,0 +1,4 @@
namespace Content.Server.GameObjects.Components.Destructible.Thresholds
{
public sealed class ActsFlags { }
}

View File

@@ -0,0 +1,45 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
public class DoActsBehavior : IThresholdBehavior
{
private int _acts;
/// <summary>
/// What acts should be triggered upon activation.
/// See <see cref="ActSystem"/>.
/// </summary>
public ThresholdActs Acts
{
get => (ThresholdActs) _acts;
set => _acts = (int) value;
}
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref _acts, "acts", 0, WithFormat.Flags<ActsFlags>());
}
public bool HasAct(ThresholdActs act)
{
return (_acts & (int) act) != 0;
}
public void Trigger(IEntity owner, DestructibleSystem system)
{
if (HasAct(ThresholdActs.Breakage))
{
system.ActSystem.HandleBreakage(owner);
}
if (HasAct(ThresholdActs.Destruction))
{
system.ActSystem.HandleDestruction(owner);
}
}
}
}

View File

@@ -0,0 +1,11 @@
using Content.Server.GameObjects.EntitySystems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
public interface IThresholdBehavior : IExposeData
{
void Trigger(IEntity owner, DestructibleSystem system);
}
}

View File

@@ -0,0 +1,32 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Audio;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
public class PlaySoundBehavior : IThresholdBehavior
{
/// <summary>
/// Sound played upon destruction.
/// </summary>
public string Sound { get; set; }
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.Sound, "sound", string.Empty);
}
public void Trigger(IEntity owner, DestructibleSystem system)
{
if (string.IsNullOrEmpty(Sound))
{
return;
}
var pos = owner.Transform.Coordinates;
system.AudioSystem.PlayAtCoords(Sound, pos, AudioHelpers.WithVariation(0.125f));
}
}
}

View File

@@ -0,0 +1,33 @@
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Audio;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
public class PlaySoundCollectionBehavior : IThresholdBehavior
{
/// <summary>
/// Sound collection from which to pick a random sound to play.
/// </summary>
private string SoundCollection { get; set; }
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.SoundCollection, "soundCollection", string.Empty);
}
public void Trigger(IEntity owner, DestructibleSystem system)
{
if (string.IsNullOrEmpty(SoundCollection))
{
return;
}
var sound = AudioHelpers.GetRandomFileFromSoundCollection(SoundCollection);
var pos = owner.Transform.Coordinates;
system.AudioSystem.PlayAtCoords(sound, pos, AudioHelpers.WithVariation(0.125f));
}
}
}

View File

@@ -0,0 +1,51 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Stack;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Utility;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior
{
public class SpawnEntitiesBehavior : IThresholdBehavior
{
/// <summary>
/// Entities spawned on reaching this threshold, from a min to a max.
/// </summary>
public Dictionary<string, MinMax> Spawn { get; set; } = new();
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(this, x => x.Spawn, "spawn", new Dictionary<string, MinMax>());
}
public void Trigger(IEntity owner, DestructibleSystem system)
{
foreach (var (entityId, minMax) in Spawn)
{
var count = minMax.Min >= minMax.Max
? minMax.Min
: system.Random.Next(minMax.Min, minMax.Max + 1);
if (count == 0) continue;
if (EntityPrototypeHelpers.HasComponent<StackComponent>(entityId))
{
var spawned = owner.EntityManager.SpawnEntity(entityId, owner.Transform.Coordinates);
var stack = spawned.GetComponent<StackComponent>();
stack.Count = count;
spawned.RandomOffset(0.5f);
}
else
{
for (var i = 0; i < count; i++)
{
var spawned = owner.EntityManager.SpawnEntity(entityId, owner.Transform.Coordinates);
spawned.RandomOffset(0.5f);
}
}
}
}
}
}

View File

@@ -2,7 +2,7 @@
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Destructible
namespace Content.Server.GameObjects.Components.Destructible.Thresholds
{
public struct MinMax : IExposeData
{

View File

@@ -0,0 +1,57 @@
#nullable enable
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Destructible.Thresholds.Behavior;
using Content.Server.GameObjects.EntitySystems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Destructible.Thresholds
{
public class Threshold : IExposeData
{
/// <summary>
/// Whether or not this threshold has already been triggered.
/// </summary>
[ViewVariables] public bool Triggered;
/// <summary>
/// Whether or not this threshold only triggers once.
/// If false, it will trigger again once the entity is healed
/// and then damaged to reach this threshold once again.
/// It will not repeatedly trigger as damage rises beyond that.
/// </summary>
[ViewVariables] public bool TriggersOnce;
/// <summary>
/// Behaviors to activate once this threshold is triggered.
/// </summary>
[ViewVariables] public List<IThresholdBehavior> Behaviors = new();
public void ExposeData(ObjectSerializer serializer)
{
serializer.DataField(ref Triggered, "triggered", false);
serializer.DataField(ref TriggersOnce, "triggersOnce", false);
serializer.DataField(ref Behaviors, "behaviors", new List<IThresholdBehavior>());
}
/// <summary>
/// Triggers this threshold.
/// </summary>
/// <param name="owner">The entity that owns this threshold.</param>
/// <param name="system">
/// An instance of <see cref="DestructibleSystem"/> to get dependency and
/// system references from, if relevant.
/// </param>
public void Trigger(IEntity owner, DestructibleSystem system)
{
Triggered = true;
foreach (var behavior in Behaviors)
{
behavior.Trigger(owner, system);
}
}
}
}

View File

@@ -1,13 +1,13 @@
using System;
using Robust.Shared.Serialization;
namespace Content.Server.GameObjects.Components.Destructible
namespace Content.Server.GameObjects.Components.Destructible.Thresholds
{
[Flags, FlagsFor(typeof(ActsFlags))]
[Serializable]
public enum ThresholdActs
{
Invalid = 0,
None = 0,
Breakage,
Destruction
}

View File

@@ -0,0 +1,26 @@
using Content.Shared.GameObjects.EntitySystems;
using JetBrains.Annotations;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
namespace Content.Server.GameObjects.EntitySystems
{
[UsedImplicitly]
public class DestructibleSystem : EntitySystem
{
[Dependency] public readonly IRobustRandom Random = default!;
public AudioSystem AudioSystem { get; private set; }
public ActSystem ActSystem { get; private set; }
public override void Initialize()
{
base.Initialize();
AudioSystem = Get<AudioSystem>();
ActSystem = Get<ActSystem>();
}
}
}

View File

@@ -61,6 +61,8 @@
- type: Destructible
thresholds:
500:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
placement:
mode: SnapgridCenter

View File

@@ -32,6 +32,8 @@
- type: Destructible
thresholds:
75:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
placement:
mode: SnapgridCenter

View File

@@ -24,12 +24,16 @@
- type: Destructible
thresholds:
30:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
WoodPlank:
min: 1
max: 1
acts: ["Destruction"]
- type: Occluder
sizeX: 32
sizeY: 32

View File

@@ -25,6 +25,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: UserInterface
interfaces:

View File

@@ -16,6 +16,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: ShuttleController
- type: Strap

View File

@@ -35,6 +35,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: entity

View File

@@ -32,12 +32,16 @@
- type: Destructible
thresholds:
30:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: entity
id: Shelf
@@ -73,9 +77,13 @@
- type: Destructible
thresholds:
30:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]

View File

@@ -40,12 +40,16 @@
- type: Destructible
thresholds:
15:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: entity
id: TableFrame
@@ -62,12 +66,16 @@
- type: Destructible
thresholds:
1:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: TableFrame
@@ -87,12 +95,16 @@
- type: Destructible
thresholds:
1:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: entity
id: TableMetal
@@ -109,12 +121,16 @@
- type: Destructible
thresholds:
15:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: MetalTable
@@ -134,12 +150,16 @@
- type: Destructible
thresholds:
75:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: ReinforcedTable
@@ -159,12 +179,16 @@
- type: Destructible
thresholds:
5:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/glass_break2.ogg
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: GlassTable
@@ -184,12 +208,16 @@
- type: Destructible
thresholds:
20:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/glass_break2.ogg
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: RGlassTable
@@ -209,12 +237,16 @@
- type: Destructible
thresholds:
15:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
WoodPlank:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: WoodTable
@@ -234,12 +266,16 @@
- type: Destructible
thresholds:
15:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/woodhit.ogg
- !type:SpawnEntitiesBehavior
spawn:
WoodPlank:
min: 1
max: 1
acts: ["Destruction"]
- type: Construction
graph: Tables
node: PokerTable
@@ -259,8 +295,11 @@
- type: Destructible
thresholds:
50:
sound: /Audio/Effects/picaxe2.ogg
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/picaxe2.ogg
- type: entity
id: TableDebug
@@ -277,4 +316,6 @@
- type: Destructible
thresholds:
1:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]

View File

@@ -14,6 +14,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: GasCanisterPort

View File

@@ -14,6 +14,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: GasCanister
- type: Anchorable

View File

@@ -24,5 +24,7 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: KitchenSpike

View File

@@ -15,6 +15,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Sprite
- type: Appearance

View File

@@ -14,6 +14,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Sprite
sprite: Constructible/Atmos/pump.rsi

View File

@@ -24,6 +24,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: entity

View File

@@ -24,6 +24,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: entity

View File

@@ -35,6 +35,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:

View File

@@ -99,6 +99,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: BreakableConstruction
node: monitorBroken

View File

@@ -32,6 +32,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Breakage"]
- type: Anchorable

View File

@@ -36,6 +36,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:

View File

@@ -239,6 +239,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Breakage"]
- type: Anchorable
- type: Pullable

View File

@@ -33,6 +33,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Breakage"]
- type: UserInterface
interfaces:

View File

@@ -23,6 +23,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: SubFloorHide
@@ -52,11 +54,14 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
HVWireStack1:
min: 1
max: 1
acts: ["Destruction"]
- type: entity
parent: WireBase
@@ -86,11 +91,14 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
MVWireStack1:
min: 1
max: 1
acts: ["Destruction"]
- type: entity
parent: WireBase
@@ -122,8 +130,11 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
ApcExtensionCableStack1:
min: 1
max: 1
acts: ["Destruction"]

View File

@@ -26,6 +26,8 @@
- type: Destructible
thresholds:
500:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: SnapGrid
offset: Center

View File

@@ -26,10 +26,13 @@
- type: Destructible
thresholds:
500:
behaviors:
- !type:SpawnEntitiesBehavior
spawn:
AMEPart:
min: 1
max: 1
- !type:DoActsBehavior
acts: ["Destruction"]
- type: SnapGrid
offset: Center

View File

@@ -22,6 +22,8 @@
- type: Destructible
thresholds:
75:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Anchorable
- type: Pullable

View File

@@ -36,11 +36,14 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
chem_master_broken:
min: 1
max: 1
acts: ["Destruction"]
- type: UserInterface
interfaces:
- key: enum.ChemMasterUiKey.Key
@@ -82,11 +85,14 @@
- type: Destructible
thresholds:
25:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: UserInterface
interfaces:
- key: enum.ChemMasterUiKey.Key

View File

@@ -18,6 +18,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Breakage"]
- type: Rotatable
- type: Pullable
@@ -150,6 +152,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:
@@ -389,6 +393,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:

View File

@@ -34,6 +34,8 @@
- type: Destructible
thresholds:
150:
behaviors:
- !type:DoActsBehavior
acts: ["Breakage"]
- type: GravityGenerator
- type: UserInterface

View File

@@ -28,6 +28,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Sprite
sprite: Constructible/Hydroponics/hydro_tools.rsi

View File

@@ -43,6 +43,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:

View File

@@ -40,6 +40,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:

View File

@@ -28,6 +28,8 @@
- type: Destructible
thresholds:
10:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: SolutionContainer
maxVol: 1500

View File

@@ -19,6 +19,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Occluder
sizeX: 32

View File

@@ -30,11 +30,14 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
acts: ["Destruction"]
- type: SnapGrid
offset: Edge
placement:

View File

@@ -41,6 +41,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: entity
@@ -68,6 +70,8 @@
- type: Destructible
thresholds:
25:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: entity
@@ -87,4 +91,6 @@
- type: Destructible
thresholds:
25:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]

View File

@@ -30,6 +30,8 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: BreakableConstruction
node: start

View File

@@ -13,6 +13,8 @@
- type: Destructible
thresholds:
5:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Sprite
drawdepth: WallTops

View File

@@ -49,11 +49,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: [ "Destruction" ]
- type: IconSmooth
key: walls
base: brick
@@ -72,11 +75,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: clock
@@ -95,11 +101,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: clown
@@ -119,11 +128,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: cult
@@ -142,11 +154,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: debug
@@ -165,11 +180,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: diamond
@@ -189,11 +207,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: gold
@@ -212,11 +233,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: ice
@@ -235,11 +259,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: metal
@@ -258,11 +285,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: plasma
@@ -281,11 +311,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: plastic
@@ -309,6 +342,8 @@
- type: Destructible
thresholds:
600:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: BreakableConstruction
node: girder
@@ -335,11 +370,14 @@
- type: Destructible
thresholds:
1000:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: riveted
@@ -358,11 +396,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: sandstone
@@ -381,11 +422,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: silver
@@ -408,6 +452,8 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: BreakableConstruction
node: girder
@@ -430,11 +476,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: uranium
@@ -453,11 +502,14 @@
- type: Destructible
thresholds:
300:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:SpawnEntitiesBehavior
spawn:
Girder:
min: 1
max: 1
acts: ["Destruction"]
- type: IconSmooth
key: walls
base: wood

View File

@@ -31,12 +31,16 @@
- type: Destructible
thresholds:
15:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundCollectionBehavior
soundCollection: WindowBreak
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 2
acts: ["Destruction"]
- type: SnapGrid
offset: Center
- type: Airtight
@@ -65,12 +69,16 @@
- type: Destructible
thresholds:
75:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundCollectionBehavior
soundCollection: WindowBreak
- !type:SpawnEntitiesBehavior
spawn:
ShardGlassReinforced:
min: 1
max: 2
acts: ["Destruction"]
- type: Window
base: rwindow
maxDamage: 75
@@ -93,12 +101,16 @@
- type: Destructible
thresholds:
100:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundCollectionBehavior
soundCollection: WindowBreak
- !type:SpawnEntitiesBehavior
spawn:
ShardGlassPhoron:
min: 1
max: 2
acts: ["Destruction"]
resistances: metallicResistances
- type: Window
base: pwindow

View File

@@ -28,8 +28,12 @@
- type: Destructible
thresholds:
5:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundCollectionBehavior
soundCollection: WindowBreak
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1

View File

@@ -132,12 +132,16 @@
- type: Destructible
thresholds:
10:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/glass_break1.ogg
- !type:SpawnEntitiesBehavior
spawn:
FloodlightBroken:
min: 1
max: 1
acts: ["Destruction"]
- type: Appearance
visuals:
- type: FlashLightVisualizer
@@ -157,12 +161,16 @@
- type: Destructible
thresholds:
20:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound: /Audio/Effects/metalbreak.ogg
- !type:SpawnEntitiesBehavior
spawn:
SteelSheet1:
min: 1
max: 1
sound: /Audio/Effects/metalbreak.ogg
acts: ["Destruction"]
- type: Physics
shapes:
- !type:PhysShapeAabb

View File

@@ -26,6 +26,8 @@
- type: Destructible
thresholds:
10:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:
@@ -56,6 +58,8 @@
- type: Destructible
thresholds:
10:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:
@@ -86,6 +90,8 @@
- type: Destructible
thresholds:
10:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals:
@@ -115,6 +121,8 @@
- type: Destructible
thresholds:
50:
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- type: Appearance
visuals: