diff --git a/Content.Server/Anomaly/Components/InjectionAnomalyComponent.cs b/Content.Server/Anomaly/Components/InjectionAnomalyComponent.cs new file mode 100644 index 0000000000..4a9b5b6b55 --- /dev/null +++ b/Content.Server/Anomaly/Components/InjectionAnomalyComponent.cs @@ -0,0 +1,47 @@ +using Content.Server.Anomaly.Effects; +using Robust.Shared.Prototypes; + +namespace Content.Server.Anomaly.Components; + +/// +/// This component allows the anomaly to inject liquid from the SolutionContainer +/// into the surrounding entities with the InjectionSolution component +/// + +[RegisterComponent, Access(typeof(InjectionAnomalySystem))] +public sealed partial class InjectionAnomalyComponent : Component +{ + /// + /// the maximum amount of injection of a substance into an entity per pulsation + /// scales with Severity + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxSolutionInjection = 15; + /// + /// the maximum amount of injection of a substance into an entity in the supercritical phase + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SuperCriticalSolutionInjection = 50; + + /// + /// The maximum radius in which the anomaly injects reagents into the surrounding containers. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float InjectRadius = 3; + /// + /// The maximum radius in which the anomaly injects reagents into the surrounding containers. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SuperCriticalInjectRadius = 15; + + /// + /// The name of the prototype of the special effect that appears above the entities into which the injection was carried out + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public EntProtoId VisualEffectPrototype = "PuddleSparkle"; + /// + /// Solution name that can be drained. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string Solution { get; set; } = "default"; +} diff --git a/Content.Server/Anomaly/Components/PuddleCreateAnomalyComponent.cs b/Content.Server/Anomaly/Components/PuddleCreateAnomalyComponent.cs new file mode 100644 index 0000000000..78c50b3d7e --- /dev/null +++ b/Content.Server/Anomaly/Components/PuddleCreateAnomalyComponent.cs @@ -0,0 +1,29 @@ +using Content.Server.Anomaly.Effects; + +namespace Content.Server.Anomaly.Components; + +/// +/// This component allows the anomaly to create puddles from the solutionContainer +/// +[RegisterComponent, Access(typeof(PuddleCreateAnomalySystem))] +public sealed partial class PuddleCreateAnomalyComponent : Component +{ + /// + /// The maximum amount of solution that an anomaly can splash out of the storage on the floor during pulsation. + /// Scales with Severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxPuddleSize = 100; + + /// + /// The maximum amount of solution that an anomaly can splash out of the storage on the floor during supercritical event + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SuperCriticalPuddleSize = 1000; + + /// + /// Solution name that can be drained. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string Solution { get; set; } = "default"; +} diff --git a/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs b/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs new file mode 100644 index 0000000000..aa860c1713 --- /dev/null +++ b/Content.Server/Anomaly/Components/ReagentProducerAnomalyComponent.cs @@ -0,0 +1,94 @@ +using Content.Server.Anomaly.Effects; +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using System.Numerics; + +namespace Content.Server.Anomaly.Components; +/// +/// This component allows the anomaly to generate a random type of reagent in the specified SolutionContainer. +/// With the increasing severity of the anomaly, the type of reagent produced may change. +/// The higher the severity of the anomaly, the higher the chance of dangerous or useful reagents. +/// +[RegisterComponent, Access(typeof(ReagentProducerAnomalySystem))] +public sealed partial class ReagentProducerAnomalyComponent : Component +{ + //the addition of the reagent will occur instantly when an anomaly appears, + //and there will not be the first three seconds of a white empty anomaly. + public float AccumulatedFrametime = 3.0f; + /// + /// How frequently should this reagent generation update, in seconds? + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float UpdateInterval = 3.0f; + + /// + /// The spread of the random weight of the choice of this category, depending on the severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public Vector2 WeightSpreadDangerous = new(5.0f, 9.0f); + /// + /// The spread of the random weight of the choice of this category, depending on the severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public Vector2 WeightSpreadFun = new(3.0f, 0.0f); + /// + /// The spread of the random weight of the choice of this category, depending on the severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public Vector2 WeightSpreadUseful = new(1.0f, 1.0f); + + /// + /// Category of dangerous reagents for injection. Various toxins and poisons + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public List> DangerousChemicals = new(); + /// + /// Category of useful reagents for injection. Medicine and other things that players WANT to get + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public List> UsefulChemicals = new(); + /// + /// Category of fun reagents for injection. Glue, drugs, beer. Something that will bring fun. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public List> FunChemicals = new(); + + /// + /// Noise made when anomaly pulse. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier ChangeSound = new SoundPathSpecifier("/Audio/Effects/waterswirl.ogg"); + /// + /// The component will repaint the sprites of the object to match the current color of the solution, + /// if the RandomSprite component is hung correctly. + /// Ideally, this should be put into a separate component, but I suffered for 4 hours, + /// and nothing worked out for me. So for now it will be like this. + /// + [DataField, ViewVariables(VVAccess.ReadOnly)] + public bool NeedRecolor = false; + + /// + /// the maximum amount of reagent produced per second + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxReagentProducing = 1.5f; + + /// + /// how much does the reagent production increase before entering the supercritical state + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SupercriticalReagentProducingModifier = 100f; + + /// + /// The name of the reagent that the anomaly produces. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId ProducingReagent = "Water"; + /// + /// Solution name where the substance is generated + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution = "default"; +} diff --git a/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs new file mode 100644 index 0000000000..acc0e2f0c3 --- /dev/null +++ b/Content.Server/Anomaly/Effects/InjectionAnomalySystem.cs @@ -0,0 +1,67 @@ +using System.Linq; +using Content.Server.Anomaly.Components; +using Content.Server.Chemistry.Components.SolutionManager; +using Content.Server.Chemistry.EntitySystems; +using Content.Shared.Anomaly.Components; + +namespace Content.Server.Anomaly.Effects; +/// +/// This component allows the anomaly to inject liquid from the SolutionContainer +/// into the surrounding entities with the InjectionSolution component +/// +/// + +/// +public sealed class InjectionAnomalySystem : EntitySystem +{ + [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + + private EntityQuery _injectableQuery; + + public override void Initialize() + { + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnSupercritical, before: new[] { typeof(SolutionContainerSystem) }); + + _injectableQuery = GetEntityQuery(); + } + + private void OnPulse(EntityUid uid, InjectionAnomalyComponent component, ref AnomalyPulseEvent args) + { + PulseScalableEffect(uid, component, component.InjectRadius, component.MaxSolutionInjection * args.Severity); + } + + private void OnSupercritical(EntityUid uid, InjectionAnomalyComponent component, ref AnomalySupercriticalEvent args) + { + PulseScalableEffect(uid, component, component.SuperCriticalInjectRadius, component.SuperCriticalSolutionInjection); + } + + private void PulseScalableEffect(EntityUid uid, InjectionAnomalyComponent component, float injectRadius, float maxInject) + { + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) + return; + //We get all the entity in the radius into which the reagent will be injected. + var xformQuery = GetEntityQuery(); + var xform = xformQuery.GetComponent(uid); + var allEnts = _lookup.GetComponentsInRange(xform.MapPosition, injectRadius) + .Select(x => x.Owner).ToList(); + + //for each matching entity found + foreach (var ent in allEnts) + { + if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable)) + continue; + + if (_injectableQuery.TryGetComponent(ent, out var injEnt)) + { + var buffer = sol; + _solutionContainer.TryTransferSolution(ent, injectable, buffer, maxInject); + //Spawn Effect + var uidXform = Transform(ent); + Spawn(component.VisualEffectPrototype, uidXform.Coordinates); + } + } + } + +} diff --git a/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs b/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs new file mode 100644 index 0000000000..deae38e5c8 --- /dev/null +++ b/Content.Server/Anomaly/Effects/PuddleCreateAnomalySystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Anomaly.Components; +using Content.Server.Chemistry.EntitySystems; +using Content.Shared.Anomaly.Components; +using Content.Server.Fluids.EntitySystems; + +namespace Content.Server.Anomaly.Effects; + +/// +/// This component allows the anomaly to create puddles from SolutionContainer. +/// +public sealed class PuddleCreateAnomalySystem : EntitySystem +{ + [Dependency] private readonly PuddleSystem _puddle = default!; + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnSupercritical, before: new[] { typeof(InjectionAnomalySystem) }); + } + + private void OnPulse(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalyPulseEvent args) + { + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) + return; + + var xform = Transform(uid); + var puddleSol = _solutionContainer.SplitSolution(uid, sol, component.MaxPuddleSize * args.Severity); + _puddle.TrySplashSpillAt(uid, xform.Coordinates, puddleSol, out _); + } + private void OnSupercritical(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalySupercriticalEvent args) + { + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol)) + return; + var buffer = sol; + var xform = Transform(uid); + _puddle.TrySpillAt(xform.Coordinates, buffer, out _); + } +} diff --git a/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs b/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs new file mode 100644 index 0000000000..fdfff42d7c --- /dev/null +++ b/Content.Server/Anomaly/Effects/ReagentProducerAnomalySystem.cs @@ -0,0 +1,152 @@ +using Content.Server.Anomaly.Components; +using Content.Server.Chemistry.EntitySystems; +using Content.Shared.Anomaly.Components; +using Robust.Shared.Random; +using Content.Shared.Chemistry.Components; +using Robust.Shared.Prototypes; +using Content.Shared.Sprite; +using Robust.Server.GameObjects; + +namespace Content.Server.Anomaly.Effects; + +/// + +public sealed class ReagentProducerAnomalySystem : EntitySystem +{ + //The idea is to divide substances into several categories. + //The anomaly will choose one of the categories with a given chance based on severity. + //Then a random substance will be selected from the selected category. + //There are the following categories: + + //Dangerous: + //selected most often. A list of substances that are extremely unpleasant for injection. + + //Fun: + //Funny things have an increased chance of appearing in an anomaly. + + //Useful: + //Those reagents that the players are hunting for. Very low percentage of loss. + + [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly PointLightSystem _light = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public const string FallbackReagent = "Water"; + + public override void Initialize() + { + SubscribeLocalEvent(OnPulse); + SubscribeLocalEvent(OnMapInit); + } + + private void OnPulse(EntityUid uid, ReagentProducerAnomalyComponent component, ref AnomalyPulseEvent args) + { + if (_random.NextFloat(0.0f, 1.0f) > args.Stability) + ChangeReagent(uid, component, args.Severity); + } + + private void ChangeReagent(EntityUid uid, ReagentProducerAnomalyComponent component, float severity) + { + var reagent = GetRandomReagentType(uid, component, severity); + component.ProducingReagent = reagent; + _audio.PlayPvs(component.ChangeSound, uid); + } + + //reagent realtime generation + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var component, out var anomaly)) + { + component.AccumulatedFrametime += frameTime; + + if (component.AccumulatedFrametime < component.UpdateInterval) + continue; + + if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var producerSol)) + continue; + + Solution newSol = new(); + var reagentProducingAmount = anomaly.Stability * component.MaxReagentProducing * component.AccumulatedFrametime; + if (anomaly.Severity >= 0.97) reagentProducingAmount *= component.SupercriticalReagentProducingModifier; + + newSol.AddReagent(component.ProducingReagent, reagentProducingAmount); + _solutionContainer.TryAddSolution(uid, producerSol, newSol); //TO DO - the container is not fully filled. + + component.AccumulatedFrametime = 0; + + // The component will repaint the sprites of the object to match the current color of the solution, + // if the RandomSprite component is hung correctly. + + // Ideally, this should be put into a separate component, but I suffered for 4 hours, + // and nothing worked out for me. So for now it will be like this. + if (component.NeedRecolor) + { + var color = producerSol.GetColor(_prototypeManager); + _light.SetColor(uid, color); + if (TryComp(uid, out var randomSprite)) + { + foreach (var ent in randomSprite.Selected) + { + var state = randomSprite.Selected[ent.Key]; + state.Color = color; + randomSprite.Selected[ent.Key] = state; + } + Dirty(uid, randomSprite); + } + } + } + } + + private void OnMapInit(EntityUid uid, ReagentProducerAnomalyComponent component, MapInitEvent args) + { + ChangeReagent(uid, component, 0.1f); //MapInit Reagent 100% change + } + + // returns a random reagent based on a system of random weights. + // First, the category is selected: The category has a minimum and maximum weight, + // the current value depends on severity. + // Accordingly, with the strengthening of the anomaly, + // the chances of falling out of some categories grow, and some fall. + // + // After that, a random reagent in the selected category is selected. + // + // Such a system is made to control the danger and interest of the anomaly more. + private string GetRandomReagentType(EntityUid uid, ReagentProducerAnomalyComponent component, float severity) + { + //Category Weight Randomization + var currentWeightDangerous = MathHelper.Lerp(component.WeightSpreadDangerous.X, component.WeightSpreadDangerous.Y, severity); + var currentWeightFun = MathHelper.Lerp(component.WeightSpreadFun.X, component.WeightSpreadFun.Y, severity); + var currentWeightUseful = MathHelper.Lerp(component.WeightSpreadUseful.X, component.WeightSpreadUseful.Y, severity); + + var sumWeight = currentWeightDangerous + currentWeightFun + currentWeightUseful; + var rnd = _random.NextFloat(0f, sumWeight); + //Dangerous + if (rnd <= currentWeightDangerous && component.DangerousChemicals.Count > 0) + { + var reagent = _random.Pick(component.DangerousChemicals); + return reagent; + } + else rnd -= currentWeightDangerous; + //Fun + if (rnd <= currentWeightFun && component.FunChemicals.Count > 0) + { + var reagent = _random.Pick(component.FunChemicals); + return reagent; + } + else rnd -= currentWeightFun; + //Useful + if (rnd <= currentWeightUseful && component.UsefulChemicals.Count > 0) + { + var reagent = _random.Pick(component.UsefulChemicals); + return reagent; + } + //We should never end up here. + //Maybe Log Error? + return FallbackReagent; + } +} diff --git a/Resources/Audio/Effects/attributions.yml b/Resources/Audio/Effects/attributions.yml index f9239f4dab..71a2ae2b53 100644 --- a/Resources/Audio/Effects/attributions.yml +++ b/Resources/Audio/Effects/attributions.yml @@ -56,4 +56,9 @@ - files: ["break_stone.ogg"] license: "CC-BY-SA-3.0" copyright: "Taken from tgstation" - source: "https://github.com/tgstation/tgstation/blob/e3a835b96043fad1269ee7b0c3a6cb340a466f3a/sound/effects/break_stone.ogg" \ No newline at end of file + source: "https://github.com/tgstation/tgstation/blob/e3a835b96043fad1269ee7b0c3a6cb340a466f3a/sound/effects/break_stone.ogg" + +- files: ["waterswirl.ogg"] + license: "CC0-1.0" + copyright: "Taken from InspectorJ via freesound.org and mixed from stereo to mono." + source: "https://freesound.org/people/InspectorJ/sounds/398703/" diff --git a/Resources/Audio/Effects/waterswirl.ogg b/Resources/Audio/Effects/waterswirl.ogg new file mode 100644 index 0000000000..d8c9755a69 Binary files /dev/null and b/Resources/Audio/Effects/waterswirl.ogg differ diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml index e1f1e56480..043bf707b4 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/anomaly.yml @@ -17,4 +17,5 @@ - AnomalyBluespace - AnomalyIce - AnomalyRock + - AnomalyLiquid chance: 1 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index a49d095535..beed7db43c 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -206,3 +206,232 @@ radius: 2 energy: 3 color: "#06DF24" + +- type: entity + name: Reagent slime + id: ReagentSlime + suffix: Water + parent: MobAdultSlimes + description: It consists of a liquid, and it wants to dissolve you in itself. + components: + - type: NpcFactionMember + factions: + - SimpleHostile + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#75b1f0" + - type: PointLight + radius: 2.0 + energy: 3.5 + color: "#75b1f0" # Edited through the LiquidAnomalySystem + - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds + thresholds: + 0: Alive + 150: Dead + - type: SlowOnDamage + speedModifierThresholds: + 50: 0.4 + - type: Bloodstream + bloodReagent: Water + chemicalMaxVolume: 100 + - type: StatusEffects + allowed: + - SlowedDown + - Electrocution + - type: MeleeWeapon + soundHit: + collection: AlienClaw + animation: WeaponArcBite + damage: + types: + Slash: 15 + - type: MeleeChemicalInjector + solution: bloodstream + transferAmount: 5 + - type: DamageStateVisuals + rotate: true + states: + Alive: + Base: alive + Dead: + Base: dead + - type: Tag + tags: + - FootstepSound + - CannotSuicide + - DoorBumpOpener + - type: NoSlip + - type: ZombieImmune + - type: ExaminableSolution + solution: bloodstream + - type: InjectableSolution + solution: bloodstream + - type: DrainableSolution + solution: bloodstream + +- type: entity + name: Reagent Slime Spawner + id: ReagentSlimeSpawner + parent: MarkerBase + components: + - type: Sprite + layers: + - state: red + - sprite: Mobs/Aliens/elemental.rsi + state: alive + - type: RandomSpawner + prototypes: + - ReagentSlime + - ReagentSlimeBeer + - ReagentSlimePax + - ReagentSlimeNocturine + - ReagentSlimeTHC + - ReagentSlimeBicaridine + - ReagentSlimeToxin + - ReagentSlimeNapalm + - ReagentSlimeOmnizine + chance: 1 + +- type: entity + id: ReagentSlimeBeer + parent: ReagentSlime + suffix: Beer + components: + - type: Bloodstream + bloodReagent: Beer + - type: PointLight + color: "#cfa85f" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#cfa85f" + +- type: entity + id: ReagentSlimePax + parent: ReagentSlime + suffix: Pax + components: + - type: Bloodstream + bloodReagent: Pax + - type: PointLight + color: "#AAAAAA" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#AAAAAA" + +- type: entity + id: ReagentSlimeNocturine + parent: ReagentSlime + suffix: Nocturine + components: + - type: Bloodstream + bloodReagent: Nocturine + - type: PointLight + color: "#128e80" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#128e80" + +- type: entity + id: ReagentSlimeTHC + parent: ReagentSlime + suffix: THC + components: + - type: Bloodstream + bloodReagent: THC + - type: PointLight + color: "#808080" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#808080" + +- type: entity + id: ReagentSlimeBicaridine + parent: ReagentSlime + suffix: Bicaridine + components: + - type: Bloodstream + bloodReagent: Bicaridine + - type: PointLight + color: "#ffaa00" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#ffaa00" + +- type: entity + id: ReagentSlimeToxin + parent: ReagentSlime + suffix: Toxin + components: + - type: Bloodstream + bloodReagent: Toxin + - type: PointLight + color: "#cf3600" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#cf3600" + +- type: entity + id: ReagentSlimeNapalm + parent: ReagentSlime + suffix: Napalm + components: + - type: Bloodstream + bloodReagent: Napalm + - type: PointLight + color: "#FA00AF" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#FA00AF" + +- type: entity + id: ReagentSlimeOmnizine + parent: ReagentSlime + suffix: Omnizine + components: + - type: Bloodstream + bloodReagent: Omnizine + - type: PointLight + color: "#fcf7f9" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#fcf7f9" \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml index 16d9365b9f..d227e57ff3 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/anomalies.yml @@ -263,3 +263,109 @@ superCriticalSpawns: - AsteroidRock - SpawnMobOreCrab + +- type: entity + id: AnomalyLiquid + parent: BaseAnomaly + suffix: Liquid + components: + - type: Sprite + sprite: Structures/Specific/Anomalies/liquid_anom.rsi + layers: + - state: anom + map: ["enum.AnomalyVisualLayers.Base"] + - state: pulse + map: ["enum.AnomalyVisualLayers.Animated"] + visible: false + - type: RandomSprite + selected: # Initialized layer values. Edited through the ReagentProducerAnomalySystem + enum.AnomalyVisualLayers.Base: + anom: "#ffffff" + enum.AnomalyVisualLayers.Animated: + pulse: "#ffffff" + - type: PointLight + radius: 4.0 + energy: 3.5 + color: "#bbbbbb" + - type: BadFood + - type: Anomaly + anomalyContactDamage: + types: + Slash: 1 + - type: EntitySpawnAnomaly + superCriticalSpawns: + - ReagentSlimeSpawner + spawns: + - PuddleSparkle + - type: SolutionContainerManager + solutions: + anomaly: + maxVol: 1500 + - type: PuddleCreateAnomaly + solution: anomaly + - type: InjectionAnomaly + solution: anomaly + - type: ReagentProducerAnomaly + solution: anomaly + needRecolor: true + dangerousChemicals: + - UnstableMutagen + - Mold + - PolytrinicAcid + - FerrochromicAcid + - FluorosulfuricAcid + - SulfuricAcid + - HeartbreakerToxin + - VentCrud + - UncookedAnimalProteins + - Thermite + - Napalm + - Phlogiston + - ChlorineTrifluoride + - FoamingAgent + - BuzzochloricBees + - RobustHarvest + usefulChemicals: + - Cryptobiolin + - Dylovene + - Arithrazine + - Bicaridine + - Cryoxadone + - Dermaline + - Dexalin + - DexalinPlus + - Epinephrine + - Leporazine + - Ambuzol + - Tricordrazine + - Artifexium + - Ethylredoxrazine + funChemicals: + - Desoxyephedrine + - Ephedrine + - THC + - THCOil + - SpaceDrugs + - Nocturine + - MuteToxin + - NorepinephricAcid + - Pax + - Ipecac + - Cognizine + - Beer + - SpaceGlue + - CogChamp + - Honk + - Carpetium + - type: Drink + solution: anomaly + - type: DrainableSolution + solution: anomaly + - type: DrawableSolution + solution: anomaly + - type: ExaminableSolution + solution: anomaly + - type: RefillableSolution + solution: anomaly + - type: InjectableSolution + solution: beaker diff --git a/Resources/Textures/Mobs/Aliens/elemental.rsi/alive.png b/Resources/Textures/Mobs/Aliens/elemental.rsi/alive.png new file mode 100644 index 0000000000..c0fbc020b3 Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/elemental.rsi/alive.png differ diff --git a/Resources/Textures/Mobs/Aliens/elemental.rsi/dead.png b/Resources/Textures/Mobs/Aliens/elemental.rsi/dead.png new file mode 100644 index 0000000000..1363188c39 Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/elemental.rsi/dead.png differ diff --git a/Resources/Textures/Mobs/Aliens/elemental.rsi/meta.json b/Resources/Textures/Mobs/Aliens/elemental.rsi/meta.json new file mode 100644 index 0000000000..3d3d7f75a8 --- /dev/null +++ b/Resources/Textures/Mobs/Aliens/elemental.rsi/meta.json @@ -0,0 +1,44 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for Space Station 14.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "dead" + }, + { + "name": "alive", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/anom.png b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/anom.png new file mode 100644 index 0000000000..f421984c36 Binary files /dev/null and b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/anom.png differ diff --git a/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/meta.json b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/meta.json new file mode 100644 index 0000000000..320816f3c5 --- /dev/null +++ b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by TheShuEd (github) for ss14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "anom", + "delays": [ + [ + 0.18625, + 0.18625, + 0.18625, + 0.18625 + ] + ] + }, + { + "name": "pulse", + "delays": [ + [ + 0.15625, + 0.15625, + 0.15625, + 0.15625 + ] + ] + } + ] +} diff --git a/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/pulse.png b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/pulse.png new file mode 100644 index 0000000000..3447184fb6 Binary files /dev/null and b/Resources/Textures/Structures/Specific/Anomalies/liquid_anom.rsi/pulse.png differ