Refactors radiation (#2009)

* Work on refactoring radiation.

* mmmm grayons

* fixes

* Now you can specify whether the pulse will decay or not

* whoops

* Move IRadiationAct to shared, make DamageableComponent implement it instead and add metallic resistances to walls

* General improvements, send draw and decay with state. Rename DPS to RadsPerSecond

* E N T I T Y  C O O R D I N A T E S

* Entity coordinates goood

* Remove unused using statements

* resistances: metallicResistances

* - type: Breakable moment

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
This commit is contained in:
Víctor Aguilera Puerto
2020-09-21 01:49:40 +02:00
committed by GitHub
parent 2927ab5cd1
commit 6ec2939f15
37 changed files with 250 additions and 123 deletions

View File

@@ -6,19 +6,35 @@ using Robust.Shared.GameObjects;
namespace Content.Client.GameObjects.Components.StationEvents namespace Content.Client.GameObjects.Components.StationEvents
{ {
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedRadiationPulseComponent))]
public sealed class RadiationPulseComponent : SharedRadiationPulseComponent public sealed class RadiationPulseComponent : SharedRadiationPulseComponent
{ {
public TimeSpan EndTime { get; private set; } private bool _draw;
private bool _decay;
private float _radsPerSecond;
private float _range;
private TimeSpan _endTime;
public override float RadsPerSecond => _radsPerSecond;
public override float Range => _range;
public override TimeSpan EndTime => _endTime;
public override bool Draw => _draw;
public override bool Decay => _decay;
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{ {
base.HandleComponentState(curState, nextState); base.HandleComponentState(curState, nextState);
if (!(curState is RadiationPulseMessage state))
if (!(curState is RadiationPulseState state))
{ {
return; return;
} }
EndTime = state.EndTime; _radsPerSecond = state.RadsPerSecond;
_range = state.Range;
_draw = state.Draw;
_decay = state.Decay;
_endTime = state.EndTime;
} }
} }
} }

View File

@@ -25,16 +25,16 @@ namespace Content.Client.StationEvents
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IEyeManager _eyeManager = default!;
/// <summary> /// <summary>
/// Current color of a pulse /// Current color of a pulse
/// </summary> /// </summary>
private readonly Dictionary<IEntity, Color> _colors = new Dictionary<IEntity, Color>(); private readonly Dictionary<IEntity, Color> _colors = new Dictionary<IEntity, Color>();
/// <summary> /// <summary>
/// Whether our alpha is increasing or decreasing and at what time does it flip (or stop) /// Whether our alpha is increasing or decreasing and at what time does it flip (or stop)
/// </summary> /// </summary>
private readonly Dictionary<IEntity, (bool EasingIn, TimeSpan TransitionTime)> _transitions = private readonly Dictionary<IEntity, (bool EasingIn, TimeSpan TransitionTime)> _transitions =
new Dictionary<IEntity, (bool EasingIn, TimeSpan TransitionTime)>(); new Dictionary<IEntity, (bool EasingIn, TimeSpan TransitionTime)>();
/// <summary> /// <summary>
@@ -43,7 +43,7 @@ namespace Content.Client.StationEvents
private readonly Dictionary<IEntity, float> _alphaRateOfChange = new Dictionary<IEntity, float>(); private readonly Dictionary<IEntity, float> _alphaRateOfChange = new Dictionary<IEntity, float>();
private TimeSpan _lastTick; private TimeSpan _lastTick;
// TODO: When worldHandle can do DrawCircle change this. // TODO: When worldHandle can do DrawCircle change this.
public override OverlaySpace Space => OverlaySpace.ScreenSpace; public override OverlaySpace Space => OverlaySpace.ScreenSpace;
@@ -64,7 +64,7 @@ namespace Content.Client.StationEvents
private Color GetColor(IEntity entity, float elapsedTime, TimeSpan endTime) private Color GetColor(IEntity entity, float elapsedTime, TimeSpan endTime)
{ {
var currentTime = _gameTiming.CurTime; var currentTime = _gameTiming.CurTime;
// New pulse // New pulse
if (!_colors.ContainsKey(entity)) if (!_colors.ContainsKey(entity))
{ {
@@ -92,7 +92,7 @@ namespace Content.Client.StationEvents
{ {
bool easingIn; bool easingIn;
TimeSpan transitionTime; TimeSpan transitionTime;
if (!_transitions.TryGetValue(entity, out var transition)) if (!_transitions.TryGetValue(entity, out var transition))
{ {
// Start as false because it will immediately be flipped // Start as false because it will immediately be flipped
@@ -104,12 +104,12 @@ namespace Content.Client.StationEvents
easingIn = transition.EasingIn; easingIn = transition.EasingIn;
transitionTime = endTime; transitionTime = endTime;
} }
_transitions[entity] = (!easingIn, transitionTime); _transitions[entity] = (!easingIn, transitionTime);
_colors[entity] = Color.Green.WithAlpha(0.0f); _colors[entity] = Color.Green.WithAlpha(0.0f);
_alphaRateOfChange[entity] = 1.0f / (float) (transitionTime - currentTime).TotalSeconds; _alphaRateOfChange[entity] = 1.0f / (float) (transitionTime - currentTime).TotalSeconds;
} }
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace) protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
{ {
// PVS should control the overlay pretty well so the overlay doesn't get instantiated unless we're near one... // PVS should control the overlay pretty well so the overlay doesn't get instantiated unless we're near one...
@@ -134,19 +134,18 @@ namespace Content.Client.StationEvents
{ {
foreach (var pulse in radiationPulses) foreach (var pulse in radiationPulses)
{ {
if (grid.Index != pulse.Owner.Transform.GridID) continue; if (!pulse.Draw || grid.Index != pulse.Owner.Transform.GridID) continue;
// TODO: Check if viewport intersects circle // TODO: Check if viewport intersects circle
var circlePosition = _eyeManager.WorldToScreen(pulse.Owner.Transform.WorldPosition); var circlePosition = _eyeManager.WorldToScreen(pulse.Owner.Transform.WorldPosition);
var comp = (RadiationPulseComponent) pulse;
// change to worldhandle when implemented // change to worldhandle when implemented
screenHandle.DrawCircle( screenHandle.DrawCircle(
circlePosition, circlePosition,
comp.Range * 64, pulse.Range * 64,
GetColor(pulse.Owner, elapsedTime, comp.EndTime)); GetColor(pulse.Owner, pulse.Decay ? elapsedTime : 0, pulse.EndTime));
} }
} }
} }
} }
} }

View File

@@ -8,58 +8,116 @@ using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Timers;
namespace Content.Server.GameObjects.Components.StationEvents namespace Content.Server.GameObjects.Components.StationEvents
{ {
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(SharedRadiationPulseComponent))]
public sealed class RadiationPulseComponent : SharedRadiationPulseComponent public sealed class RadiationPulseComponent : SharedRadiationPulseComponent
{ {
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
private const float MinPulseLifespan = 0.8f; private float _duration;
private const float MaxPulseLifespan = 2.5f; private float _radsPerSecond;
private float _range;
public float DPS => _dps;
private float _dps;
private TimeSpan _endTime; private TimeSpan _endTime;
private bool _draw;
private bool _decay;
/// <summary>
/// Whether the entity will delete itself after a certain duration defined by
/// <see cref="MinPulseLifespan"/> and <see cref="MaxPulseLifespan"/>
/// </summary>
public override bool Decay
{
get => _decay;
set
{
_decay = value;
Dirty();
}
}
public float MinPulseLifespan { get; set; }
public float MaxPulseLifespan { get; set; }
public override float RadsPerSecond
{
get => _radsPerSecond;
set
{
_radsPerSecond = value;
Dirty();
}
}
public string Sound { get; set; }
public override float Range
{
get => _range;
set
{
_range = value;
Dirty();
}
}
public override bool Draw
{
get => _draw;
set
{
_draw = value;
Dirty();
}
}
public override TimeSpan EndTime => _endTime;
public override void ExposeData(ObjectSerializer serializer) public override void ExposeData(ObjectSerializer serializer)
{ {
base.ExposeData(serializer); base.ExposeData(serializer);
serializer.DataField(ref _dps, "dps", 40.0f); serializer.DataField(this, x => x.RadsPerSecond, "dps", 40.0f);
serializer.DataField(this, x => x.Sound, "sound", "/Audio/Weapons/Guns/Gunshots/laser3.ogg");
serializer.DataField(this, x => x.Range, "range", 5.0f);
serializer.DataField(this, x => x.Draw, "draw", true);
serializer.DataField(this, x => x.Decay, "decay", true);
serializer.DataField(this, x => x.MaxPulseLifespan, "maxPulseLifespan", 2.5f);
serializer.DataField(this, x => x.MinPulseLifespan, "minPulseLifespan", 0.8f);
} }
public override void Initialize() public void DoPulse()
{ {
base.Initialize(); if (Decay)
var currentTime = _gameTiming.CurTime;
var duration =
TimeSpan.FromSeconds(
_random.NextFloat() * (MaxPulseLifespan - MinPulseLifespan) +
MinPulseLifespan);
_endTime = currentTime + duration;
Timer.Spawn(duration,
() =>
{ {
if (!Owner.Deleted) var currentTime = _gameTiming.CurTime;
{ _duration = _random.NextFloat() * (MaxPulseLifespan - MinPulseLifespan) + MinPulseLifespan;
Owner.Delete(); _endTime = currentTime + TimeSpan.FromSeconds(_duration);
} }
});
if(!string.IsNullOrEmpty(Sound))
EntitySystem.Get<AudioSystem>().PlayAtCoords(Sound, Owner.Transform.Coordinates);
EntitySystem.Get<AudioSystem>().PlayAtCoords("/Audio/Weapons/Guns/Gunshots/laser3.ogg", Owner.Transform.Coordinates);
Dirty(); Dirty();
} }
public override ComponentState GetComponentState() public override ComponentState GetComponentState()
{ {
return new RadiationPulseMessage(_endTime); return new RadiationPulseState(_radsPerSecond, _range, Draw, Decay, _endTime);
}
public void Update(float frameTime)
{
if (!Decay || Owner.Deleted)
return;
if(_duration <= 0f)
Owner.Delete();
_duration -= frameTime;
} }
} }
} }

View File

@@ -1,87 +1,56 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.StationEvents; using Content.Server.GameObjects.Components.StationEvents;
using Content.Shared.Damage; using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Damage;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Server.GameObjects.EntitySystems.StationEvents namespace Content.Server.GameObjects.EntitySystems.StationEvents
{ {
[UsedImplicitly] [UsedImplicitly]
public sealed class RadiationPulseSystem : EntitySystem public sealed class RadiationPulseSystem : EntitySystem
{ {
// Rather than stuffing around with collidables and checking entities on initialize etc. we'll just tick over private const string RadiationPrototype = "RadiationPulse";
// for each entity in range. Seemed easier than checking entities on spawn, then checking collidables, etc.
// Especially considering each pulse is a big chonker, + no circle hitboxes yet.
private TypeEntityQuery _speciesQuery; public IEntity RadiationPulse(EntityCoordinates coordinates, float range, int dps, bool decay = true, float minPulseLifespan = 0.8f, float maxPulseLifespan = 2.5f, string sound = null)
/// <summary>
/// Damage works with ints so we'll just accumulate damage and once we hit this threshold we'll apply it.
/// </summary>
/// This also server to stop spamming the damagethreshold with 1 damage continuously.
private const int DamageThreshold = 10;
private Dictionary<IEntity, float> _accumulatedDamage = new Dictionary<IEntity, float>();
public override void Initialize()
{ {
base.Initialize(); var radiationEntity = EntityManager.SpawnEntity(RadiationPrototype, coordinates);
_speciesQuery = new TypeEntityQuery(typeof(ISharedBodyManagerComponent)); var radiation = radiationEntity.GetComponent<RadiationPulseComponent>();
radiation.Range = range;
radiation.RadsPerSecond = dps;
radiation.Draw = false;
radiation.Decay = decay;
radiation.MinPulseLifespan = minPulseLifespan;
radiation.MaxPulseLifespan = maxPulseLifespan;
radiation.Sound = sound;
radiation.DoPulse();
return radiationEntity;
} }
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);
var anyPulses = false;
foreach (var comp in ComponentManager.EntityQuery<RadiationPulseComponent>()) foreach (var comp in ComponentManager.EntityQuery<RadiationPulseComponent>())
{ {
anyPulses = true; comp.Update(frameTime);
var ent = comp.Owner;
foreach (var species in EntityManager.GetEntities(_speciesQuery)) if (ent.Deleted) continue;
foreach (var entity in EntityManager.GetEntitiesInRange(ent.Transform.Coordinates, comp.Range, true))
{ {
// Work out if we're in range and accumulate more damage if (entity.Deleted) continue;
// If we've hit the DamageThreshold we'll also apply that damage to the mob
// If we're really lagging server can apply multiples of the DamageThreshold at once
if (species.Transform.MapID != comp.Owner.Transform.MapID) continue;
if ((species.Transform.WorldPosition - comp.Owner.Transform.WorldPosition).Length > comp.Range) foreach (var radiation in entity.GetAllComponents<IRadiationAct>())
{ {
continue; radiation.RadiationAct(frameTime, comp);
} }
var totalDamage = frameTime * comp.DPS;
if (!_accumulatedDamage.TryGetValue(species, out var accumulatedSpecies))
{
_accumulatedDamage[species] = 0.0f;
}
totalDamage += accumulatedSpecies;
_accumulatedDamage[species] = totalDamage;
if (totalDamage < DamageThreshold) continue;
if (!species.TryGetComponent(out DamageableComponent damageableComponent)) continue;
var damageMultiple = (int) (totalDamage / DamageThreshold);
_accumulatedDamage[species] = totalDamage % DamageThreshold;
damageableComponent.ChangeDamage(DamageType.Heat, damageMultiple * DamageThreshold, false, comp.Owner);
} }
} }
if (anyPulses)
{
return;
}
// probably don't need to worry about clearing this at roundreset unless you have a radiation pulse at roundstart
// (which is currently not possible)
_accumulatedDamage.Clear();
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.StationEvents;
using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.Utility; using Content.Shared.Utility;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -114,7 +115,8 @@ namespace Content.Server.StationEvents
private void SpawnPulse(IMapGrid mapGrid) private void SpawnPulse(IMapGrid mapGrid)
{ {
_entityManager.SpawnEntity("RadiationPulse", FindRandomGrid(mapGrid)); var pulse = _entityManager.SpawnEntity("RadiationPulse", FindRandomGrid(mapGrid));
pulse.GetComponent<RadiationPulseComponent>().DoPulse();
_timeUntilPulse = _robustRandom.NextFloat() * (MaxPulseDelay - MinPulseDelay) + MinPulseDelay; _timeUntilPulse = _robustRandom.NextFloat() * (MaxPulseDelay - MinPulseDelay) + MinPulseDelay;
_pulsesRemaining -= 1; _pulsesRemaining -= 1;
} }

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Damage.DamageContainer; using Content.Shared.Damage.DamageContainer;
using Content.Shared.Damage.ResistanceSet; using Content.Shared.Damage.ResistanceSet;
using Content.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
@@ -19,7 +20,7 @@ namespace Content.Shared.GameObjects.Components.Damage
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
[ComponentReference(typeof(IDamageableComponent))] [ComponentReference(typeof(IDamageableComponent))]
public class DamageableComponent : Component, IDamageableComponent public class DamageableComponent : Component, IDamageableComponent, IRadiationAct
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -388,5 +389,12 @@ namespace Content.Shared.GameObjects.Components.Damage
Dirty(); Dirty();
} }
public void RadiationAct(float frameTime, SharedRadiationPulseComponent radiation)
{
var totalDamage = Math.Max((int)(frameTime * radiation.RadsPerSecond), 1);
ChangeDamage(DamageType.Radiation, totalDamage, false, radiation.Owner);
}
} }
} }

View File

@@ -9,30 +9,38 @@ namespace Content.Shared.GameObjects.Components
public override string Name => "RadiationPulse"; public override string Name => "RadiationPulse";
public override uint? NetID => ContentNetIDs.RADIATION_PULSE; public override uint? NetID => ContentNetIDs.RADIATION_PULSE;
public virtual float RadsPerSecond { get; set; }
/// <summary> /// <summary>
/// Radius of the pulse from its position /// Radius of the pulse from its position
/// </summary> /// </summary>
public float Range => _range; public virtual float Range { get; set; }
private float _range;
public override void ExposeData(ObjectSerializer serializer) public virtual bool Decay { get; set; }
{ public virtual bool Draw { get; set; }
base.ExposeData(serializer);
serializer.DataField(ref _range, "range", 5.0f); public virtual TimeSpan EndTime { get; }
}
} }
/// <summary> /// <summary>
/// For syncing the pulse's lifespan between client and server for the overlay /// For syncing the pulse's lifespan between client and server for the overlay
/// </summary> /// </summary>
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class RadiationPulseMessage : ComponentState public class RadiationPulseState : ComponentState
{ {
public TimeSpan EndTime { get; } public readonly float RadsPerSecond;
public readonly float Range;
public readonly bool Draw;
public readonly bool Decay;
public readonly TimeSpan EndTime;
public RadiationPulseMessage(TimeSpan endTime) : base(ContentNetIDs.RADIATION_PULSE) public RadiationPulseState(float radsPerSecond, float range, bool draw, bool decay, TimeSpan endTime) : base(ContentNetIDs.RADIATION_PULSE)
{ {
RadsPerSecond = radsPerSecond;
Range = range;
Draw = draw;
Decay = decay;
EndTime = endTime; EndTime = endTime;
} }
} }
} }

View File

@@ -0,0 +1,10 @@
using Content.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Shared.Interfaces.GameObjects.Components
{
public interface IRadiationAct : IComponent
{
void RadiationAct(float frameTime, SharedRadiationPulseComponent radiation);
}
}

View File

@@ -61,6 +61,7 @@
offset: Center offset: Center
- type: Destructible - type: Destructible
deadThreshold: 500 deadThreshold: 500
resistances: metallicResistances
placement: placement:
mode: SnapgridCenter mode: SnapgridCenter

View File

@@ -19,6 +19,7 @@
- type: Pullable - type: Pullable
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: entity - type: entity
name: bar stool name: bar stool
@@ -52,6 +53,7 @@
- type: Pullable - type: Pullable
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: entity - type: entity
name: dark office chair name: dark office chair
@@ -87,6 +89,7 @@
- type: Pullable - type: Pullable
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: entity - type: entity
parent: Chair parent: Chair
@@ -135,5 +138,6 @@
rotation: -90 rotation: -90
- type: Destructible - type: Destructible
deadThreshold: 75 deadThreshold: 75
resistances: metallicResistances
placement: placement:
mode: SnapgridCenter mode: SnapgridCenter

View File

@@ -19,6 +19,7 @@
offset: Center offset: Center
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: UserInterface - type: UserInterface
interfaces: interfaces:
- key: enum.InstrumentUiKey.Key - key: enum.InstrumentUiKey.Key

View File

@@ -15,6 +15,7 @@
- type: InteractionOutline - type: InteractionOutline
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Physics - type: Physics
- type: ShuttleController - type: ShuttleController
- type: Strap - type: Strap

View File

@@ -12,6 +12,7 @@
- type: Sprite - type: Sprite
- type: Destructible - type: Destructible
thresholdvalue: 100 thresholdvalue: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: PipeVisualizer - type: PipeVisualizer

View File

@@ -21,6 +21,7 @@
pumpRSI: Constructible/Atmos/pressurepump.rsi pumpRSI: Constructible/Atmos/pressurepump.rsi
- type: Destructible - type: Destructible
thresholdvalue: 100 thresholdvalue: 100
resistances: metallicResistances
- type: entity - type: entity
abstract: true abstract: true

View File

@@ -23,6 +23,7 @@
siphonRSI: Constructible/Atmos/scrubber.rsi siphonRSI: Constructible/Atmos/scrubber.rsi
- type: Destructible - type: Destructible
thresholdvalue: 100 thresholdvalue: 100
resistances: metallicResistances
- type: entity - type: entity
parent: ScrubberBase parent: ScrubberBase

View File

@@ -1,7 +1,7 @@
- type: entity - type: entity
id: Table id: Table
name: "table" name: "table"
description: A square piece of metal standing on four metal legs. description: A square piece of metal standing on four metal legs.
components: components:
- type: Clickable - type: Clickable
- type: InteractionOutline - type: InteractionOutline
@@ -25,6 +25,7 @@
- type: Climbable - type: Climbable
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
spawnOnDestroy: SteelSheet1 spawnOnDestroy: SteelSheet1
- type: entity - type: entity
@@ -54,4 +55,5 @@
- type: Climbable - type: Climbable
- type: Destructible - type: Destructible
deadThreshold: 15 deadThreshold: 15
resistances: metallicResistances
spawnOnDestroy: WoodPlank spawnOnDestroy: WoodPlank

View File

@@ -22,6 +22,7 @@
- type: VentVisualizer - type: VentVisualizer
ventRSI: Constructible/Atmos/vent.rsi ventRSI: Constructible/Atmos/vent.rsi
- type: Destructible - type: Destructible
resistances: metallicResistances
thresholdvalue: 100 thresholdvalue: 100
- type: entity - type: entity

View File

@@ -18,6 +18,7 @@
mode: CardinalFlags mode: CardinalFlags
- type: Destructible - type: Destructible
thresholdvalue: 100 thresholdvalue: 100
resistances: metallicResistances
- type: SubFloorHide - type: SubFloorHide
- type: entity - type: entity
@@ -39,6 +40,7 @@
wireDroppedOnCutPrototype: HVWireStack1 wireDroppedOnCutPrototype: HVWireStack1
wireType: HighVoltage wireType: HighVoltage
- type: Destructible - type: Destructible
resistances: metallicResistances
spawnondestroy: HVWireStack1 spawnondestroy: HVWireStack1
- type: entity - type: entity
@@ -61,6 +63,7 @@
wireDroppedOnCutPrototype: MVWireStack1 wireDroppedOnCutPrototype: MVWireStack1
wireType: MediumVoltage wireType: MediumVoltage
- type: Destructible - type: Destructible
resistances: metallicResistances
spawnondestroy: MVWireStack1 spawnondestroy: MVWireStack1
- type: entity - type: entity
@@ -85,4 +88,5 @@
wireDroppedOnCutPrototype: ApcExtensionCableStack1 wireDroppedOnCutPrototype: ApcExtensionCableStack1
wireType: Apc wireType: Apc
- type: Destructible - type: Destructible
resistances: metallicResistances
spawnondestroy: ApcExtensionCableStack1 spawnondestroy: ApcExtensionCableStack1

View File

@@ -22,6 +22,7 @@
- SmallImpassable - SmallImpassable
- type: Destructible - type: Destructible
maxHP: 500 maxHP: 500
resistances: metallicResistances
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
- type: Anchorable - type: Anchorable
@@ -41,4 +42,4 @@
nodeGroupID: HVPower nodeGroupID: HVPower
- type: PowerReceiver - type: PowerReceiver
- type: PowerSupplier - type: PowerSupplier
supplyRate: 0 supplyRate: 0

View File

@@ -23,6 +23,7 @@
- SmallImpassable - SmallImpassable
- type: Destructible - type: Destructible
maxHP: 500 maxHP: 500
resistances: metallicResistances
spawnondestroy: AMEPart spawnondestroy: AMEPart
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
@@ -43,4 +44,4 @@
color: "#00AAFF" color: "#00AAFF"
- type: Appearance - type: Appearance
visuals: visuals:
- type: AMEVisualizer - type: AMEVisualizer

View File

@@ -35,6 +35,7 @@
cloningTime: 10.0 cloningTime: 10.0
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: CloningPodVisualizer - type: CloningPodVisualizer

View File

@@ -30,6 +30,7 @@
drawRate: 50 drawRate: 50
- type: Breakable - type: Breakable
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Anchorable - type: Anchorable
- type: entity - type: entity

View File

@@ -30,6 +30,7 @@
- type: InteractionOutline - type: InteractionOutline
- type: Breakable - type: Breakable
deadThreshold: 150 deadThreshold: 150
resistances: metallicResistances
- type: GravityGenerator - type: GravityGenerator
- type: UserInterface - type: UserInterface
interfaces: interfaces:

View File

@@ -35,6 +35,7 @@
- type: MedicalScanner - type: MedicalScanner
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: MedicalScannerVisualizer - type: MedicalScannerVisualizer

View File

@@ -188,3 +188,4 @@
offset: Center offset: Center
- type: Breakable - type: Breakable
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances

View File

@@ -32,6 +32,7 @@
offset: Center offset: Center
- type: Breakable - type: Breakable
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: UserInterface - type: UserInterface
interfaces: interfaces:
- key: enum.VendingMachineUiKey.Key - key: enum.VendingMachineUiKey.Key

View File

@@ -43,6 +43,7 @@
- type: PlaceableSurface - type: PlaceableSurface
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: StorageVisualizer - type: StorageVisualizer

View File

@@ -27,6 +27,7 @@
Anchored: false Anchored: false
- type: Destructible - type: Destructible
deadThreshold: 10 deadThreshold: 10
resistances: metallicResistances
- type: SolutionContainer - type: SolutionContainer
maxVol: 1500 maxVol: 1500
caps: RemoveFrom caps: RemoveFrom

View File

@@ -38,6 +38,8 @@
- type: PlaceableSurface - type: PlaceableSurface
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: StorageVisualizer - type: StorageVisualizer

View File

@@ -18,6 +18,7 @@
layer: [MobMask] layer: [MobMask]
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: Occluder - type: Occluder
sizeX: 32 sizeX: 32
sizeY: 32 sizeY: 32

View File

@@ -16,6 +16,7 @@
layer: [MobMask, Opaque] layer: [MobMask, Opaque]
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
spawnOnDestroy: SteelSheet1 spawnOnDestroy: SteelSheet1
- type: SnapGrid - type: SnapGrid
offset: Edge offset: Edge

View File

@@ -40,6 +40,7 @@
- type: PowerReceiver - type: PowerReceiver
- type: Destructible - type: Destructible
deadThreshold: 50 deadThreshold: 50
resistances: metallicResistances
- type: entity - type: entity
name: small light name: small light
@@ -61,3 +62,4 @@
- type: PowerReceiver - type: PowerReceiver
- type: Destructible - type: Destructible
deadThreshold: 25 deadThreshold: 25
resistances: metallicResistances

View File

@@ -26,6 +26,7 @@
- SmallImpassable - SmallImpassable
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
- type: Climbable - type: Climbable

View File

@@ -10,6 +10,7 @@
- !type:PhysShapeAabb - !type:PhysShapeAabb
- type: Destructible - type: Destructible
thresholdvalue: 5 thresholdvalue: 5
resistances: metallicResistances
- type: Sprite - type: Sprite
drawdepth: WallTops drawdepth: WallTops
sprite: Constructible/Misc/decals.rsi sprite: Constructible/Misc/decals.rsi

View File

@@ -28,6 +28,7 @@
- type: Destructible - type: Destructible
deadThreshold: 500 deadThreshold: 500
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: Occluder - type: Occluder
sizeX: 32 sizeX: 32
sizeY: 32 sizeY: 32
@@ -51,6 +52,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: brick base: brick
@@ -67,6 +69,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: clock base: clock
@@ -83,6 +86,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: clown base: clown
@@ -100,6 +104,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: cult base: cult
@@ -116,6 +121,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: debug base: debug
@@ -132,6 +138,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: diamond base: diamond
@@ -149,6 +156,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: gold base: gold
@@ -165,6 +173,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: ice base: ice
@@ -181,6 +190,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: metal base: metal
@@ -197,6 +207,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: plasma base: plasma
@@ -213,6 +224,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: plastic base: plastic
@@ -231,6 +243,7 @@
- type: Destructible - type: Destructible
deadThreshold: 600 deadThreshold: 600
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: ReinforcedWall - type: ReinforcedWall
key: walls key: walls
base: solid base: solid
@@ -249,6 +262,7 @@
- type: Destructible - type: Destructible
deadThreshold: 1000 deadThreshold: 1000
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: riveted base: riveted
@@ -265,6 +279,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: sandstone base: sandstone
@@ -281,6 +296,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: silver base: silver
@@ -299,6 +315,7 @@
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
destroySound: /Audio/Effects/metalbreak.ogg destroySound: /Audio/Effects/metalbreak.ogg
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: solid base: solid
@@ -315,6 +332,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: uranium base: uranium
@@ -331,6 +349,7 @@
- type: Destructible - type: Destructible
deadThreshold: 300 deadThreshold: 300
spawnOnDestroy: Girder spawnOnDestroy: Girder
resistances: metallicResistances
- type: IconSmooth - type: IconSmooth
key: walls key: walls
base: wood base: wood

View File

@@ -29,6 +29,7 @@
- SmallImpassable - SmallImpassable
- type: Destructible - type: Destructible
deadThreshold: 100 deadThreshold: 100
resistances: metallicResistances
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
- type: Airtight - type: Airtight

View File

@@ -14,6 +14,7 @@
offset: Center offset: Center
- type: Anchorable - type: Anchorable
- type: Breakable - type: Breakable
resistances: metallicResistances
- type: Rotatable - type: Rotatable
- type: Pullable - type: Pullable
@@ -139,6 +140,7 @@
- type: Anchorable - type: Anchorable
- type: Destructible - type: Destructible
thresholdvalue: 100 thresholdvalue: 100
resistances: metallicResistances
- type: Appearance - type: Appearance
visuals: visuals:
- type: DisposalUnitVisualizer - type: DisposalUnitVisualizer