XenoArch [Science Overhaul] (#12204)
* multi-node xeno artifacts * refactor existing artifact effects * more tweaks to generation * more shit plus fix tests * more generation stuff plus threat levels * doink * now make it build * defer the artifact activation to not cause errors also pricing * some changes * all of the yaml + ui stuff for artifact analyzer * machine linking and starting to make the ui functional * artifact analyzer display * a shit ton of artifact analyzer stuff * more changes; making destroy work properly; progress bar tweaks * getting shit going! ALL RIGHT * small tweaks that didn't help much * Komm susser todd: the end of analysis * recipes and hints and ui, oh my! * add some in-game sources gotta prepare for day 1 launch * node data + ditch random seed in place of id * bunch of triggers * finish off the last few triggers * implement machine examine verb * knock, flicker, blink, throw * shatter, foam, shuffle, heat * fix all the shit i broke * *some* of these have to be good, no? 25 effects * callin' it there for effects * comments + reword some trigger hints * don't mind this little commit here * byref event * fix brokey node entry * fix low pressure trigger * mirror review plus fixing 0x40's bug also the throw artifact threw incorrectly * randomize the event message a teeny bit
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Whitelist;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// When activated, damages nearby entities.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class DamageNearbyArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The radius of entities that will be affected
|
||||
/// </summary>
|
||||
[DataField("radius")]
|
||||
public float Radius = 3f;
|
||||
|
||||
/// <summary>
|
||||
/// A whitelist for filtering certain damage.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// TODO: The component portion, since it uses an array, does not work currently.
|
||||
/// </remarks>
|
||||
[DataField("whitelist")]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
/// <summary>
|
||||
/// The damage that is applied
|
||||
/// </summary>
|
||||
[DataField("damage", required: true)]
|
||||
public DamageSpecifier Damage = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The chance that damage is applied to each individual entity
|
||||
/// </summary>
|
||||
[DataField("damageChance")]
|
||||
public float DamageChance = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this should ignore resistances for the damage
|
||||
/// </summary>
|
||||
[DataField("ignoreResistances")]
|
||||
public bool IgnoreResistances;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Disease;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
/// <summary>
|
||||
@@ -8,10 +9,15 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
public sealed class DiseaseArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Disease the artifact will spawn
|
||||
/// If empty, picks a random one from its list
|
||||
/// The diseases that the artifact can use.
|
||||
/// </summary>
|
||||
[DataField("diseasePrototype", customTypeSerializer: typeof(PrototypeIdListSerializer<DiseasePrototype>))]
|
||||
public List<string> DiseasePrototypes = new();
|
||||
|
||||
/// <summary>
|
||||
/// Disease the artifact will spawn
|
||||
/// Picks a random one from its list
|
||||
/// </summary>
|
||||
[DataField("disease")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DiseasePrototype? SpawnDisease;
|
||||
|
||||
@@ -19,7 +25,6 @@ public sealed class DiseaseArtifactComponent : Component
|
||||
/// How far away it will check for people
|
||||
/// If empty, picks a random one from its list
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("range"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Range = 5f;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Generates foam from the artifact when activated
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class FoamArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The list of reagents that will randomly be picked from
|
||||
/// to choose the foam reagent
|
||||
/// </summary>
|
||||
[DataField("reagents", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<ReagentPrototype>))]
|
||||
public List<string> Reagents = new();
|
||||
|
||||
/// <summary>
|
||||
/// The foam reagent
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? SelectedReagent;
|
||||
|
||||
/// <summary>
|
||||
/// How long does the foam last?
|
||||
/// </summary>
|
||||
[DataField("duration")]
|
||||
public float Duration = 10;
|
||||
|
||||
/// <summary>
|
||||
/// How much reagent is in the foam?
|
||||
/// </summary>
|
||||
[DataField("reagentAmount")]
|
||||
public float ReagentAmount = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum radius of foam spawned
|
||||
/// </summary>
|
||||
[DataField("minFoamAmount")]
|
||||
public int MinFoamAmount = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum radius of foam spawned
|
||||
/// </summary>
|
||||
[DataField("maxFoamAmount")]
|
||||
public int MaxFoamAmount = 6;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes for each tile of foam to spawn
|
||||
/// </summary>
|
||||
[DataField("spreadDuration")]
|
||||
public float SpreadDuration = 1;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public sealed class GasArtifactComponent : Component
|
||||
/// List of possible activation gases to pick on startup.
|
||||
/// </summary>
|
||||
[DataField("possibleGas")]
|
||||
public Gas[] PossibleGases =
|
||||
public List<Gas> PossibleGases = new()
|
||||
{
|
||||
Gas.Oxygen,
|
||||
Gas.Plasma,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for using the "knock" spell when the artifact is activated
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class KnockArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The range of the spell
|
||||
/// </summary>
|
||||
[DataField("knockRange")]
|
||||
public float KnockRange = 4f;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Flickers all the lights within a certain radius.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class LightFlickerArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Lights within this radius will be flickered on activation
|
||||
/// </summary>
|
||||
[DataField("radius")]
|
||||
public float Radius = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The chance that the light will flicker
|
||||
/// </summary>
|
||||
[DataField("flickerChance")]
|
||||
public float FlickerChance = 0.75f;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Spawn RadiationPulse when artifact activated.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class RadiateArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Radiation pulse prototype to spawn.
|
||||
/// </summary>
|
||||
[DataField("pulsePrototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string PulsePrototype = "RadiationPulse";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// When activated, will teleport the artifact
|
||||
/// to a random position within a certain radius
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class RandomTeleportArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The max distance that the artifact will teleport.
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
public float Range = 7.5f;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// When activated, will shuffle the position of all players
|
||||
/// within a certain radius.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class ShuffleArtifactComponent : Component
|
||||
{
|
||||
[DataField("radius")]
|
||||
public float Radius = 7.5f;
|
||||
}
|
||||
@@ -11,21 +11,35 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
[RegisterComponent]
|
||||
public sealed class SpawnArtifactComponent : Component
|
||||
{
|
||||
[DataField("random")]
|
||||
public bool RandomPrototype = true;
|
||||
|
||||
/// <summary>
|
||||
/// The list of possible prototypes to spawn that it picks from.
|
||||
/// </summary>
|
||||
[DataField("possiblePrototypes", customTypeSerializer:typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string> PossiblePrototypes = new();
|
||||
|
||||
/// <summary>
|
||||
/// The prototype it selected to spawn.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? Prototype;
|
||||
|
||||
/// <summary>
|
||||
/// The range around the artifact that it will spawn the entity
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
public float Range = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of times the spawn will occur
|
||||
/// </summary>
|
||||
[DataField("maxSpawns")]
|
||||
public int MaxSpawns = 20;
|
||||
|
||||
public int SpawnsCount = 0;
|
||||
/// <summary>
|
||||
/// Whether or not the artifact spawns the same entity every time
|
||||
/// or picks through the list each time.
|
||||
/// </summary>
|
||||
[DataField("consistentSpawn")]
|
||||
public bool ConsistentSpawn = true;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public sealed class TelepathicArtifactComponent : Component
|
||||
/// </summary>
|
||||
[DataField("messages")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string[] Messages = default!;
|
||||
public List<string> Messages = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Loc string ids of telepathic messages (spooky version).
|
||||
@@ -21,7 +21,7 @@ public sealed class TelepathicArtifactComponent : Component
|
||||
/// </summary>
|
||||
[DataField("drastic")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string[] DrasticMessages = default!;
|
||||
public List<string>? DrasticMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Probability to pick drastic version of message.
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
[RegisterComponent]
|
||||
public sealed class TemperatureArtifactComponent : Component
|
||||
{
|
||||
[DataField("targetTemp")]
|
||||
[DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float TargetTemperature = Atmospherics.T0C;
|
||||
|
||||
[DataField("spawnTemp")]
|
||||
@@ -21,6 +21,6 @@ public sealed class TemperatureArtifactComponent : Component
|
||||
/// If true, artifact will heat/cool not only its current tile, but surrounding tiles too.
|
||||
/// This will change room temperature much faster.
|
||||
/// </summary>
|
||||
[DataField("effectAdjacent")]
|
||||
public bool EffectAdjacentTiles = true;
|
||||
[DataField("affectAdjacent")]
|
||||
public bool AffectAdjacentTiles = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Throws all nearby entities backwards.
|
||||
/// Also pries nearby tiles.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class ThrowArtifactComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// How close do you have to be to get yeeted?
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
public float Range = 2f;
|
||||
|
||||
/// <summary>
|
||||
/// How likely is it that an individual tile will get pried?
|
||||
/// </summary>
|
||||
[DataField("tilePryChance")]
|
||||
public float TilePryChance = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// How strongly does stuff get thrown?
|
||||
/// </summary>
|
||||
[DataField("throwStrength"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ThrowStrength = 5f;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class BreakWindowArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<DamageNearbyArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, DamageNearbyArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var ents = _lookup.GetEntitiesInRange(uid, component.Radius);
|
||||
if (args.Activator != null)
|
||||
ents.Add(args.Activator.Value);
|
||||
foreach (var ent in ents)
|
||||
{
|
||||
if (component.Whitelist != null && !component.Whitelist.IsValid(ent))
|
||||
continue;
|
||||
|
||||
if (!_random.Prob(component.DamageChance))
|
||||
return;
|
||||
|
||||
_damageable.TryChangeDamage(ent, component.Damage, component.IgnoreResistances);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Shared.Disease;
|
||||
using Content.Server.Disease;
|
||||
using Content.Server.Disease.Components;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Interaction;
|
||||
|
||||
@@ -15,38 +15,25 @@ namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems
|
||||
public sealed class DiseaseArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||
|
||||
// TODO: YAML Serializer won't catch this.
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public readonly IReadOnlyList<string> ArtifactDiseases = new[]
|
||||
{
|
||||
"VanAusdallsRobovirus",
|
||||
"OwOnavirus",
|
||||
"BleedersBite",
|
||||
"Ultragigacancer",
|
||||
"MemeticAmirmir",
|
||||
"TongueTwister",
|
||||
"AMIV"
|
||||
};
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<DiseaseArtifactComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<DiseaseArtifactComponent, ArtifactNodeEnteredEvent>(OnNodeEntered);
|
||||
SubscribeLocalEvent<DiseaseArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes sure this artifact is assigned a disease
|
||||
/// </summary>
|
||||
private void OnMapInit(EntityUid uid, DiseaseArtifactComponent component, MapInitEvent args)
|
||||
private void OnNodeEntered(EntityUid uid, DiseaseArtifactComponent component, ArtifactNodeEnteredEvent args)
|
||||
{
|
||||
if (component.SpawnDisease != null || ArtifactDiseases.Count == 0) return;
|
||||
var diseaseName = _random.Pick(ArtifactDiseases);
|
||||
if (component.SpawnDisease != null || !component.DiseasePrototypes.Any())
|
||||
return;
|
||||
var diseaseName = component.DiseasePrototypes[args.RandomSeed % component.DiseasePrototypes.Count];
|
||||
|
||||
if (!_prototypeManager.TryIndex<DiseasePrototype>(diseaseName, out var disease))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Chemistry.ReactionEffects;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class FoamArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<FoamArtifactComponent, ArtifactNodeEnteredEvent>(OnNodeEntered);
|
||||
SubscribeLocalEvent<FoamArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnNodeEntered(EntityUid uid, FoamArtifactComponent component, ArtifactNodeEnteredEvent args)
|
||||
{
|
||||
if (!component.Reagents.Any())
|
||||
return;
|
||||
|
||||
component.SelectedReagent = component.Reagents[args.RandomSeed % component.Reagents.Count];
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, FoamArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
if (component.SelectedReagent == null)
|
||||
return;
|
||||
|
||||
var sol = new Solution();
|
||||
var xform = Transform(uid);
|
||||
sol.AddReagent(component.SelectedReagent, component.ReagentAmount);
|
||||
|
||||
FoamAreaReactionEffect.SpawnFoam("Foam", xform.Coordinates, sol,
|
||||
_random.Next(component.MinFoamAmount, component.MaxFoamAmount), component.Duration,
|
||||
component.SpreadDuration, component.SpreadDuration, entityManager: EntityManager);
|
||||
}
|
||||
}
|
||||
@@ -2,33 +2,32 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class GasArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GasArtifactComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<GasArtifactComponent, ArtifactNodeEnteredEvent>(OnNodeEntered);
|
||||
SubscribeLocalEvent<GasArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, GasArtifactComponent component, MapInitEvent args)
|
||||
private void OnNodeEntered(EntityUid uid, GasArtifactComponent component, ArtifactNodeEnteredEvent args)
|
||||
{
|
||||
if (component.SpawnGas == null && component.PossibleGases.Length != 0)
|
||||
if (component.SpawnGas == null && component.PossibleGases.Count != 0)
|
||||
{
|
||||
var gas = _random.Pick(component.PossibleGases);
|
||||
var gas = component.PossibleGases[args.RandomSeed % component.PossibleGases.Count];
|
||||
component.SpawnGas = gas;
|
||||
}
|
||||
|
||||
if (component.SpawnTemperature == null)
|
||||
{
|
||||
var temp = _random.NextFloat(component.MinRandomTemperature, component.MaxRandomTemperature);
|
||||
var temp = args.RandomSeed % component.MaxRandomTemperature - component.MinRandomTemperature +
|
||||
component.MinRandomTemperature;
|
||||
component.SpawnTemperature = temp;
|
||||
}
|
||||
}
|
||||
@@ -38,8 +37,6 @@ public sealed class GasArtifactSystem : EntitySystem
|
||||
if (component.SpawnGas == null || component.SpawnTemperature == null)
|
||||
return;
|
||||
|
||||
var transform = Transform(uid);
|
||||
|
||||
var environment = _atmosphereSystem.GetContainingMixture(uid, false, true);
|
||||
if (environment == null)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using Content.Server.Magic.Events;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class KnockArtifactSystem : EntitySystem
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KnockArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, KnockArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var ev = new KnockSpellEvent
|
||||
{
|
||||
Performer = uid,
|
||||
Range = component.KnockRange
|
||||
};
|
||||
RaiseLocalEvent(ev);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Content.Server.Ghost;
|
||||
using Content.Server.Light.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This handles...
|
||||
/// </summary>
|
||||
public sealed class LightFlickerArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly GhostSystem _ghost = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<LightFlickerArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, LightFlickerArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var lights = GetEntityQuery<PoweredLightComponent>();
|
||||
foreach (var light in _lookup.GetEntitiesInRange(uid, component.Radius, LookupFlags.StaticSundries ))
|
||||
{
|
||||
if (!lights.HasComponent(light))
|
||||
continue;
|
||||
|
||||
if (!_random.Prob(component.FlickerChance))
|
||||
continue;
|
||||
|
||||
_ghost.DoGhostBooEvent(light);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Content.Server.Radiation;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class RadiateArtifactSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<RadiateArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, RadiateArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var transform = Transform(uid);
|
||||
EntityManager.SpawnEntity(component.PulsePrototype, transform.Coordinates);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This handles...
|
||||
/// </summary>
|
||||
public sealed class RandomTeleportArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<RandomTeleportArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, RandomTeleportArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
_popup.PopupCoordinates(Loc.GetString("blink-artifact-popup"), xform.Coordinates, Filter.Pvs(uid), PopupType.Medium);
|
||||
|
||||
xform.Coordinates = xform.Coordinates.Offset(_random.NextVector2(component.Range));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.MobState.Components;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class ShuffleArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<ShuffleArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, ShuffleArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var mobState = GetEntityQuery<MobStateComponent>();
|
||||
|
||||
List<EntityCoordinates> allCoords = new();
|
||||
List<TransformComponent> toShuffle = new();
|
||||
|
||||
foreach (var ent in _lookup.GetEntitiesInRange(uid, component.Radius, LookupFlags.Dynamic | LookupFlags.Sundries))
|
||||
{
|
||||
if (!mobState.HasComponent(ent))
|
||||
continue;
|
||||
|
||||
var xform = Transform(ent);
|
||||
|
||||
toShuffle.Add(xform);
|
||||
allCoords.Add(xform.Coordinates);
|
||||
}
|
||||
|
||||
foreach (var xform in toShuffle)
|
||||
{
|
||||
xform.Coordinates = _random.PickAndTake(allCoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,25 +9,40 @@ public sealed class SpawnArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly ArtifactSystem _artifact = default!;
|
||||
|
||||
public const string NodeDataSpawnAmount = "nodeDataSpawnAmount";
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SpawnArtifactComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<SpawnArtifactComponent, ArtifactNodeEnteredEvent>(OnNodeEntered);
|
||||
SubscribeLocalEvent<SpawnArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
private void OnMapInit(EntityUid uid, SpawnArtifactComponent component, MapInitEvent args)
|
||||
private void OnNodeEntered(EntityUid uid, SpawnArtifactComponent component, ArtifactNodeEnteredEvent args)
|
||||
{
|
||||
ChooseRandomPrototype(uid, component);
|
||||
if (component.PossiblePrototypes.Count == 0)
|
||||
return;
|
||||
|
||||
var proto = component.PossiblePrototypes[args.RandomSeed % component.PossiblePrototypes.Count];
|
||||
component.Prototype = proto;
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, SpawnArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
if (component.Prototype == null)
|
||||
return;
|
||||
if (component.SpawnsCount >= component.MaxSpawns)
|
||||
|
||||
if (!_artifact.TryGetNodeData(uid, NodeDataSpawnAmount, out int amount))
|
||||
amount = 0;
|
||||
|
||||
if (amount >= component.MaxSpawns)
|
||||
return;
|
||||
|
||||
var toSpawn = component.Prototype;
|
||||
if (!component.ConsistentSpawn)
|
||||
toSpawn = _random.Pick(component.PossiblePrototypes);
|
||||
|
||||
// select spawn position near artifact
|
||||
var artifactCord = Transform(uid).Coordinates;
|
||||
var dx = _random.NextFloat(-component.Range, component.Range);
|
||||
@@ -35,25 +50,11 @@ public sealed class SpawnArtifactSystem : EntitySystem
|
||||
var spawnCord = artifactCord.Offset(new Vector2(dx, dy));
|
||||
|
||||
// spawn entity
|
||||
var spawned = EntityManager.SpawnEntity(component.Prototype, spawnCord);
|
||||
component.SpawnsCount++;
|
||||
var spawned = EntityManager.SpawnEntity(toSpawn, spawnCord);
|
||||
_artifact.SetNodeData(uid, NodeDataSpawnAmount, amount+1);
|
||||
|
||||
// if there is an user - try to put spawned item in their hands
|
||||
// doesn't work for spawners
|
||||
_handsSystem.PickupOrDrop(args.Activator, spawned);
|
||||
}
|
||||
|
||||
private void ChooseRandomPrototype(EntityUid uid, SpawnArtifactComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (!component.RandomPrototype)
|
||||
return;
|
||||
if (component.PossiblePrototypes.Count == 0)
|
||||
return;
|
||||
|
||||
var proto = _random.Pick(component.PossiblePrototypes);
|
||||
component.Prototype = proto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,15 @@ public sealed class TelepathicArtifactSystem : EntitySystem
|
||||
continue;
|
||||
|
||||
// roll if msg should be usual or drastic
|
||||
var isDrastic = _random.NextFloat() <= component.DrasticMessageProb;
|
||||
var msgArr = isDrastic ? component.DrasticMessages : component.Messages;
|
||||
List<string> msgArr;
|
||||
if (_random.NextFloat() <= component.DrasticMessageProb && component.DrasticMessages != null)
|
||||
{
|
||||
msgArr = component.DrasticMessages;
|
||||
}
|
||||
else
|
||||
{
|
||||
msgArr = component.Messages;
|
||||
}
|
||||
|
||||
// pick a random message
|
||||
var msgId = _random.Pick(msgArr);
|
||||
|
||||
@@ -26,7 +26,7 @@ public sealed class TemperatureArtifactSystem : EntitySystem
|
||||
return;
|
||||
UpdateTileTemperature(component, center);
|
||||
|
||||
if (component.EffectAdjacentTiles && transform.GridUid != null)
|
||||
if (component.AffectAdjacentTiles && transform.GridUid != null)
|
||||
{
|
||||
var adjacent = _atmosphereSystem.GetAdjacentTileMixtures(transform.GridUid.Value,
|
||||
_transformSystem.GetGridOrMapTilePosition(uid, transform), excite: true);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public sealed class ThrowArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<ThrowArtifactComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, ThrowArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
if (_map.TryGetGrid(xform.GridUid, out var grid))
|
||||
{
|
||||
var tiles = grid.GetTilesIntersecting(
|
||||
Box2.CenteredAround(xform.WorldPosition, (component.Range*2, component.Range)));
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
if (!_random.Prob(component.TilePryChance))
|
||||
continue;
|
||||
|
||||
tile.PryTile();
|
||||
}
|
||||
}
|
||||
|
||||
var lookup = _lookup.GetEntitiesInRange(uid, component.Range, LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||
foreach (var ent in lookup)
|
||||
{
|
||||
var tempXform = Transform(ent);
|
||||
|
||||
var foo = tempXform.MapPosition.Position - xform.MapPosition.Position;
|
||||
_throwing.TryThrow(ent, foo*2, component.ThrowStrength, uid, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user