diff --git a/Content.Server/Lightning/LightningSystem.cs b/Content.Server/Lightning/LightningSystem.cs
index 8b0a18afb3..226772faf0 100644
--- a/Content.Server/Lightning/LightningSystem.cs
+++ b/Content.Server/Lightning/LightningSystem.cs
@@ -50,6 +50,7 @@ public sealed class LightningSystem : SharedLightningSystem
public void ShootLightning(EntityUid user, EntityUid target, string lightningPrototype = "Lightning", bool triggerLightningEvents = true)
{
var spriteState = LightningRandomizer();
+
_beam.TryCreateBeam(user, target, lightningPrototype, spriteState);
if (triggerLightningEvents) // we don't want certain prototypes to trigger lightning level events
@@ -69,7 +70,7 @@ public sealed class LightningSystem : SharedLightningSystem
/// The prototype for the lightning to be created
/// how many times to recursively fire lightning bolts from the target points of the first shot.
/// if the lightnings being fired should trigger lightning events.
- public void ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true)
+ public bool ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true)
{
//TODO: add support to different priority target tablem for different lightning types
//TODO: Remove Hardcode LightningTargetComponent (this should be a parameter of the SharedLightningComponent)
@@ -80,6 +81,7 @@ public sealed class LightningSystem : SharedLightningSystem
_random.Shuffle(targets);
targets.Sort((x, y) => y.Comp.Priority.CompareTo(x.Comp.Priority));
+ bool shooted = false; //starlight
int shootedCount = 0;
int count = -1;
while(shootedCount < boltCount)
@@ -93,12 +95,14 @@ public sealed class LightningSystem : SharedLightningSystem
continue;
ShootLightning(user, targets[count].Owner, lightningPrototype, triggerLightningEvents);
+ shooted = true;//starlight
if (arcDepth - targets[count].Comp.LightningResistance > 0)
{
ShootRandomLightnings(targets[count].Owner, range, 1, lightningPrototype, arcDepth - targets[count].Comp.LightningResistance, triggerLightningEvents);
}
shootedCount++;
}
+ return shooted; //starlight
}
}
diff --git a/Content.Server/Singularity/EntitySystems/SingularitySystem.cs b/Content.Server/Singularity/EntitySystems/SingularitySystem.cs
index 13f5afa5ba..f28502fc75 100644
--- a/Content.Server/Singularity/EntitySystems/SingularitySystem.cs
+++ b/Content.Server/Singularity/EntitySystems/SingularitySystem.cs
@@ -4,10 +4,11 @@ using Content.Server.Singularity.Events;
using Content.Shared.Singularity.Components;
using Content.Shared.Singularity.EntitySystems;
using Content.Shared.Singularity.Events;
-using Content.Server.Supermatter.Components;
using Robust.Server.GameStates;
+using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.GameStates;
+using Robust.Shared.Player;
using Robust.Shared.Timing;
namespace Content.Server.Singularity.EntitySystems;
@@ -36,11 +37,6 @@ public sealed class SingularitySystem : SharedSingularitySystem
///
public const float BaseEntityEnergy = 1f;
- ///
- /// Whether or not the singuloo has eaten the supermatter crystal
- ///
- public bool HasEatenSM = false;
-
public override void Initialize()
{
base.Initialize();
@@ -107,7 +103,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
{
// Normally, a level 6 singularity requires the supermatter + 3000 energy.
// The required amount of energy has been bumped up to compensate for the lack of the supermatter.
- >= 5000 when HasEatenSM => 6,
+ >= 5000 => 6,
>= 2000 => 5,
>= 1000 => 4,
>= 500 => 3,
@@ -220,8 +216,7 @@ public sealed class SingularitySystem : SharedSingularitySystem
// Don't double count singulo food
if (HasComp(args.Entity))
return;
- if (HasComp(uid))
- HasEatenSM = true;
+
AdjustEnergy(uid, BaseEntityEnergy, singularity: comp);
}
diff --git a/Content.Server/Supermatter/Components/SupermatterComponent.cs b/Content.Server/Supermatter/Components/SupermatterComponent.cs
deleted file mode 100644
index 5e699e9a49..0000000000
--- a/Content.Server/Supermatter/Components/SupermatterComponent.cs
+++ /dev/null
@@ -1,276 +0,0 @@
-using Content.Shared.Atmos;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Supermatter.Components;
-
-[RegisterComponent]
-public sealed partial class SupermatterComponent : Component
-{
- ///
- /// The damage taken from direct hits, e.g. laser weapons
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float AVExternalDamage = 0f;
-
- //
- [ViewVariables(VVAccess.ReadOnly)]
- public float HeatAccumulatorRate = 0.5f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float AVHeatAccumulator = 0f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float RadiationAccumulatorRate = 0.3f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float AVRadiationAccumulator = 0f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float LightingAccumulatorThreshold = 2f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float LightingAccumulatorRate = 0.1f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float AVLightingAccumulator = 0f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public float InternalEnergyAccumulatorRate = 0.1f;
- ///
- /// Lightning prototype IDs that the supermatter should spit out.
- ///
- public readonly string[] LightningPrototypeIDs =
- {
- "Lightning",
- "ChargedLightning",
- "SuperchargedLightning",
- "HyperchargedLightning"
- };
- public readonly string SliverPrototype = "SupermatterSliver";
-
- [DataField("zapSound")]
- public SoundSpecifier SupermatterZapSound = new SoundPathSpecifier("/Audio/Weapons/emitter2.ogg");
-
- [DataField("calmAmbienceSound")]
- public SoundSpecifier CalmAmbienceSound = new SoundPathSpecifier("/Audio/Ambience/Objects/supermatter_calm.ogg");
-
- [DataField("delamAmbienceSound")]
- public SoundSpecifier DelamAmbienceSound = new SoundPathSpecifier("/Audio/Ambience/Objects/supermatter_delam.ogg");
-
- [ViewVariables]
- public SoundSpecifier CurrentAmbience = new SoundPathSpecifier("/Audio/Ambience/Objects/supermatter_calm.ogg");
-
- [DataField("teslaSpawnPrototype")]
- public string TeslaPrototype = "TeslaEnergyBall";
-
- [DataField("singularitySpawnPrototype")]
- public string SingularityPrototype = "Singularity";
-
- [DataField("supermatterKudzuSpawnPrototype")]
- public string SupermatterKudzuPrototype = "SupermatterKudzu";
-
- ///
- /// If a supermatter sliver has been removed. Lowers the delamination countdown time.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public bool SliverRemoved = false;
-
- ///
- /// Indicates whether supermatter crystal is active or not.
- ///
- [DataField("activated")]
- public bool Activated = false;
-
- [ViewVariables]
- public GasMixture AbsorbedGasMix = new();
-
- ///
- /// Delta time between Update() calls storage.
- ///
- public float DeltaTime = 0f;
-
- public float UpdateTimerAccumulator = 0f;
-
- public float AnnouncementTimerAccumulator = 0f;
-
- ///
- /// Amount of seconds to pass before another SM cycle.
- ///
- [DataField("updateTimer")]
- public float UpdateTimer = 1f;
-
- ///
- /// Amount of seconds to pass before makes an announcement.
- ///
- [DataField("announcementTimer")]
- public float AnnouncementTimer = 60f;
-
- [ViewVariables(VVAccess.ReadWrite)]
- public int? PreferredDelamType = 0;
-
- ///
- /// The time in seconds for crystal to delaminate.
- ///
- [DataField("countdownTimer")]
- public float DelamCountdownTimerRaw = 120f;
- public float DelamCountdownTimer => SliverRemoved ? DelamCountdownTimerRaw / 2 : DelamCountdownTimerRaw;
- public bool DelamAnnouncementHappened = false;
-
- [ViewVariables(VVAccess.ReadWrite)]
- public float DelamCountdownAccumulator = 0f;
-
- ///
- /// The portion of gasmix we should absorb.
- ///
- [DataField("gasAbsorptionRatio")]
- public float AbsorptionRatio = .15f;
-
- ///
- /// This value effects gas output, damage and power generation.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float InternalEnergy = 0f;
-
- ///
- /// The amount of damage the SM currently has.
- ///
- [DataField("damage")]
- public float Damage = 0f;
-
- ///
- /// The amount of damage SM had before the cycle.
- ///
- public float DamageArchive = 0f;
-
- ///
- /// The temperature at which the supermatter crystal will begin to take damage.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float TempLimit = Atmospherics.T0C + HeatPenaltyThreshold;
-
- ///
- /// Multiplies our gas waste amount and temperature.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float WasteMultiplier = 0f;
-
- [DataField("damageDangerPoint")]
- public float DamageDangerPoint = 50f;
-
- [DataField("damageEmergencyPoint")]
- public float DamageEmergencyPoint = 75f;
-
- [DataField("damageDelaminationPoint")]
- public float DelaminationPoint = 100f;
-
- [ViewVariables(VVAccess.ReadOnly)]
- public bool AreWeDelaming = false;
-
- ///
- /// Affects the heat SM makes.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float GasHeatModifier = 0f;
- ///
- /// Affters the minimum point at which SM takes damage.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float GasHeatResistance = 0f;
- ///
- /// How much power decay is negated. Complete power decay negation at 1.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float GasPowerlossInhibition = 0f;
- [ViewVariables(VVAccess.ReadOnly)]
- public float ThermalСonductivity = 0f;
- ///
- /// Affects the power gain the SM experiences from heat.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public float HeatPowerGeneration = 0f;
-
- ///
- /// Lesser than that and it's not worth processing.
- ///
- public const float MinimumMoleCount = .01f;
-
- public const float HeatPenaltyThreshold = 40f;
- public const float PowerPenaltyThreshold = 3f;
- public const float MolePenaltyThreshold = 900f;
- public const float ThermalReleaseModifier = 4f;
- public const float PlasmaReleaseModifier = 1.5f;
- public const float OxygenReleaseModifier = 2.5f;
- public const float GasHeatPowerScaling = 1f / 6f;
-
- ///
- /// Stores gas properties used for the supermatter.
- /// Array values should alwayd match gas enum values.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- public GasFact[] GasFacts =
- {
- new (thermalConductivity: 2.4f, heatPowerGeneration: 1f), // o2
- new (thermalConductivity: 2.0f, heatModifier: -2.5f, heatPowerGeneration: -1), // n2
- new (thermalConductivity: 1.2f, heatModifier: 1f, heatPowerGeneration: 1f, powerlossInhibition: 1f), // co2
- new (thermalConductivity: 6.0f, heatModifier: 14f, heatPowerGeneration: 1f), // plasma
- new (thermalConductivity: 3.0f, heatModifier: 9f, heatPowerGeneration: 1f), // tritium
- new (thermalConductivity: 1.4f, heatModifier: 11f, heatPowerGeneration: 1f), // vapor
- new (thermalConductivity: 1.6f, heatPowerGeneration: .5f), // ommonium
- new (thermalConductivity: 1.3f, heatResistance: 5f), // n2o
- new (thermalConductivity: 9.9f, heatModifier: 9f, heatResistance: 1f, heatPowerGeneration: 1f), // frezon
- };
-}
-
-///
-/// Stores gas properties used for the supermatter.
-///
-[Serializable]
-[DataDefinition]
-public sealed partial class GasFact
-{
- ///
- /// Affects the amount of power the main SM zap makes.
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- public float ThermalСonductivity;
- ///
- /// Affects the heat SM makes.
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- public float HeatModifier;
- ///
- /// Affters the minimum point at which SM takes damage.
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- public float HeatResistance;
- ///
- /// Affects the power gain the SM experiences from heat.
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- public float HeatPowerGeneration;
- ///
- /// How much power decay is negated. Complete power decay negation at 1.
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- public float PowerlossInhibition;
-
- public GasFact(float? thermalConductivity = null, float? heatModifier = null, float? heatResistance = null, float? heatPowerGeneration = null, float? powerlossInhibition = null)
- {
- ThermalСonductivity = thermalConductivity ?? 1;
- HeatModifier = heatModifier ?? 1;
- HeatResistance = heatResistance ?? 0;
- HeatPowerGeneration = heatPowerGeneration ?? 0;
- PowerlossInhibition = powerlossInhibition ?? 0;
- }
-}
-
-///
-/// Type of delamination that should occur.
-///
-public enum DelamType : sbyte
-{
- Explosion = 0,
- Tesla = 1,
- Singularity = 2,
- ResonanceCascade = 3,
-}
diff --git a/Content.Server/Supermatter/EntitySystems/SupermatterSystem.cs b/Content.Server/Supermatter/EntitySystems/SupermatterSystem.cs
deleted file mode 100644
index f82677cb5c..0000000000
--- a/Content.Server/Supermatter/EntitySystems/SupermatterSystem.cs
+++ /dev/null
@@ -1,504 +0,0 @@
-using Content.Server.Atmos.EntitySystems;
-using Content.Server.Supermatter.Components;
-using Content.Shared.Atmos;
-using Content.Server.Lightning;
-using Content.Shared.Radiation.Components;
-using Content.Shared.Interaction;
-using Content.Server.Audio;
-using Content.Shared.Audio;
-using Content.Server.Station.Systems;
-using Content.Server.Station.Components;
-using Content.Server.Anomaly;
-using Content.Shared.Damage;
-using Content.Shared.Tag;
-using Content.Shared.DoAfter;
-using Content.Server.Popups;
-using Content.Shared.Supermatter;
-using Content.Server.Administration.Logs;
-using Robust.Shared.Physics.Events;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Random;
-using Content.Shared.Database;
-using Content.Server.Chat.Systems;
-using System.Text;
-using Content.Server.AlertLevel;
-using Content.Shared.Examine;
-using Content.Server.DoAfter;
-using Content.Server.Explosion.EntitySystems;
-using Content.Server.Kitchen.Components;
-using Content.Shared.Weapons.Melee.EnergySword;
-using Content.Shared.Singularity.Components;
-using System;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Supermatter.EntitySystems;
-
-public sealed class SupermatterSystem : EntitySystem
-{
- [Dependency] private readonly AtmosphereSystem _atmos = default!;
- [Dependency] private readonly SharedAudioSystem _sound = default!;
- [Dependency] private readonly LightningSystem _lightning = default!;
- [Dependency] private readonly ChatSystem _chat = default!;
- [Dependency] private readonly AlertLevelSystem _alert = default!;
- [Dependency] private readonly PopupSystem _popup = default!;
- [Dependency] private readonly AmbientSoundSystem _ambience = default!;
- [Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly TagSystem _tagSystem = default!;
- [Dependency] private readonly StationSystem _station = default!;
- [Dependency] private readonly AnomalySystem _anomaly = default!;
- [Dependency] private readonly SharedTransformSystem _transform = default!;
- [Dependency] private readonly IAdminLogManager _adminLogger = default!;
- [Dependency] private readonly DoAfterSystem _doAfter = default!;
- [Dependency] private readonly ExplosionSystem _explosion = default!;
-
- public static SoundSpecifier VaporizeSound =
- new SoundPathSpecifier("/Audio/Effects/Grenades/Supermatter/supermatter_start.ogg");
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent(OnCollide);
- SubscribeLocalEvent(OnClick);
- SubscribeLocalEvent(OnGetSliver);
- SubscribeLocalEvent(OnGetHit);
- SubscribeLocalEvent(OnExamine);
- }
-
- public override void Update(float frameTime)
- {
- base.Update(frameTime);
-
- foreach (var sm in EntityQuery())
- {
- if (!sm.Activated)
- return;
-
- var uid = sm.Owner;
-
- sm.DeltaTime = frameTime;
- sm.UpdateTimerAccumulator += frameTime;
-
- if (sm.UpdateTimerAccumulator >= sm.UpdateTimer)
- {
- sm.UpdateTimerAccumulator = 0f;
- Cycle(uid, sm);
- }
- }
- }
-
- public void Cycle(EntityUid uid, SupermatterComponent sm)
- {
- sm.AnnouncementTimerAccumulator++;
-
- ProcessAtmos(uid, sm);
- ProcessPower(uid, sm);
- ProcessDamage(uid, sm);
-
- // due to how damage calculation works, it will do the announcement only if sm is consistently taking damage
- if (sm.Damage > sm.DamageArchive)
- {
- if (sm.AnnouncementTimerAccumulator > sm.AnnouncementTimer)
- {
- sm.AnnouncementTimerAccumulator = 0f;
- var loc = "danger";
- if (sm.Damage > sm.DamageEmergencyPoint)
- loc = "critical";
-
- SupermatterAlert(uid, Loc.GetString($"supermatter-announcement-{loc}", ("integrity", (int)(sm.DelaminationPoint - sm.Damage))));
- }
- }
- sm.DamageArchive = sm.Damage;
-
- if (sm.AreWeDelaming)
- DelamCountdown(uid, sm);
-
- ProcessWaste(uid, sm);
-
- HandleSound(uid, sm);
- }
-
- ///
- /// Calculate power based on gases absorbed.
- ///
- private void ProcessAtmos(EntityUid uid, SupermatterComponent sm)
- {
- var mix = _atmos.GetContainingMixture((uid, Transform(uid)), true, true) ?? new();
- var absorbedMix = mix?.RemoveRatio(sm.AbsorptionRatio) ?? new();
-
- // calculate gases
- var gasPercentages = new float[Enum.GetValues(typeof(Gas)).Length];
-
- var thermalСonductivity = 0f;
- var heatModifier = 0f;
- var heatResistance = 0f;
- var heatPowerGeneration = 0f;
- var powerlossInhibition = 0f;
-
- var moles = absorbedMix.TotalMoles;
-
- if (moles <= SupermatterComponent.MinimumMoleCount)
- return;
-
- for (int i = 0; i < gasPercentages.Length; i++)
- {
- var moleCount = absorbedMix.GetMoles(i);
-
- if (moleCount <= SupermatterComponent.MinimumMoleCount)
- continue;
-
- gasPercentages[i] = moleCount / moles;
- var smGas = sm.GasFacts[i];
-
- thermalСonductivity += smGas.ThermalСonductivity * gasPercentages[i];
- heatModifier += smGas.HeatModifier * gasPercentages[i];
- heatResistance += smGas.HeatResistance * gasPercentages[i];
- heatPowerGeneration += smGas.HeatPowerGeneration * gasPercentages[i];
- powerlossInhibition += smGas.PowerlossInhibition * gasPercentages[i];
- }
-
- heatPowerGeneration = Math.Clamp(heatPowerGeneration, 0, 1);
- powerlossInhibition = Math.Clamp(powerlossInhibition, 0, 1);
-
- sm.AbsorbedGasMix = absorbedMix;
- sm.ThermalСonductivity = thermalСonductivity;
- sm.GasHeatModifier = heatModifier;
- sm.GasHeatResistance = heatResistance;
- sm.HeatPowerGeneration = heatPowerGeneration;
- sm.GasPowerlossInhibition = powerlossInhibition;
- }
- ///
- /// Shoot lightning and radiate everything based on whatever power there is.
- ///
- private void ProcessPower(EntityUid uid, SupermatterComponent sm)
- {
- var powerHeat = sm.HeatPowerGeneration * sm.AbsorbedGasMix.Temperature * SupermatterComponent.GasHeatPowerScaling;
- var powerloss = -1 * sm.GasPowerlossInhibition;
- var atmosStrength = Math.Clamp((powerHeat + powerloss) * 0.2f, 0, 2);
-
- var damageStrength = Math.Clamp(sm.Damage / sm.DelaminationPoint, 0, 1);
- var strength = Math.Clamp(atmosStrength + damageStrength, 0, 4);
- var damageExternal = sm.AVExternalDamage + strength;
- sm.AVExternalDamage = 0f;
-
- sm.AVHeatAccumulator = Math.Clamp(sm.AVHeatAccumulator + (damageExternal * sm.HeatAccumulatorRate), 0, 10);
- sm.AVRadiationAccumulator = Math.Clamp(sm.AVRadiationAccumulator + (damageExternal * sm.RadiationAccumulatorRate), 0, 10);
- sm.AVLightingAccumulator = Math.Clamp(sm.AVLightingAccumulator + (damageExternal * sm.LightingAccumulatorRate), 0, 10);
- sm.InternalEnergy = Math.Clamp(sm.InternalEnergy + (damageExternal * sm.InternalEnergyAccumulatorRate), 0, 10);
-
- if (sm.AVLightingAccumulator > sm.LightingAccumulatorThreshold)
- {
- var lightningProto = sm.LightningPrototypeIDs[(int)Math.Clamp(sm.AVLightingAccumulator, 0, 3)];
- _lightning.ShootRandomLightnings(uid, 3, (int)sm.AVLightingAccumulator, lightningProto);
- sm.AVLightingAccumulator = 0;
- }
-
- Comp(uid).Intensity = 1 + sm.AVRadiationAccumulator;
- sm.AVRadiationAccumulator /= 2;
- sm.InternalEnergy /= 2;
-
- var mix = _atmos.GetContainingMixture((uid, Transform(uid)), true, true) ?? new();
- mix.Temperature += sm.AVHeatAccumulator * 4;
- sm.AVHeatAccumulator /= sm.ThermalСonductivity;
- }
- ///
- /// React to damage dealt by all doodads.
- ///
- private void ProcessDamage(EntityUid uid, SupermatterComponent sm)
- {
- var additiveTempBase = Atmospherics.T0C + SupermatterComponent.HeatPenaltyThreshold;
- var tempLimitBase = additiveTempBase;
- var tempLimitGas = sm.GasHeatResistance * additiveTempBase;
- var tempLimitMoles = Math.Clamp(2 - sm.AbsorbedGasMix.TotalMoles / 100, 0, 1) * additiveTempBase;
-
- sm.TempLimit = Math.Max(tempLimitBase + tempLimitGas + tempLimitMoles, Atmospherics.TCMB);
-
- var damageHeat = Math.Clamp((sm.AbsorbedGasMix.Temperature - sm.TempLimit) / 24000, 0, .15f);
- var damagePower = Math.Clamp((sm.InternalEnergy - SupermatterComponent.PowerPenaltyThreshold), 0, .1f);
- var damageMoles = Math.Clamp((sm.AbsorbedGasMix.TotalMoles - SupermatterComponent.MolePenaltyThreshold) / 3200, 0, .1f);
-
- var damageHealHeat = 0f;
-
- if (sm.AbsorbedGasMix.TotalMoles > 0)
- damageHealHeat = Math.Clamp((sm.AbsorbedGasMix.TotalMoles - sm.TempLimit) / 6000, -.1f, 0);
-
- var totalDamage = damageHeat + damagePower + damageMoles + damageHealHeat;
- var oldDamage = sm.Damage;
- sm.Damage += Math.Max(totalDamage, 0);
-
- if (sm.Damage >= sm.DelaminationPoint && !sm.AreWeDelaming)
- {
- sm.AreWeDelaming = true;
- SupermatterAlert(uid, Loc.GetString("supermatter-announcement-delam"));
- }
-
- if (sm.Damage > sm.DamageDangerPoint && _random.Prob(.0001f))
- GenerateAnomaly(uid);
- }
- ///
- /// Process waste, release hot plasma and oxygen.
- ///
- private void ProcessWaste(EntityUid uid, SupermatterComponent sm)
- {
- sm.WasteMultiplier = Math.Clamp(1f + sm.GasHeatModifier, .5f, float.PositiveInfinity);
- var mix = _atmos.GetContainingMixture((uid, Transform(uid)), true, true) ?? new();
- var mergeMix = sm.AbsorbedGasMix;
-
- mergeMix.Temperature += .65f * sm.WasteMultiplier * SupermatterComponent.ThermalReleaseModifier;
- mergeMix.Temperature = Math.Clamp(mergeMix.Temperature, Atmospherics.TCMB, 2500 * sm.WasteMultiplier);
-
- mergeMix.AdjustMoles(Gas.Plasma, Math.Max(.65f * sm.InternalEnergy * sm.WasteMultiplier * SupermatterComponent.PlasmaReleaseModifier, 0));
- mergeMix.AdjustMoles(Gas.Oxygen, Math.Max(.65f * sm.InternalEnergy * sm.WasteMultiplier * SupermatterComponent.OxygenReleaseModifier, 0));
-
- _atmos.Merge(mix, mergeMix);
- }
-
- ///
- /// Swaps out ambience sounds whether the SM is delamming or not.
- ///
- private void HandleSound(EntityUid uid, SupermatterComponent sm)
- {
- var ambienceComp = Comp(uid);
-
- if (sm.AreWeDelaming)
- {
- if (sm.CurrentAmbience != sm.DelamAmbienceSound)
- sm.CurrentAmbience = sm.DelamAmbienceSound;
- }
- else if (sm.CurrentAmbience != sm.CalmAmbienceSound)
- sm.CurrentAmbience = sm.CalmAmbienceSound;
-
- if (ambienceComp.Sound != sm.CurrentAmbience)
- _ambience.SetSound(uid, sm.CurrentAmbience, ambienceComp);
- }
-
- ///
- /// Make console alerts, set station codes, etc. etc.
- ///
- /// If true, the message will be sent from Central Command
- public void SupermatterAlert(EntityUid uid, string message, bool customSender = false)
- {
- _chat.DispatchStationAnnouncement(uid, message, customSender ? "Central Command" : Loc.GetString("supermatter-announcement-sender"), playDefault: false, playTts: true, colorOverride: Color.Yellow);
- }
-
- private void GenerateAnomaly(EntityUid uid, float amount = 1)
- {
- var stationUid = _station.GetOwningStation(uid);
-
- if (stationUid == null || !TryComp(stationUid, out var data))
- return;
-
- var grid = _station.GetLargestGrid(data);
-
- if (grid == null)
- return;
-
- for (var i = 0; i < amount; i++)
- {
- _anomaly.SpawnOnRandomGridLocation((EntityUid)grid, "RandomAnomalySpawner");
- _adminLogger.Add(LogType.Anomaly, LogImpact.Medium, $"An anomaly has been spawned by the supermatter crystal.");
- }
- }
-
- ///
- /// Vaporizes the targeted uid.
- ///
- private void Vaporize(EntityUid uid, EntityUid smUid)
- {
- if (EntityManager.IsQueuedForDeletion(uid))
- return;
-
- if (_tagSystem.HasTag(uid, "EmitterBolt")
- || HasComp(uid))
- return;
-
- if (TryComp(smUid, out var sm))
- sm.AVExternalDamage += 1f;
-
- _sound.PlayPvs(VaporizeSound, smUid);
- EntityManager.QueueDeleteEntity(uid);
-
- // getting discombobulated by the SM is the same as permanent round removal so why not log that
- _adminLogger.Add(LogType.Action, LogImpact.High, $"{EntityManager.ToPrettyString(uid):player} has been vaporized by the supermatter.");
- }
-
- ///
- /// Handle supermatter delamination and the end of the station.
- ///
- private void Delaminate(EntityUid uid, SupermatterComponent sm)
- {
- sm.PreferredDelamType = sm.PreferredDelamType ?? (int)ChooseDelam(sm);
- Delaminate(uid, sm, (DelamType)sm.PreferredDelamType);
- }
-
- ///
- /// Handle supermatter delamination based on it's type.
- ///
- private void Delaminate(EntityUid uid, SupermatterComponent sm, DelamType type)
- {
- GenerateAnomaly(uid, _random.Next(2, 4));
-
- var prototypeId = string.Empty;
- switch (type)
- {
- case DelamType.Explosion:
- default:
- _explosion.TriggerExplosive(uid); return;
- case DelamType.Tesla:
- prototypeId = sm.TeslaPrototype; break;
- case DelamType.Singularity:
- prototypeId = sm.SingularityPrototype; break;
- case DelamType.ResonanceCascade:
- prototypeId = sm.SupermatterKudzuPrototype; break;
- }
- if (string.IsNullOrWhiteSpace(prototypeId))
- return;
- EntityManager.SpawnEntity(prototypeId, Transform(uid).Coordinates);
- }
-
- ///
- /// Choose a prefered delamination type. The supermatter is picky.
- ///
- private DelamType ChooseDelam(SupermatterComponent sm)
- {
- if (sm.AbsorbedGasMix.TotalMoles >= SupermatterComponent.MolePenaltyThreshold)
- return DelamType.Singularity;
-
- if (sm.InternalEnergy > SupermatterComponent.PowerPenaltyThreshold)
- return DelamType.Tesla;
-
- // todo: add resonance cascade when hypernob and antinob gases get added
- // or a destabilizing crystal. bet it will take years :godo:
-
- return DelamType.Explosion;
- }
- ///
- /// Handle the delamination countdown, alerts, etc.
- ///
- private void DelamCountdown(EntityUid uid, SupermatterComponent sm)
- {
- if (!sm.DelamAnnouncementHappened)
- {
- var delamType = ChooseDelam(sm);
- var stationUid = _station.GetStationInMap(Transform(uid).MapID);
-
- var alertLevel = string.Empty;
- var announcementLoc = string.Empty;
-
- var sb = new StringBuilder();
- sb.Append(Loc.GetString("supermatter-announcement-delam"));
- switch (delamType)
- {
- case DelamType.Explosion:
- default:
- announcementLoc = "supermatter-announcement-delam-explosion";
- alertLevel = "yellow";
- break;
- case DelamType.Tesla:
- announcementLoc = "supermatter-announcement-delam-tesla";
- alertLevel = "delta";
- break;
- case DelamType.Singularity:
- announcementLoc = "supermatter-announcement-delam-singuloose";
- alertLevel = "delta";
- break;
- case DelamType.ResonanceCascade:
- announcementLoc = "supermatter-announcement-delam-cascade";
- alertLevel = "delta";
- break;
- }
- sb.AppendLine(" " + Loc.GetString(announcementLoc));
- sb.Append(Loc.GetString("supermatter-announcement-delam-countdown", ("seconds", sm.DelamCountdownTimer)));
- // make it cancellable in case there are crazy engineers that managed to contain the delam
- if (stationUid != null)
- _alert.SetLevel(stationUid.Value, alertLevel, true, true, true, false);
-
- SupermatterAlert(uid, sb.ToString());
-
- sm.DelamAnnouncementHappened = true;
- }
-
- if (sm.Damage < sm.DelaminationPoint)
- {
- // yay!
- sm.DelamCountdownAccumulator = 0;
- sm.DelamAnnouncementHappened = false;
- sm.AreWeDelaming = false;
- SupermatterAlert(uid, Loc.GetString("supermatter-announcement-safe"));
- return;
- }
- if (sm.DelamCountdownAccumulator >= sm.DelamCountdownTimer) // uh oh
- Delaminate(uid, sm);
- sm.DelamCountdownAccumulator++;
- }
-
- private void OnCollide(EntityUid uid, SupermatterComponent sm, StartCollideEvent args)
- {
- if (!sm.Activated)
- sm.Activated = true;
-
- Vaporize(args.OtherEntity, uid);
- }
-
- private void OnClick(EntityUid uid, SupermatterComponent sm, InteractUsingEvent args)
- {
- if (HasComp(args.Used))
- {
- if (sm.Damage >= 100)
- {
- _popup.PopupEntity(Loc.GetString("supermatter-tamper-fail"), args.User, args.User);
- return;
- }
-
- if (HasComp(args.Used))
- {
- _adminLogger.Add(LogType.Action, LogImpact.High, $"{EntityManager.ToPrettyString(args.User):player} is trying to extract a sliver from the supermatter crystal.");
- _popup.PopupEntity(Loc.GetString("supermatter-tamper-begin"), args.User, args.User);
-
- var doAfterArgs = new DoAfterArgs(EntityManager, args.User, 30, new SupermatterDoAfterEvent(), uid, target: uid, used: args.Used)
- {
- BreakOnDamage = true,
- BreakOnHandChange = true,
- BreakOnMove = true,
- BreakOnWeightlessMove = false,
- NeedHand = true,
- RequireCanInteract = true,
- };
-
- _doAfter.TryStartDoAfter(doAfterArgs);
- }
- else
- {
- Vaporize(args.Used, uid);
- }
- }
- }
-
- private void OnGetSliver(EntityUid uid, SupermatterComponent sm, SupermatterDoAfterEvent args)
- {
- if (args.Cancelled)
- return;
-
- sm.Damage += 10; // your criminal actions will not go unnoticed
- SupermatterAlert(uid, Loc.GetString("supermatter-announcement-tamper", ("integrity", (int)(100 - sm.Damage))));
-
- Spawn(sm.SliverPrototype, _transform.GetMapCoordinates(args.User));
- _popup.PopupEntity(Loc.GetString("supermatter-tamper-end"), args.User, args.User);
- }
-
- private void OnGetHit(EntityUid uid, SupermatterComponent sm, DamageChangedEvent args)
- {
- if (!sm.Activated)
- sm.Activated = true;
-
- sm.AVExternalDamage += args.DamageDelta?.GetTotal().Value / 100 ?? 0;
- }
-
- private void OnExamine(EntityUid uid, SupermatterComponent sm, ExaminedEvent args)
- {
- if (args.IsInDetailsRange) // get all close to it
- {
- args.PushMarkup(Loc.GetString("supermatter-examine-integrity", ("integrity", (int)(100 - sm.Damage))));
- }
- }
-}
diff --git a/Content.Server/_Starlight/Energy/Supermatter/Const.cs b/Content.Server/_Starlight/Energy/Supermatter/Const.cs
new file mode 100644
index 0000000000..f8daae6290
--- /dev/null
+++ b/Content.Server/_Starlight/Energy/Supermatter/Const.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Content.Shared.Atmos;
+using Content.Shared.FixedPoint;
+using Robust.Shared.Physics;
+
+namespace Content.Server.Starlight.Energy.Supermatter;
+internal static class Const
+{
+ public static FixedPoint2 HeatPercent = 0.82f;
+ public static FixedPoint2 BreakPercent = 0.04f;
+ public static FixedPoint2 LightingPercent = 0.03f;
+ public static FixedPoint2 RadiationPercent = 0.11f;
+
+ public static FixedPoint2 DamageMultiplayer = 3.14f;
+
+ public static GasProperties[] GasProperties =
+ [
+ new (0.24f, 1.20f, 1.4f), // oxygen
+ new (0.20f, 1.46f, 1.5f), // nitrogen
+ new (0.12f, 2.21f, 3.5f), // carbon dioxide
+ new (0.60f, 0.61f, 1.3f), // plasma
+ new (0.30f, 0.45f, 1.2f), // tritium
+ new (0.14f, 2.31f, 2.5f), // vapor
+ new (0.16f, 2.11f, 4.4f), // ommonium
+ new (0.13f, 2.19f, 2.2f), // nitrous oxide
+ new (1.00f, 0.01f, 1.1f), // frezon
+ ];
+
+ public static float MinPressure = 33f;
+ public static float MaxPressure = 303.9f;
+
+ public static float MaxTemperature = Atmospherics.T0C + 150;
+
+ public static float EvaporationCompensation = 10;
+
+ public static FixedPoint2 MaxDamagePerSecond = (100f / 120f) + RegenerationPerSecond; // Ensures it takes at least 2 minutes to deplete
+ public static FixedPoint2 RegenerationPerSecond = 0.3f;
+
+ public static string[] AudioCrack = ["/Audio/_Starlight/Effects/supermatter/crystal_crack_1.ogg", "/Audio/_Starlight/Effects/supermatter/crystal_crack_2.ogg"];
+ public static string[] AudioBurn = ["/Audio/_Starlight/Effects/supermatter/burning_1.ogg", "/Audio/_Starlight/Effects/supermatter/burning_2.ogg", "/Audio/_Starlight/Effects/supermatter/burning_3.ogg"];
+ public static string AudioEvaporate = "/Audio/_Starlight/Effects/supermatter/emitter2.ogg";
+}
+public record struct GasProperties(float HeatTransferPerMole, float HeatModifier, float RadiationStability);
diff --git a/Content.Server/_Starlight/Energy/Supermatter/SupermatterCascadeSystem.cs b/Content.Server/_Starlight/Energy/Supermatter/SupermatterCascadeSystem.cs
new file mode 100644
index 0000000000..09996cc5e6
--- /dev/null
+++ b/Content.Server/_Starlight/Energy/Supermatter/SupermatterCascadeSystem.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Linq;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Chat.Managers;
+using Content.Server.Lightning;
+using Content.Server.Radio.EntitySystems;
+using Content.Server.Starlight.Energy.Supermatter;
+using Content.Shared.Abilities.Goliath;
+using Content.Shared.Atmos;
+using Content.Shared.Coordinates.Helpers;
+using Content.Shared.Directions;
+using Content.Shared.Maps;
+using Content.Shared.Physics;
+using Content.Shared.Random.Helpers;
+using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
+using Robust.Shared.Random;
+
+namespace Content.Server.Starlight.Energy.Supermatter;
+
+public sealed class SupermatterCascadeSystem : EntitySystem
+{
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly SharedMapSystem _map = default!;
+ [Dependency] private readonly EntityLookupSystem _lookup = default!;
+
+ private readonly LinkedList _branches = [];
+ private LinkedListNode? node;
+ private readonly string[] _prototypes = ["Cascad1", "Cascad2", "Cascad3", "Cascad4", "Cascad5", "Cascad6"];
+ public override void Initialize()
+ {
+ }
+
+ public override void Update(float frameTime)
+ {
+ node ??= _branches.First;
+ if (node == null) return;
+ var branch = node.Value;
+ var nextNode = node.Next;
+
+ branch.Lifetime--;
+ if (branch.Lifetime <= 0)
+ {
+ _branches.Remove(node);
+ node = nextNode;
+ return;
+ }
+
+ var rand = _random.Next(0, 100);
+
+ if (rand < 10)
+ {
+ branch.Direction = branch.RotateLeft();
+ }
+ else if (rand < 20)
+ {
+ branch.Direction = branch.RotateRight();
+ }
+ else if (rand < 25 && _branches.Count < 10)
+ {
+ var leftBranch = new Branch
+ {
+ Coordinates = branch.Coordinates,
+ Direction = branch.RotateLeft(),
+ Lifetime = branch.Lifetime
+ };
+ var rightBranch = new Branch
+ {
+ Coordinates = branch.Coordinates,
+ Direction = branch.RotateRight(),
+ Lifetime = branch.Lifetime
+ };
+
+ _branches.AddLast(leftBranch);
+ _branches.AddLast(rightBranch);
+
+ _branches.Remove(node);
+ node = nextNode;
+ return;
+ }
+
+ branch.Coordinates = branch.Coordinates.Offset(branch.Direction);
+ if (_transform.GetGrid(branch.Coordinates) is not { } grid
+ || !TryComp(grid, out var gridComp)
+ || !_map.TryGetTileRef(grid, gridComp, branch.Coordinates, out var tileRef)
+ || tileRef.IsSpace())
+ {
+ _branches.Remove(node);
+ node = nextNode;
+ return;
+ }
+ branch.Coordinates = branch.Coordinates.SnapToGrid(gridComp);
+
+ foreach (var entity in _lookup.GetEntitiesIntersecting(branch.Coordinates))
+ QueueDel(entity);
+
+ SpawnAttachedTo(_random.Pick(_prototypes), branch.Coordinates);
+
+ node = nextNode;
+ }
+
+ public void StartCascade(EntityCoordinates coordinates)
+ {
+ for (int i = 0; i < 8; i += 2)
+ _branches.AddLast(new Branch
+ {
+ Coordinates = coordinates,
+ Direction = (Direction)i,
+ Lifetime = 100
+ });
+ }
+
+ private sealed class Branch
+ {
+ public EntityCoordinates Coordinates { get; set; }
+ public Direction Direction { get; set; }
+ public int Lifetime { get; set; }
+
+ public Direction RotateLeft() => Direction switch
+ {
+ Direction.North => Direction.NorthWest,
+ Direction.NorthWest => Direction.West,
+ Direction.West => Direction.SouthWest,
+ Direction.SouthWest => Direction.South,
+ Direction.South => Direction.SouthEast,
+ Direction.SouthEast => Direction.East,
+ Direction.East => Direction.NorthEast,
+ Direction.NorthEast => Direction.North,
+ _ => Direction,
+ };
+
+ public Direction RotateRight() => Direction switch
+ {
+ Direction.North => Direction.NorthEast,
+ Direction.NorthEast => Direction.East,
+ Direction.East => Direction.SouthEast,
+ Direction.SouthEast => Direction.South,
+ Direction.South => Direction.SouthWest,
+ Direction.SouthWest => Direction.West,
+ Direction.West => Direction.NorthWest,
+ Direction.NorthWest => Direction.North,
+ _ => Direction,
+ };
+ }
+}
\ No newline at end of file
diff --git a/Content.Server/_Starlight/Energy/Supermatter/SupermatterSystem.cs b/Content.Server/_Starlight/Energy/Supermatter/SupermatterSystem.cs
new file mode 100644
index 0000000000..a3d819c763
--- /dev/null
+++ b/Content.Server/_Starlight/Energy/Supermatter/SupermatterSystem.cs
@@ -0,0 +1,242 @@
+using System;
+using System.Linq;
+using Content.Server.Atmos.EntitySystems;
+using Content.Server.Chat.Managers;
+using Content.Server.Lightning;
+using Content.Server.Radio.EntitySystems;
+using Content.Server.Starlight.Energy.Supermatter;
+using Content.Shared.Abilities.Goliath;
+using Content.Shared.Atmos;
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Content.Shared.FixedPoint;
+using Content.Shared.Ghost;
+using Content.Shared.Interaction;
+using Content.Shared.Projectiles;
+using Content.Shared.Radiation.Components;
+using Content.Shared.Radio;
+using Content.Shared.Singularity.Components;
+using Content.Shared.Starlight.Energy.Supermatter;
+using Microsoft.CodeAnalysis;
+using Robust.Server.Audio;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Events;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+using Robust.Shared.Toolshed.TypeParsers;
+
+namespace Content.Server.Starlight.Energy.Supermatter;
+
+public sealed class SupermatterSystem : AccUpdateEntitySystem
+{
+ [Dependency] private readonly DamageableSystem _damageable = default!;
+ [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly LightningSystem _lightning = default!;
+ [Dependency] private readonly RadioSystem _radioSystem = default!;
+ [Dependency] private readonly SupermatterCascadeSystem _cascade = default!;
+ [Dependency] private readonly IChatManager _chat = default!;
+ [Dependency] private readonly IPrototypeManager _prototypes = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+
+ private readonly Dictionary> _supermatters = [];
+ private DamageGroupPrototype? _brute;
+ private DamageGroupPrototype? _burn;
+ private RadioChannelPrototype? _engi;
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(AddSupermatter);
+ SubscribeLocalEvent(RemoveSupermatter);
+
+ SubscribeLocalEvent(OnCollide);
+ SubscribeLocalEvent(OnInteract);
+ }
+
+ private void OnInteract(Entity ent, ref InteractHandEvent args)
+ {
+ if (HasComp(args.User)) return;
+
+ _audio.PlayPvs(Const.AudioEvaporate, ent.Owner);
+
+ float damage = 1;
+ if (TryComp(args.User, out var fixture))
+ damage = fixture.Fixtures.Select(x => x.Value.Density).Aggregate((i, p) => p + i) / 3;
+
+ _burn ??= _prototypes.Index("Burn");
+ _damageable.TryChangeDamage(ent.Owner, new(_burn, damage), true);
+
+ QueueDel(args.User);
+ }
+
+ private void OnCollide(Entity ent, ref EndCollideEvent args)
+ {
+ ent.Comp.Activated = true;
+
+ if (HasComp(args.OtherEntity)
+ || HasComp(args.OtherEntity)) return;
+
+ _audio.PlayPvs(Const.AudioEvaporate, ent.Owner);
+ float damage = 1;
+ if (TryComp(args.OtherEntity, out var fixture))
+ damage = fixture.Fixtures.Select(x => x.Value.Density).Aggregate((i, p) => p + i) / 3;
+
+ _burn ??= _prototypes.Index("Burn");
+ _damageable.TryChangeDamage(ent.Owner, new(_burn, damage), true);
+
+ QueueDel(args.OtherEntity);
+ }
+ private void AddSupermatter(Entity ent, ref ComponentInit args) => _supermatters.TryAdd(ent.Owner, ent);
+ private void RemoveSupermatter(Entity ent, ref ComponentShutdown args) => _supermatters.Remove(ent.Owner);
+
+ protected override float Threshold { get; set; } = 1f;
+ protected override void AccUpdate()
+ {
+ foreach (var supermatter in _supermatters)
+ Handle(supermatter.Value);
+ }
+
+ private void Handle(Entity supermatter)
+ {
+ if (!supermatter.Comp.Activated) return;
+
+ HandleDamage(supermatter);
+ HandleGas(supermatter);
+ HandleRadiation(supermatter);
+ HandleLighting(supermatter);
+ HandleDestruction(supermatter);
+ NotifyCascad(supermatter);
+ Cascad(supermatter);
+ }
+
+ private void Cascad(Entity supermatter)
+ {
+ if (supermatter.Comp.Durability > 0.01) return;
+
+ _cascade.StartCascade(Transform(supermatter.Owner).Coordinates);
+ QueueDel(supermatter.Owner);
+ }
+
+ private void NotifyCascad(Entity supermatter)
+ {
+ var currentDurability = (int)Math.Floor(supermatter.Comp.Durability.Float());
+ var lastDurability = (int)Math.Floor(supermatter.Comp.LastSendedDurability.Float());
+ _engi ??= _prototypes.Index("Engineering");
+
+ if (Math.Abs(currentDurability - lastDurability) < 5)
+ return;
+
+ supermatter.Comp.LastSendedDurability = supermatter.Comp.Durability;
+
+ if (currentDurability > lastDurability)
+ _radioSystem.SendRadioMessage(supermatter.Owner, $"The crystal is regenerating. Durability: {currentDurability}%", _engi, supermatter.Owner);
+ else switch (currentDurability)
+ {
+ case > 75: _radioSystem.SendRadioMessage(supermatter.Owner, $"Attention! The crystal is destabilizing. Durability: {currentDurability}%", _engi, supermatter.Owner); break;
+ case > 50: _chat.DispatchServerAnnouncement($"Attention! The crystal is destabilizing. Durability: {currentDurability}%", Color.Yellow); break;
+ case > 25: _chat.DispatchServerAnnouncement($"Critical state of the crystal! Durability: {currentDurability}%", Color.OrangeRed); break;
+ default: _chat.DispatchServerAnnouncement($"Crystal destruction is inevitable. Current durability: {currentDurability}%", Color.Red); break;
+ }
+ }
+
+ private void HandleDestruction(Entity supermatter)
+ {
+ var damageToApply = MathHelper.Clamp((supermatter.Comp.AccBreak / 10) - Const.RegenerationPerSecond, -Const.RegenerationPerSecond, Const.MaxDamagePerSecond);
+ supermatter.Comp.AccBreak = 0;
+
+ supermatter.Comp.Durability = MathHelper.Clamp(supermatter.Comp.Durability - damageToApply, 0f, 100f);
+ }
+
+ private void HandleLighting(Entity supermatter)
+ {
+ if (supermatter.Comp.AccLighting != 0
+ && _lightning.ShootRandomLightnings(supermatter.Owner, supermatter.Comp.AccLighting.Float(), 1))
+ supermatter.Comp.AccLighting = 0;
+ }
+
+ private void HandleRadiation(Entity supermatter)
+ {
+ var radComp = EnsureComp(supermatter.Owner);
+ radComp.Intensity = supermatter.Comp.AccRadiation.Float();
+
+ supermatter.Comp.AccRadiation /= supermatter.Comp.RadiationStability;
+ }
+
+ private void HandleGas(Entity supermatter)
+ {
+ var gas = _atmosphere.GetTileMixture(supermatter.Owner, true) ?? new();
+ DamageByPressure(supermatter, gas);
+ DamageByTemperature(supermatter, gas);
+
+ if (gas.TotalMoles < 1) return;
+
+ float heatTransfer = 0;
+ float heatModifier = 0;
+ float radiationStability = 0;
+
+ for (var i = 0; i < Const.GasProperties.Length; i++)
+ {
+ var prop = Const.GasProperties[i];
+ var percent = Math.Clamp(gas.Moles[i] / gas.TotalMoles, 0, 1);
+ heatTransfer += prop.HeatTransferPerMole * gas.Moles[i];
+ heatModifier += prop.HeatModifier * percent;
+ radiationStability += prop.RadiationStability * percent;
+ }
+
+ supermatter.Comp.RadiationStability = MathHelper.Clamp(radiationStability, 1, 10);
+
+ ProcessHeat(supermatter, gas, heatTransfer, heatModifier);
+ TryCompensateDamage(supermatter, gas);
+ }
+
+ private static void TryCompensateDamage(Entity supermatter, GasMixture gas)
+ {
+ var breakDelta = supermatter.Comp.AccBreak > Const.EvaporationCompensation ? Const.EvaporationCompensation : supermatter.Comp.AccBreak;
+ if (breakDelta == 0) return;
+ supermatter.Comp.AccBreak -= breakDelta;
+
+ gas.AdjustMoles((int)Gas.Tritium, breakDelta.Float()/2);
+
+ gas.AdjustMoles((int)Gas.Oxygen, breakDelta.Float()*4);
+ }
+
+ private static void ProcessHeat(Entity supermatter, GasMixture gas, float heatTransfer, float heatModifier)
+ {
+ var accHeat = supermatter.Comp.AccHeat.Float();
+ var heatDelta = heatTransfer <= accHeat ? heatTransfer : accHeat;
+
+ accHeat = MathHelper.Clamp(accHeat - heatDelta, 0, 9999); ;
+ supermatter.Comp.AccHeat = 0;
+ gas.Temperature += heatDelta * heatModifier;
+ supermatter.Comp.AccBreak += accHeat;
+ }
+
+ private void DamageByTemperature(Entity supermatter, GasMixture gas)
+ {
+ if (gas.Temperature <= Const.MaxTemperature) return;
+ _audio.PlayPvs(_random.Pick(Const.AudioBurn), supermatter.Owner);
+ _burn ??= _prototypes.Index("Burn");
+ DamageSpecifier damage = new(_burn, Const.MaxTemperature - gas.Temperature);
+ _damageable.TryChangeDamage(supermatter.Owner, damage, true);
+ }
+
+ private void DamageByPressure(Entity supermatter, GasMixture gas)
+ {
+ if (gas.Pressure >= Const.MinPressure && gas.Pressure <= Const.MaxPressure) return;
+ _audio.PlayPvs(_random.Pick(Const.AudioCrack), supermatter.Owner);
+ _brute ??= _prototypes.Index("Brute");
+ DamageSpecifier damage = new(_brute, Math.Max(Const.MinPressure - gas.Pressure, gas.Pressure - Const.MaxPressure) / 100);
+ _damageable.TryChangeDamage(supermatter.Owner, damage, true);
+ }
+
+ private void HandleDamage(Entity supermatter)
+ {
+ EnsureComp(supermatter.Owner, out var damageable);
+ var trueDamage = damageable.TotalDamage * Const.DamageMultiplayer;
+ _damageable.TryChangeDamage(supermatter.Owner, damageable.Damage.Invert(), true);
+
+ supermatter.Comp.AccBreak = MathHelper.Clamp(supermatter.Comp.AccBreak + (trueDamage * Const.BreakPercent), 0, 9999);
+ supermatter.Comp.AccHeat = MathHelper.Clamp(supermatter.Comp.AccHeat + (trueDamage * Const.HeatPercent), 0, 9999);
+ supermatter.Comp.AccLighting = MathHelper.Clamp(supermatter.Comp.AccLighting + (trueDamage * Const.LightingPercent), 0, 25);
+ supermatter.Comp.AccRadiation = MathHelper.Clamp(supermatter.Comp.AccRadiation + (trueDamage * Const.RadiationPercent), 0, 100);
+ }
+}
diff --git a/Content.Shared/Atmos/GasMixture.cs b/Content.Shared/Atmos/GasMixture.cs
index 612626d614..7ecb934b58 100644
--- a/Content.Shared/Atmos/GasMixture.cs
+++ b/Content.Shared/Atmos/GasMixture.cs
@@ -19,7 +19,7 @@ namespace Content.Shared.Atmos
public static GasMixture SpaceGas => new() {Volume = Atmospherics.CellVolume, Temperature = Atmospherics.TCMB, Immutable = true};
// No access, to ensure immutable mixtures are never accidentally mutated.
- [Access(typeof(SharedAtmosphereSystem), typeof(SharedAtmosDebugOverlaySystem), typeof(GasEnumerator), Other = AccessPermissions.None)]
+ [Access(typeof(SharedAtmosphereSystem), typeof(SharedAtmosDebugOverlaySystem), typeof(GasEnumerator), Other = AccessPermissions.Read)] // Sunrise-Edit
[DataField]
public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
diff --git a/Content.Shared/Construction/Components/FlatpackComponent.cs b/Content.Shared/Construction/Components/FlatpackComponent.cs
index 5cb178075b..5a877064bd 100644
--- a/Content.Shared/Construction/Components/FlatpackComponent.cs
+++ b/Content.Shared/Construction/Components/FlatpackComponent.cs
@@ -19,6 +19,12 @@ public sealed partial class FlatpackComponent : Component
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public ProtoId QualityNeeded = "Pulsing";
+ ///
+ /// Is Flatpack allowed to unpuck on tables? (For microwaves, etc.)
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool AllowUnpackOnTables = false; // Starlight-edit
+
///
/// The entity that is spawned when this object is unpacked.
///
diff --git a/Content.Shared/Construction/SharedFlatpackSystem.cs b/Content.Shared/Construction/SharedFlatpackSystem.cs
index f3358031d2..7372cc0a6c 100644
--- a/Content.Shared/Construction/SharedFlatpackSystem.cs
+++ b/Content.Shared/Construction/SharedFlatpackSystem.cs
@@ -1,4 +1,5 @@
using Content.Shared._Sunrise.Economy;
+using System.Linq;
using Content.Shared.Construction.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
@@ -6,6 +7,7 @@ using Content.Shared.Database;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Materials;
+using Content.Shared.Tag;
using Content.Shared.Popups;
using Content.Shared.Tools.Systems;
using Robust.Shared.Audio.Systems;
@@ -31,6 +33,7 @@ public abstract class SharedFlatpackSystem : EntitySystem
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedToolSystem _tool = default!;
+ [Dependency] private readonly TagSystem _tag = default!;
///
public override void Initialize()
@@ -80,10 +83,12 @@ public abstract class SharedFlatpackSystem : EntitySystem
var buildPos = _map.TileIndicesFor(grid, gridComp, xform.Coordinates);
var coords = _map.ToCenterCoordinates(grid, buildPos);
- // TODO FLATPAK
- // Make this logic smarter. This should eventually allow for shit like building microwaves on tables and such.
- // Also: make it ignore ghosts
- if (_entityLookup.AnyEntitiesIntersecting(coords, LookupFlags.Dynamic | LookupFlags.Static))
+ // TODO FLATPACK
+ // make it ignore ghosts
+ // Starlight-start
+ if (_entityLookup.GetEntitiesIntersecting(coords, LookupFlags.Dynamic | LookupFlags.Static)
+ .Any(entity => entity != uid && (!_tag.HasTag(entity, "Table") || !ent.Comp.AllowUnpackOnTables)))
+ // Starlight-end
{
// this popup is on the server because the predicts on the intersection is crazy
if (_net.IsServer)
diff --git a/Content.Shared/Supermatter/SupermatterDoAfterEvent.cs b/Content.Shared/Supermatter/SupermatterDoAfterEvent.cs
deleted file mode 100644
index addc07b721..0000000000
--- a/Content.Shared/Supermatter/SupermatterDoAfterEvent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Content.Shared.DoAfter;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Supermatter;
-
-[Serializable, NetSerializable]
-public sealed partial class SupermatterDoAfterEvent : SimpleDoAfterEvent
-{
-
-}
diff --git a/Content.Shared/_Starlight/Abstract/AccUpdateEntitySystem.cs b/Content.Shared/_Starlight/Abstract/AccUpdateEntitySystem.cs
new file mode 100644
index 0000000000..3d17d54725
--- /dev/null
+++ b/Content.Shared/_Starlight/Abstract/AccUpdateEntitySystem.cs
@@ -0,0 +1,19 @@
+namespace Content.Shared.Abilities.Goliath;
+
+public abstract class AccUpdateEntitySystem : EntitySystem
+{
+ public override void Update(float frameTime)
+ {
+ _accumulator += frameTime;
+ if (_accumulator > Threshold)
+ {
+ AccUpdate();
+ _accumulator = 0;
+ }
+ }
+ protected virtual void AccUpdate()
+ {
+ }
+ protected virtual float Threshold { get; set; } = 0.35f;
+ private float _accumulator = 0f;
+}
diff --git a/Content.Shared/_Starlight/Energy/Supermatter/SupermatterComponent.cs b/Content.Shared/_Starlight/Energy/Supermatter/SupermatterComponent.cs
new file mode 100644
index 0000000000..0f79da5a8f
--- /dev/null
+++ b/Content.Shared/_Starlight/Energy/Supermatter/SupermatterComponent.cs
@@ -0,0 +1,33 @@
+using Content.Shared.FixedPoint;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Starlight.Energy.Supermatter;
+
+[RegisterComponent, NetworkedComponent]
+public sealed partial class SupermatterComponent : Component
+{
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool Activated = false;
+
+ [ViewVariables(VVAccess.ReadOnly)]
+ public FixedPoint2 AccHeat = 0f;
+
+ [ViewVariables(VVAccess.ReadOnly)]
+ public FixedPoint2 AccRadiation = 0f;
+
+ [ViewVariables(VVAccess.ReadOnly)]
+ public FixedPoint2 AccLighting = 0f;
+
+ [ViewVariables(VVAccess.ReadOnly)]
+ public FixedPoint2 AccBreak = 0f;
+
+ [ViewVariables(VVAccess.ReadOnly)]
+ public FixedPoint2 RadiationStability = 1f;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 Durability = 100f;
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 LastSendedDurability = 100f;
+}
diff --git a/Resources/Audio/Ambience/Objects/attributions.yml b/Resources/Audio/Ambience/Objects/attributions.yml
index 1e1d03d4f0..e5cd81a372 100644
--- a/Resources/Audio/Ambience/Objects/attributions.yml
+++ b/Resources/Audio/Ambience/Objects/attributions.yml
@@ -62,8 +62,3 @@
license: "CC-BY-4.0"
copyright: "Taken and edited from source"
source: "https://freesound.org/people/juskiddink/sounds/215658/"
-
-- files: ["supermatter_calm.ogg", "supermatter_delam.ogg"]
- license: "CC-BY-SA-3.0"
- copyright: "Taken from source"
- source: "https://github.com/tgstation/tgstation/blob/master/sound/machines/sm/loops"
\ No newline at end of file
diff --git a/Resources/Audio/Ambience/Objects/supermatter_calm.ogg b/Resources/Audio/Ambience/Objects/supermatter_calm.ogg
deleted file mode 100644
index cee14fcd13..0000000000
Binary files a/Resources/Audio/Ambience/Objects/supermatter_calm.ogg and /dev/null differ
diff --git a/Resources/Audio/Ambience/Objects/supermatter_delam.ogg b/Resources/Audio/Ambience/Objects/supermatter_delam.ogg
deleted file mode 100644
index 7d79f0e3c4..0000000000
Binary files a/Resources/Audio/Ambience/Objects/supermatter_delam.ogg and /dev/null differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/attributions.yml b/Resources/Audio/_Starlight/Effects/supermatter/attributions.yml
new file mode 100644
index 0000000000..77ea07bf56
--- /dev/null
+++ b/Resources/Audio/_Starlight/Effects/supermatter/attributions.yml
@@ -0,0 +1,9 @@
+- files: ["crystal_crack_1.ogg","crystal_crack_2.ogg", "burning_1.ogg", "burning_2.ogg", "burning_3.ogg"]
+ license: "CC-BY-4.0"
+ copyright: 'Darkrell'
+ source: "https://github.com/ss14Starlight/space-station-14"
+
+- files: ["emitter2.ogg"]
+ license: "CC-BY-SA-3.0"
+ copyright: "Taken from tgstation"
+ source: "https://github.com/tgstation/tgstation/blob/master/sound/weapons/emitter2.ogg"
\ No newline at end of file
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/burning_1.ogg b/Resources/Audio/_Starlight/Effects/supermatter/burning_1.ogg
new file mode 100644
index 0000000000..7a89578111
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/burning_1.ogg differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/burning_2.ogg b/Resources/Audio/_Starlight/Effects/supermatter/burning_2.ogg
new file mode 100644
index 0000000000..5b1bd5358f
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/burning_2.ogg differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/burning_3.ogg b/Resources/Audio/_Starlight/Effects/supermatter/burning_3.ogg
new file mode 100644
index 0000000000..23ac1ea231
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/burning_3.ogg differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_1.ogg b/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_1.ogg
new file mode 100644
index 0000000000..d816fa6312
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_1.ogg differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_2.ogg b/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_2.ogg
new file mode 100644
index 0000000000..eaba292527
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/crystal_crack_2.ogg differ
diff --git a/Resources/Audio/_Starlight/Effects/supermatter/emitter2.ogg b/Resources/Audio/_Starlight/Effects/supermatter/emitter2.ogg
new file mode 100644
index 0000000000..4cba77cd96
Binary files /dev/null and b/Resources/Audio/_Starlight/Effects/supermatter/emitter2.ogg differ
diff --git a/Resources/Locale/en-US/_prototypes/_sunrise/objectives/traitorObjectives.ftl b/Resources/Locale/en-US/_prototypes/_sunrise/objectives/traitorObjectives.ftl
index ee9f06a0cf..0e14422eb5 100644
--- a/Resources/Locale/en-US/_prototypes/_sunrise/objectives/traitorObjectives.ftl
+++ b/Resources/Locale/en-US/_prototypes/_sunrise/objectives/traitorObjectives.ftl
@@ -4,7 +4,5 @@ ent-CMOAdvancedDefibrillatorStealObjective = { ent-BaseCMOStealObjective }
.desc = { ent-BaseCMOStealObjective.desc }
ent-PlutoniumCoreStealObjective = { ent-BaseTraitorStealObjective }
.desc = { ent-BaseTraitorStealObjective.desc }
-ent-StealSupermatterSliverObjective = { ent-BaseTraitorStealObjective }
- .desc = { ent-BaseTraitorStealObjective.desc }
ent-HandheldFaxStealObjective = { ent-BaseTraitorStealObjective }
.desc = { ent-BaseTraitorStealObjective.desc }
diff --git a/Resources/Locale/en-US/_prototypes/entities/objects/misc/supermatter_sliver.ftl b/Resources/Locale/en-US/_prototypes/entities/objects/misc/supermatter_sliver.ftl
deleted file mode 100644
index 0892c1911a..0000000000
--- a/Resources/Locale/en-US/_prototypes/entities/objects/misc/supermatter_sliver.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-ent-SupermatterSliver = supermatter sliver
- .desc = A shard from the station's supermatter engine. Highly radioactive.
diff --git a/Resources/Locale/en-US/_strings/_sunrise/objectives/steal.ftl b/Resources/Locale/en-US/_strings/_sunrise/objectives/steal.ftl
index 9e070174a3..0a97aa4fa5 100644
--- a/Resources/Locale/en-US/_strings/_sunrise/objectives/steal.ftl
+++ b/Resources/Locale/en-US/_strings/_sunrise/objectives/steal.ftl
@@ -1,5 +1,4 @@
objective-condition-steal-nuclear-bomb = nuclear bomb
-objective-condition-steal-supermatter-sliver = Отрежьте кусочек от кристалла суперматерии.
objective-description-steal-supermatter-sliver = Используйте любой подходящий режущий инструмент. Лучше всего подойдёт скальпель. И постарайтесь не умереть от радиационного отравления.
objective-description-steal-handheld-fax = You need to steal a portable fax machine from a corporate representative.
objective-condition-steal-handheld-fax = Portable fax
diff --git a/Resources/Locale/ru-RU/_prototypes/_sunrise/objectives/traitorObjectives.ftl b/Resources/Locale/ru-RU/_prototypes/_sunrise/objectives/traitorObjectives.ftl
index ee9f06a0cf..0e14422eb5 100644
--- a/Resources/Locale/ru-RU/_prototypes/_sunrise/objectives/traitorObjectives.ftl
+++ b/Resources/Locale/ru-RU/_prototypes/_sunrise/objectives/traitorObjectives.ftl
@@ -4,7 +4,5 @@ ent-CMOAdvancedDefibrillatorStealObjective = { ent-BaseCMOStealObjective }
.desc = { ent-BaseCMOStealObjective.desc }
ent-PlutoniumCoreStealObjective = { ent-BaseTraitorStealObjective }
.desc = { ent-BaseTraitorStealObjective.desc }
-ent-StealSupermatterSliverObjective = { ent-BaseTraitorStealObjective }
- .desc = { ent-BaseTraitorStealObjective.desc }
ent-HandheldFaxStealObjective = { ent-BaseTraitorStealObjective }
.desc = { ent-BaseTraitorStealObjective.desc }
diff --git a/Resources/Locale/ru-RU/_prototypes/entities/objects/misc/supermatter_sliver.ftl b/Resources/Locale/ru-RU/_prototypes/entities/objects/misc/supermatter_sliver.ftl
deleted file mode 100644
index 7d87e34d98..0000000000
--- a/Resources/Locale/ru-RU/_prototypes/entities/objects/misc/supermatter_sliver.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-ent-SupermatterSliver = осколок суперматерии
- .desc = Осколок от кристалла суперматерии станции. Сильно радиоактивен.
diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/objectives/steal.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/objectives/steal.ftl
index c1f0f452f7..715b9f032b 100644
--- a/Resources/Locale/ru-RU/_strings/_sunrise/objectives/steal.ftl
+++ b/Resources/Locale/ru-RU/_strings/_sunrise/objectives/steal.ftl
@@ -1,3 +1,2 @@
objective-condition-steal-nuclear-bomb = ядерную бомбу
-objective-condition-steal-supermatter-sliver = Отрежьте кусочек от кристалла суперматерии.
objective-description-steal-supermatter-sliver = Используйте любой подходящий режущий инструмент. Лучше всего подойдёт скальпель. И постарайтесь не умереть от радиационного отравления.
diff --git a/Resources/Locale/ru-RU/_strings/objectives/conditions/steal-target-groups.ftl b/Resources/Locale/ru-RU/_strings/objectives/conditions/steal-target-groups.ftl
index ea87f96ef7..e2c7f9dd88 100644
--- a/Resources/Locale/ru-RU/_strings/objectives/conditions/steal-target-groups.ftl
+++ b/Resources/Locale/ru-RU/_strings/objectives/conditions/steal-target-groups.ftl
@@ -1,5 +1,4 @@
# Traitor single items
-steal-target-groups-supermatter-sliver = осколок суперматерии
steal-target-groups-hypospray = гипоспрей
steal-target-groups-handheld-crew-monitor = портативный монитор экипажа
steal-target-groups-clothing-outer-hardsuit-rd = экспериментальный исследовательский скафандр
diff --git a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml
index fe15d88942..3aedd5bf6a 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml
@@ -231,6 +231,7 @@
layers:
- state: fax-machine
- type: Flatpack
+ allowUnpackOnTables: true
entity: FaxMachineBase
- type: entity
@@ -251,6 +252,32 @@
- type: Flatpack
entity: ComputerCrewMonitoring
+- type: entity
+ parent: BaseFlatpack
+ id: MicrowaveFlatpack
+ name: microwave flatpack
+ description: A flatpack used for constructing a microwave.
+ components:
+ - type: Sprite
+ layers:
+ - state: microwave
+ - type: Flatpack
+ allowUnpackOnTables: true
+ entity: KitchenMicrowave
+
+- type: entity
+ parent: BaseFlatpack
+ id: SyndicateMicrowaveFlatpack
+ name: microwave flatpack
+ description: A flatpack used for constructing a microwave.
+ components:
+ - type: Sprite
+ layers:
+ - state: microwave
+ - type: Flatpack
+ allowUnpackOnTables: true
+ entity: SyndicateMicrowave
+
- type: entity
parent: BaseFlatpack
id: HydroponicsTrayFlatpack
diff --git a/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml b/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml
deleted file mode 100644
index ab7e1d6815..0000000000
--- a/Resources/Prototypes/Entities/Objects/Misc/supermatter_sliver.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-- type: entity
- parent: BaseItem
- id: SupermatterSliver
- name: supermatter sliver
- description: A shard from the station's supermatter engine. Highly radioactive.
- components:
- - type: PointLight
- enabled: true
- radius: 3
- energy: 2
- color: "#fff633"
- - type: RadiationSource
- intensity: 2.5
- - type: Icon
- sprite: Objects/Misc/supermatter_sliver.rsi
- state: icon
- - type: Sprite
- sprite: Objects/Misc/supermatter_sliver.rsi
- state: icon
- - type: StealTarget
- stealGroup: SupermatterSliver
- - type: Tag
- tags:
- - HighRiskItem
diff --git a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml
index 27cb4d8b68..d8c69f0646 100644
--- a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml
+++ b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml
@@ -40,6 +40,7 @@
- type: Tag
tags:
- ForceFixRotations
+ - Table
- type: entity
id: CounterBase
diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml
deleted file mode 100644
index 4e56d30a9f..0000000000
--- a/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-- type: entity
- id: SupermatterCrystal
- name: supermatter crystal
- description: A strangely translucent and iridescent crystal.
- placement:
- mode: SnapgridCenter
- components:
- - type: Supermatter
- - type: Transform
- anchored: true
- noRot: true
- - type: Damageable
- damageContainer: Inorganic
- damageModifierSet: Glass
- - type: RadiationSource
- intensity: 0 # will be set somewhere else
- - type: Physics
- bodyType: Static
- - type: Fixtures
- fixtures:
- fix1:
- shape:
- !type:PhysShapeAabb
- bounds: "-0.45,-0.45,0.45,0.45"
- density: 250
- mask:
- - FullTileMask
- layer:
- - WallLayer
- - type: CollisionWake
- enabled: false
- - type: Clickable
- - type: InteractionOutline
- - type: Sprite
- drawdepth: 2
- sprite: Structures/Power/Generation/supermatter.rsi
- state: supermatter
- - type: Icon
- sprite: Structures/Power/Generation/supermatter.rsi
- state: supermatter
- - type: PointLight
- enabled: true
- radius: 10
- energy: 5
- color: "#fff633"
- - type: AmbientSound
- range: 4
- volume: -2
- sound:
- path: /Audio/Ambience/Objects/supermatter_calm.ogg
- - type: SinguloFood
- energy: 7500
- - type: WarpPoint
- follow: true
- location: supermatter
- - type: Explosive
- explosionType: HardBomb
- totalIntensity: 10000.0
- intensitySlope: 4
- maxIntensity: 1000
diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter_kudzu.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Supermatter/supermatter_kudzu.yml
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml
index 090d2f1839..cdb98dc8bd 100644
--- a/Resources/Prototypes/Objectives/objectiveGroups.yml
+++ b/Resources/Prototypes/Objectives/objectiveGroups.yml
@@ -26,7 +26,6 @@
PlutoniumCoreStealObjective: 0.5
#MultiphaseEnergygunStealObjective: 1 # Sunrise-Edit: ОСЩ больше не появляется на станции
CMOAdvancedDefibrillatorStealObjective: 1
- StealSupermatterSliverObjective: 1
HandheldFaxStealObjective: 1
# Sunrise-End
diff --git a/Resources/Prototypes/Objectives/stealTargetGroups.yml b/Resources/Prototypes/Objectives/stealTargetGroups.yml
index f87866bdcc..b99696331c 100644
--- a/Resources/Prototypes/Objectives/stealTargetGroups.yml
+++ b/Resources/Prototypes/Objectives/stealTargetGroups.yml
@@ -1,12 +1,5 @@
# Traitor single items
-- type: stealTargetGroup
- id: SupermatterSliver
- name: steal-target-groups-supermatter-sliver
- sprite:
- sprite: Objects/Misc/supermatter_sliver.rsi
- state: icon
-
- type: stealTargetGroup
id: Hypospray
name: steal-target-groups-hypospray
diff --git a/Resources/Prototypes/_Starlight/Catalog/Cargo/cargo_engineering.yml b/Resources/Prototypes/_Starlight/Catalog/Cargo/cargo_engineering.yml
new file mode 100644
index 0000000000..b283321dfa
--- /dev/null
+++ b/Resources/Prototypes/_Starlight/Catalog/Cargo/cargo_engineering.yml
@@ -0,0 +1,9 @@
+- type: cargoProduct
+ id: SupermatterFlatpackPurchase
+ icon:
+ sprite: _Starlight/Objects/Specific/supermatter.rsi
+ state: supermatter
+ product: SupermatterFlatpack
+ cost: 8000
+ category: cargoproduct-category-name-engineering
+ group: market
diff --git a/Resources/Prototypes/_Starlight/Entities/Objects/Devices/flatpack.yml b/Resources/Prototypes/_Starlight/Entities/Objects/Devices/flatpack.yml
new file mode 100644
index 0000000000..ed9c01ed93
--- /dev/null
+++ b/Resources/Prototypes/_Starlight/Entities/Objects/Devices/flatpack.yml
@@ -0,0 +1,67 @@
+- type: entity
+ parent: BaseStructureDynamic
+ id: BaseStructureFlatpack
+ name: base structure flatpack
+ description: A flatpack used for constructing something.
+ categories:
+ - HideSpawnMenu
+ components:
+ - type: Animateable
+ - type: Transform
+ noRot: true
+ - type: Icon
+ sprite: Structures/Storage/Crates/generic.rsi
+ state: base
+ - type: Sprite
+ sprite: Objects/Devices/flatpack.rsi
+ layers:
+ - state: base
+ - state: overlay
+ color: "#cec8ac"
+ map: ["enum.FlatpackVisualLayers.Overlay"]
+ - state: icon-default
+ - type: InteractionOutline
+ - type: Physics
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.4,-0.4,0.4,0.29"
+ density: 50
+ mask:
+ - CrateMask #this is so they can go under plastic flaps
+ layer:
+ - MachineLayer
+ - type: Appearance
+ - type: Flatpack
+ boardColors:
+ command: "#334E6D"
+ medical: "#52B4E9"
+ service: "#9FED58"
+ engineering: "#EFB341"
+ security: "#DE3A3A"
+ science: "#D381C9"
+ supply: "#A46106"
+ cpu_command: "#334E6D"
+ cpu_medical: "#52B4E9"
+ cpu_service: "#9FED58"
+ cpu_engineering: "#EFB341"
+ cpu_security: "#DE3A3A"
+ cpu_science: "#D381C9"
+ cpu_supply: "#A46106"
+ - type: StaticPrice
+ price: 250
+
+- type: entity
+ parent: [BaseStructureFlatpack, BaseEngineeringContraband]
+ id: SupermatterFlatpack
+ name: supermatter flatpack
+ description: A flatpack used for constructing a Supermatter Crystal.
+ components:
+ - type: Sprite
+ sprite: Objects/Devices/flatpack.rsi
+ layers:
+ - state: large
+ - type: Flatpack
+ entity: SupermatterCrystal
\ No newline at end of file
diff --git a/Resources/Prototypes/_Starlight/Entities/Structures/Specific/supermatter.yml b/Resources/Prototypes/_Starlight/Entities/Structures/Specific/supermatter.yml
new file mode 100644
index 0000000000..637d530c63
--- /dev/null
+++ b/Resources/Prototypes/_Starlight/Entities/Structures/Specific/supermatter.yml
@@ -0,0 +1,141 @@
+- type: entity
+ id: SupermatterCrystal
+ name: supermatter
+ description: A glowing supermatter crystal, with half an ID card lying next to it, and it says "Clown pira..." on it.
+ placement:
+ mode: SnapgridCenter
+ components:
+ - type: Supermatter
+ - type: Transform
+ noRot: true
+ anchored: true
+ - type: InteractionOutline
+ - type: Clickable
+ - type: Anchorable
+ delay: 2
+ - type: Physics
+ bodyType: Static
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.40,-0.40,0.40,0.40"
+ density: 190
+ friction: 0.8
+ mask:
+ - FullTileMask
+ layer:
+ - FullTileLayer
+ - type: Pullable
+ - type: Sprite
+ sprite: _Starlight/Objects/Specific/supermatter.rsi
+ state: supermatter
+ shader: unshaded
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter.rsi
+ state: supermatter
+ - type: PointLight
+ enabled: true
+ color: "#FFFB97"
+ - type: Damageable
+ damageModifierSet: RGlass
+ damageContainer: StructuralInorganic
+ # - type: LightningTarget Tesla needs to interact too.
+ # priority: 1
+
+
+- type: entity
+ id: Cascad1
+ name: cascad
+ description: Consequences of the supermatter crystal's cascade failure.
+ placement:
+ mode: SnapgridCenter
+ components:
+ - type: Damageable
+ damageContainer: StructuralInorganic
+ damageModifierSet: Glass
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 80
+ behaviors:
+ - !type:DoActsBehavior
+ acts: [ "Destruction" ]
+ - !type:PlaySoundBehavior
+ sound:
+ collection: GlassBreak
+ - type: Sprite
+ drawdepth: Walls
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ layers:
+ - state: cascade_1
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_1
+ - type: Physics
+ bodyType: Static
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.5,-0.5,0.5,0.5"
+ layer:
+ - GlassLayer
+
+- type: entity
+ id: Cascad2
+ parent: Cascad1
+ components:
+ - type: Sprite
+ layers:
+ - state: cascade_2
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_2
+
+- type: entity
+ id: Cascad3
+ parent: Cascad1
+ components:
+ - type: Sprite
+ layers:
+ - state: cascade_3
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_3
+
+- type: entity
+ id: Cascad4
+ parent: Cascad1
+ components:
+ - type: Sprite
+ layers:
+ - state: cascade_4
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_4
+
+- type: entity
+ id: Cascad5
+ parent: Cascad1
+ components:
+ - type: Sprite
+ layers:
+ - state: cascade_5
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_5
+
+- type: entity
+ id: Cascad6
+ parent: Cascad1
+ components:
+ - type: Sprite
+ layers:
+ - state: cascade_6
+ - type: Icon
+ sprite: _Starlight/Objects/Specific/supermatter_cascade.rsi
+ state: cascade_6
\ No newline at end of file
diff --git a/Resources/Prototypes/_Sunrise/Objectives/traitorObjectives.yml b/Resources/Prototypes/_Sunrise/Objectives/traitorObjectives.yml
index d57a7f2390..3dc702f6fc 100644
--- a/Resources/Prototypes/_Sunrise/Objectives/traitorObjectives.yml
+++ b/Resources/Prototypes/_Sunrise/Objectives/traitorObjectives.yml
@@ -33,18 +33,6 @@
listings:
- UplinkCoreExtractionToolbox
-- type: entity
- categories: [ HideSpawnMenu ]
- parent: BaseTraitorStealObjective
- id: StealSupermatterSliverObjective
- components:
- - type: Objective
- difficulty: 2.5
- - type: StealCondition
- stealGroup: SupermatterSliver
- objectiveNoOwnerText: objective-condition-steal-supermatter-sliver
- descriptionText: objective-description-steal-supermatter-sliver
-
- type: entity
parent: BaseTraitorStealObjective
id: HandheldFaxStealObjective
diff --git a/Resources/Prototypes/_Sunrise/tags.yml b/Resources/Prototypes/_Sunrise/tags.yml
index acb8721b06..95add452b8 100644
--- a/Resources/Prototypes/_Sunrise/tags.yml
+++ b/Resources/Prototypes/_Sunrise/tags.yml
@@ -456,3 +456,6 @@
- type: Tag
id: SnapPop
+
+- type: Tag
+ id: Table
diff --git a/Resources/Textures/Objects/Devices/flatpack.rsi/large.png b/Resources/Textures/Objects/Devices/flatpack.rsi/large.png
new file mode 100644
index 0000000000..587c6b271f
Binary files /dev/null and b/Resources/Textures/Objects/Devices/flatpack.rsi/large.png differ
diff --git a/Resources/Textures/Objects/Devices/flatpack.rsi/meta.json b/Resources/Textures/Objects/Devices/flatpack.rsi/meta.json
index ac1e6be151..5efc8b68e4 100644
--- a/Resources/Textures/Objects/Devices/flatpack.rsi/meta.json
+++ b/Resources/Textures/Objects/Devices/flatpack.rsi/meta.json
@@ -48,6 +48,12 @@
},
{
"name": "hydroponics-tray"
+ },
+ {
+ "name": "large"
+ },
+ {
+ "name": "microwave"
}
]
}
diff --git a/Resources/Textures/Objects/Devices/flatpack.rsi/microwave.png b/Resources/Textures/Objects/Devices/flatpack.rsi/microwave.png
new file mode 100644
index 0000000000..9eb23c25d3
Binary files /dev/null and b/Resources/Textures/Objects/Devices/flatpack.rsi/microwave.png differ
diff --git a/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/icon.png b/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/icon.png
deleted file mode 100644
index 2187706b10..0000000000
Binary files a/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/icon.png and /dev/null differ
diff --git a/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/meta.json b/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/meta.json
deleted file mode 100644
index 744651bea0..0000000000
--- a/Resources/Textures/Objects/Misc/supermatter_sliver.rsi/meta.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "version": 1,
- "copyright": "Taken and edited from https://github.com/tgstation/tgstation/blob/master/icons/obj/antags/syndicate_tools.dmi",
- "license": "CC-BY-SA-3.0",
- "size": {
- "x": 32,
- "y": 32
- },
- "states": [
- {
- "name": "icon"
- }
- ]
-}
diff --git a/Resources/Textures/Structures/Power/Generation/supermatter.rsi/meta.json b/Resources/Textures/Structures/Power/Generation/supermatter.rsi/meta.json
deleted file mode 100644
index d0a000ae2b..0000000000
--- a/Resources/Textures/Structures/Power/Generation/supermatter.rsi/meta.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "version": 1,
- "copyright": "Taken and edited from https://tgstation13.org/wiki/images/a/a4/Supermatter-bg.gif",
- "license": "CC-BY-SA-3.0",
- "size": {
- "x": 32,
- "y": 48
- },
- "states": [
- {
- "name": "supermatter",
- "delays": [
- [
- 0.08,
- 0.08,
- 0.08
- ]
- ]
- }
- ]
-}
diff --git a/Resources/Textures/Structures/Power/Generation/supermatter.rsi/supermatter.png b/Resources/Textures/Structures/Power/Generation/supermatter.rsi/supermatter.png
deleted file mode 100644
index 0c5747a315..0000000000
Binary files a/Resources/Textures/Structures/Power/Generation/supermatter.rsi/supermatter.png and /dev/null differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/meta.json b/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/meta.json
new file mode 100644
index 0000000000..f1364c9a97
--- /dev/null
+++ b/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/meta.json
@@ -0,0 +1,24 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from https://tgstation13.org/wiki/images/a/a4/Supermatter-bg.gif",
+ "size": {
+ "x": 32,
+ "y": 48
+ },
+ "states": [
+ {
+ "name": "supermatter",
+ "delays": [
+ [
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/supermatter.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/supermatter.png
new file mode 100644
index 0000000000..04db70cde1
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter.rsi/supermatter.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_1.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_1.png
new file mode 100644
index 0000000000..a16072b8e1
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_1.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_2.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_2.png
new file mode 100644
index 0000000000..a3c7e2786d
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_2.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_3.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_3.png
new file mode 100644
index 0000000000..59338c0961
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_3.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_4.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_4.png
new file mode 100644
index 0000000000..559063f9b3
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_4.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_5.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_5.png
new file mode 100644
index 0000000000..b2050dfd89
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_5.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_6.png b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_6.png
new file mode 100644
index 0000000000..be9635ea33
Binary files /dev/null and b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/cascade_6.png differ
diff --git a/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/meta.json b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/meta.json
new file mode 100644
index 0000000000..462a0b4d0d
--- /dev/null
+++ b/Resources/Textures/_Starlight/Objects/Specific/supermatter_cascade.rsi/meta.json
@@ -0,0 +1,29 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from https://tgstation13.org/wiki/images/a/a4/Supermatter-bg.gif",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "cascade_1"
+ },
+ {
+ "name": "cascade_2"
+ },
+ {
+ "name": "cascade_3"
+ },
+ {
+ "name": "cascade_4"
+ },
+ {
+ "name": "cascade_5"
+ },
+ {
+ "name": "cascade_6"
+ }
+ ]
+}