Xenoarchaeology artifacts (#6069)
Co-authored-by: Alexander Evgrashin <evgrashin.adl@gmail.com>
@@ -326,7 +326,13 @@ namespace Content.Client.Entry
|
||||
"GrowingKudzu",
|
||||
"MonkeyAccent",
|
||||
"ReplacementAccent",
|
||||
"ResistLocker"
|
||||
"ResistLocker",
|
||||
"SpawnArtifact",
|
||||
"TelepathicArtifact",
|
||||
"ArtifactGasTrigger",
|
||||
"ArtifactInteractionTrigger",
|
||||
"Artifact",
|
||||
"RandomArtifactSprite"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Content.Shared.Xenoarchaeology.XenoArtifacts;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Client.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
public class RandomArtifactVisualizer : AppearanceVisualizer
|
||||
{
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
|
||||
var entities = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entities.TryGetComponent(component.Owner, out ISpriteComponent? sprite)) return;
|
||||
|
||||
if (!component.TryGetData(SharedArtifactsVisuals.SpriteIndex, out int spriteIndex))
|
||||
return;
|
||||
|
||||
if (!component.TryGetData(SharedArtifactsVisuals.IsActivated, out bool isActivated))
|
||||
isActivated = false;
|
||||
|
||||
var spriteIndexStr = spriteIndex.ToString("D2");
|
||||
var spritePrefix = isActivated ? "_on" : "";
|
||||
|
||||
var spriteState = "ano" + spriteIndexStr + spritePrefix;
|
||||
sprite.LayerSetState(0, spriteState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
[RegisterComponent]
|
||||
public class ArtifactComponent : Component
|
||||
{
|
||||
public override string Name => "Artifact";
|
||||
|
||||
/// <summary>
|
||||
/// Should artifact pick a random trigger on startup?
|
||||
/// </summary>
|
||||
[DataField("randomTrigger")]
|
||||
public bool RandomTrigger = true;
|
||||
|
||||
/// <summary>
|
||||
/// List of all possible triggers activations.
|
||||
/// Should be same as components names.
|
||||
/// </summary>
|
||||
[DataField("possibleTriggers")]
|
||||
public string[] PossibleTriggers = {
|
||||
"ArtifactInteractionTrigger",
|
||||
"ArtifactGasTrigger"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Cooldown time between artifact activations (in seconds).
|
||||
/// </summary>
|
||||
[DataField("timer")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public double CooldownTime = 10;
|
||||
|
||||
public TimeSpan LastActivationTime;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
public class ArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ArtifactComponent, ComponentInit>(OnInit);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, ArtifactComponent component, ComponentInit args)
|
||||
{
|
||||
if (component.RandomTrigger)
|
||||
{
|
||||
AddRandomTrigger(uid, component);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRandomTrigger(EntityUid uid, ArtifactComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
var triggerName = _random.Pick(component.PossibleTriggers);
|
||||
var trigger = (Component) _componentFactory.GetComponent(triggerName);
|
||||
trigger.Owner = uid;
|
||||
|
||||
EntityManager.AddComponent(uid, trigger);
|
||||
}
|
||||
|
||||
public bool TryActivateArtifact(EntityUid uid, EntityUid? user = null,
|
||||
ArtifactComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
// check if artifact isn't under cooldown
|
||||
var timeDif = _gameTiming.CurTime - component.LastActivationTime;
|
||||
if (timeDif.TotalSeconds < component.CooldownTime)
|
||||
return false;
|
||||
|
||||
ForceActivateArtifact(uid, user, component);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ForceActivateArtifact(EntityUid uid, EntityUid? user = null,
|
||||
ArtifactComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
component.LastActivationTime = _gameTiming.CurTime;
|
||||
|
||||
var ev = new ArtifactActivatedEvent()
|
||||
{
|
||||
Activator = user
|
||||
};
|
||||
RaiseLocalEvent(uid, ev);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// When activated artifact will spawn an entity from prototype.
|
||||
/// It could be an angry mob or some random item.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class SpawnArtifactComponent : Component
|
||||
{
|
||||
public override string Name => "SpawnArtifact";
|
||||
|
||||
[DataField("random")]
|
||||
public bool RandomPrototype = true;
|
||||
|
||||
[DataField("possiblePrototypes", customTypeSerializer:typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string> PossiblePrototypes = new();
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? Prototype;
|
||||
|
||||
[DataField("range")]
|
||||
public float Range = 0.5f;
|
||||
|
||||
[DataField("maxSpawns")]
|
||||
public int MaxSpawns = 20;
|
||||
|
||||
public int SpawnsCount = 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Harmless artifact that broadcast "thoughts" to players nearby.
|
||||
/// Thoughts are shown as popups and unique for each player.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class TelepathicArtifactComponent : Component
|
||||
{
|
||||
public override string Name => "TelepathicArtifact";
|
||||
|
||||
/// <summary>
|
||||
/// Loc string ids of telepathic messages.
|
||||
/// Will be randomly picked and shown to player.
|
||||
/// </summary>
|
||||
[DataField("messages")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string[] Messages = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Loc string ids of telepathic messages (spooky version).
|
||||
/// Will be randomly picked and shown to player.
|
||||
/// </summary>
|
||||
[DataField("drastic")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string[] DrasticMessages = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Probability to pick drastic version of message.
|
||||
/// </summary>
|
||||
[DataField("drasticProb")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float DrasticMessageProb = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Radius in which player can receive artifacts messages.
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Range = 10f;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using Content.Server.Clothing.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public class SpawnArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SpawnArtifactComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<SpawnArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
private void OnInit(EntityUid uid, SpawnArtifactComponent component, ComponentInit args)
|
||||
{
|
||||
ChooseRandomPrototype(uid, component);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, SpawnArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
if (component.Prototype == null)
|
||||
return;
|
||||
if (component.SpawnsCount >= component.MaxSpawns)
|
||||
return;
|
||||
|
||||
// select spawn position near artifact
|
||||
var artifactCord = Transform(uid).Coordinates;
|
||||
var dx = _random.NextFloat(-component.Range, component.Range);
|
||||
var dy = _random.NextFloat(-component.Range, component.Range);
|
||||
var spawnCord = artifactCord.Offset(new Vector2(dx, dy));
|
||||
|
||||
// spawn entity
|
||||
var spawned = EntityManager.SpawnEntity(component.Prototype, spawnCord);
|
||||
component.SpawnsCount++;
|
||||
|
||||
// if there is an user - try to put spawned item in their hands
|
||||
// doesn't work for spawners
|
||||
if (args.Activator != null &&
|
||||
EntityManager.TryGetComponent(args.Activator.Value, out SharedHandsComponent? hands) &&
|
||||
EntityManager.HasComponent<ItemComponent>(spawned))
|
||||
{
|
||||
hands.TryPutInAnyHand(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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||
|
||||
public class TelepathicArtifactSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IEntityLookup _lookup = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<TelepathicArtifactComponent, ArtifactActivatedEvent>(OnActivate);
|
||||
}
|
||||
|
||||
private void OnActivate(EntityUid uid, TelepathicArtifactComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
// try to find victims nearby
|
||||
var victims = _lookup.GetEntitiesInRange(uid, component.Range);
|
||||
foreach (var victimUid in victims)
|
||||
{
|
||||
if (!EntityManager.HasComponent<ActorComponent>(victimUid))
|
||||
continue;
|
||||
|
||||
// roll if msg should be usual or drastic
|
||||
var isDrastic = _random.NextFloat() <= component.DrasticMessageProb;
|
||||
var msgArr = isDrastic ? component.DrasticMessages : component.Messages;
|
||||
|
||||
// pick a random message
|
||||
var msgId = _random.Pick(msgArr);
|
||||
var msg = Loc.GetString(msgId);
|
||||
|
||||
// show it as a popup, but only for the victim
|
||||
_popupSystem.PopupEntity(msg, victimUid, Filter.Entities(victimUid));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes when artifact was successfully activated.
|
||||
/// Used to start attached effects.
|
||||
/// </summary>
|
||||
public class ArtifactActivatedEvent : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity that activate this artifact.
|
||||
/// Usually player, but can also be another object.
|
||||
/// </summary>
|
||||
public EntityUid? Activator;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
[RegisterComponent]
|
||||
public class RandomArtifactSpriteComponent : Component
|
||||
{
|
||||
public override string Name => "RandomArtifactSprite";
|
||||
|
||||
[DataField("minSprite")]
|
||||
public int MinSprite = 1;
|
||||
|
||||
[DataField("maxSprite")]
|
||||
public int MaxSprite = 14;
|
||||
|
||||
[DataField("activationTime")]
|
||||
public double ActivationTime = 2.0;
|
||||
|
||||
public TimeSpan? ActivationStart;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Xenoarchaeology.XenoArtifacts;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
public class RandomArtifactSpriteSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IGameTiming _time = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<RandomArtifactSpriteComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<RandomArtifactSpriteComponent, ArtifactActivatedEvent>(OnActivated);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var query = EntityManager.EntityQuery<RandomArtifactSpriteComponent, AppearanceComponent>();
|
||||
foreach (var (component, appearance) in query)
|
||||
{
|
||||
if (component.ActivationStart == null)
|
||||
return;
|
||||
|
||||
var timeDif = _time.CurTime - component.ActivationStart.Value;
|
||||
if (timeDif.Seconds >= component.ActivationTime)
|
||||
{
|
||||
appearance.SetData(SharedArtifactsVisuals.IsActivated, false);
|
||||
component.ActivationStart = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, RandomArtifactSpriteComponent component, ComponentInit args)
|
||||
{
|
||||
if (!TryComp(uid, out AppearanceComponent? appearance))
|
||||
return;
|
||||
|
||||
var randomSprite = _random.Next(component.MinSprite, component.MaxSprite + 1);
|
||||
appearance.SetData(SharedArtifactsVisuals.SpriteIndex, randomSprite);
|
||||
}
|
||||
|
||||
private void OnActivated(EntityUid uid, RandomArtifactSpriteComponent component, ArtifactActivatedEvent args)
|
||||
{
|
||||
if (!TryComp(uid, out AppearanceComponent? appearance))
|
||||
return;
|
||||
|
||||
appearance.SetData(SharedArtifactsVisuals.IsActivated, true);
|
||||
component.ActivationStart = _time.CurTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Activates artifact when it surrounded by certain gas.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class ArtifactGasTriggerComponent : Component
|
||||
{
|
||||
public override string Name => "ArtifactGasTrigger";
|
||||
|
||||
/// <summary>
|
||||
/// List of possible activation gases to pick on startup.
|
||||
/// </summary>
|
||||
[DataField("possibleGas")]
|
||||
public Gas[] PossibleGases =
|
||||
{
|
||||
Gas.Oxygen,
|
||||
Gas.Plasma,
|
||||
Gas.Nitrogen,
|
||||
Gas.CarbonDioxide
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gas id that will activate artifact.
|
||||
/// </summary>
|
||||
[DataField("gas")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Gas? ActivationGas;
|
||||
|
||||
/// <summary>
|
||||
/// How many moles of gas should be present in room to activate artifact.
|
||||
/// </summary>
|
||||
[DataField("moles")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ActivationMoles = Atmospherics.MolesCellStandard * 0.1f;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Activate artifact just by touching it.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class ArtifactInteractionTriggerComponent : Component
|
||||
{
|
||||
public override string Name => "ArtifactInteractionTrigger";
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||
|
||||
public class ArtifactGasTriggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ArtifactGasTriggerComponent, ComponentInit>(OnInit);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var query = EntityManager.EntityQuery<ArtifactGasTriggerComponent, TransformComponent>();
|
||||
foreach (var (trigger, transform) in query)
|
||||
{
|
||||
if (trigger.ActivationGas == null)
|
||||
return;
|
||||
|
||||
var environment = _atmosphereSystem.GetTileMixture(transform.Coordinates, true);
|
||||
if (environment == null)
|
||||
return;
|
||||
|
||||
// check if outside there is enough moles to activate artifact
|
||||
var moles = environment.GetMoles(trigger.ActivationGas.Value);
|
||||
if (moles < trigger.ActivationMoles)
|
||||
return;
|
||||
|
||||
_artifactSystem.TryActivateArtifact(trigger.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, ArtifactGasTriggerComponent component, ComponentInit args)
|
||||
{
|
||||
if (component.ActivationGas == null)
|
||||
{
|
||||
var gas = _random.Pick(component.PossibleGases);
|
||||
component.ActivationGas = gas;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Helpers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||
|
||||
public class ArtifactInteractionTriggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ArtifactInteractionTriggerComponent, InteractHandEvent>(OnInteract);
|
||||
}
|
||||
|
||||
private void OnInteract(EntityUid uid, ArtifactInteractionTriggerComponent component, InteractHandEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
if (!args.InRangeUnobstructed())
|
||||
return;
|
||||
|
||||
args.Handled = _artifactSystem.TryActivateArtifact(uid, args.User);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Xenoarchaeology.XenoArtifacts;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SharedArtifactsVisuals : byte
|
||||
{
|
||||
SpriteIndex,
|
||||
IsActivated
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
badfeeling-artifact-1 = Something doesn't feel right.
|
||||
badfeeling-artifact-2 = You get a strange feeling in your gut.
|
||||
badfeeling-artifact-3 = Your instincts are trying to warn you about something.
|
||||
badfeeling-artifact-4 = Someone just walked over your grave.
|
||||
badfeeling-artifact-5 = There's a strange feeling in the air.
|
||||
badfeeling-artifact-6 = There's a strange smell in the air.
|
||||
badfeeling-artifact-7 = The tips of your fingers feel tingly.
|
||||
badfeeling-artifact-8 = You feel witchy.
|
||||
badfeeling-artifact-9 = You have a terrible sense of foreboding.
|
||||
badfeeling-artifact-10 = You've got a bad feeling about this.
|
||||
badfeeling-artifact-11 = Your scalp prickles.
|
||||
badfeeling-artifact-12 = The light seems to flicker.
|
||||
badfeeling-artifact-13 = The shadows seem to lengthen.
|
||||
badfeeling-artifact-14 = The walls are getting closer.
|
||||
badfeeling-artifact-15 = Something is wrong.
|
||||
|
||||
badfeeling-artifact-drastic-1 = Someone's trying to kill you!
|
||||
badfeeling-artifact-drastic-2 = There's something out there!
|
||||
badfeeling-artifact-drastic-3 = What's happening to you?
|
||||
badfeeling-artifact-drastic-4 = OH GOD!
|
||||
badfeeling-artifact-drastic-5 = HELP ME!
|
||||
badfeeling-artifact-drastic-6 = You've got to get out of here!
|
||||
@@ -0,0 +1,21 @@
|
||||
goodfeeling-artifact-1 = You feel good.
|
||||
goodfeeling-artifact-2 = Everything seems to be going alright
|
||||
goodfeeling-artifact-3 = You've got a good feeling about this
|
||||
goodfeeling-artifact-4 = Your instincts tell you everything is going to be getting better.
|
||||
goodfeeling-artifact-5 = There's a good feeling in the air.
|
||||
goodfeeling-artifact-6 = Something smells... good.
|
||||
goodfeeling-artifact-7 = The tips of your fingers feel tingly.
|
||||
goodfeeling-artifact-8 = You've got a good feeling about this.
|
||||
goodfeeling-artifact-9 = You feel happy.
|
||||
goodfeeling-artifact-10 = ou fight the urge to smile.
|
||||
goodfeeling-artifact-11 = Your scalp prickles.
|
||||
goodfeeling-artifact-12 = All the colours seem a bit more vibrant.
|
||||
goodfeeling-artifact-13 = Everything seems a little lighter.
|
||||
goodfeeling-artifact-14 = The troubles of the world seem to fade away.
|
||||
|
||||
goodfeeling-artifact-drastic-1 = You want to hug everyone you meet!
|
||||
goodfeeling-artifact-drastic-2 = Everything is going so well!
|
||||
goodfeeling-artifact-drastic-3 = You feel euphoric.
|
||||
goodfeeling-artifact-drastic-4 = You feel giddy.
|
||||
goodfeeling-artifact-drastic-5 = You're so happy suddenly you almost want to dance and sing.
|
||||
goodfeeling-artifact-drastic-6 = You feel like the world is out to help you.
|
||||
@@ -0,0 +1,25 @@
|
||||
- type: entity
|
||||
id: RandomArtifactSpawner
|
||||
name: random artifact spawner
|
||||
parent: MarkerBase
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: red
|
||||
- texture: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi/ano01.png
|
||||
- type: RandomSpawner
|
||||
prototypes:
|
||||
- BadfeelingArtifact
|
||||
- GoodfeelingArtifact
|
||||
- AngryMobsSpawnArtifact
|
||||
- JunkSpawnArtifact
|
||||
- BananaSpawnArtifact
|
||||
chance: 1
|
||||
|
||||
- type: entity
|
||||
id: RandomArtifactSpawner20
|
||||
name: random artifact spawner [20]
|
||||
parent: RandomArtifactSpawner
|
||||
components:
|
||||
- type: RandomSpawner
|
||||
chance: 0.2
|
||||
@@ -0,0 +1,124 @@
|
||||
- type: entity
|
||||
parent: BaseStructureDynamic
|
||||
id: BaseXenoArtifact
|
||||
name: alien artifact
|
||||
description: A strange alien device.
|
||||
abstract: true
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi
|
||||
netsync: false
|
||||
state: ano01
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
- shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.45
|
||||
mass: 150
|
||||
layer:
|
||||
- SmallImpassable
|
||||
mask:
|
||||
- VaultImpassable
|
||||
- type: InteractionOutline
|
||||
- type: Artifact
|
||||
- type: RandomArtifactSprite
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: RandomArtifactVisualizer
|
||||
|
||||
# Telepathic
|
||||
- type: entity
|
||||
parent: BaseXenoArtifact
|
||||
id: BadfeelingArtifact
|
||||
suffix: Badfeeling
|
||||
components:
|
||||
- type: TelepathicArtifact
|
||||
messages:
|
||||
- badfeeling-artifact-1
|
||||
- badfeeling-artifact-2
|
||||
- badfeeling-artifact-3
|
||||
- badfeeling-artifact-4
|
||||
- badfeeling-artifact-5
|
||||
- badfeeling-artifact-6
|
||||
- badfeeling-artifact-7
|
||||
- badfeeling-artifact-8
|
||||
- badfeeling-artifact-9
|
||||
- badfeeling-artifact-10
|
||||
- badfeeling-artifact-11
|
||||
- badfeeling-artifact-12
|
||||
- badfeeling-artifact-13
|
||||
- badfeeling-artifact-14
|
||||
- badfeeling-artifact-15
|
||||
drastic:
|
||||
- badfeeling-artifact-drastic-1
|
||||
- badfeeling-artifact-drastic-2
|
||||
- badfeeling-artifact-drastic-3
|
||||
- badfeeling-artifact-drastic-4
|
||||
- badfeeling-artifact-drastic-5
|
||||
- badfeeling-artifact-drastic-6
|
||||
|
||||
- type: entity
|
||||
parent: BaseXenoArtifact
|
||||
id: GoodfeelingArtifact
|
||||
suffix: Goodfeeling
|
||||
components:
|
||||
- type: TelepathicArtifact
|
||||
messages:
|
||||
- goodfeeling-artifact-1
|
||||
- goodfeeling-artifact-2
|
||||
- goodfeeling-artifact-3
|
||||
- goodfeeling-artifact-4
|
||||
- goodfeeling-artifact-5
|
||||
- goodfeeling-artifact-6
|
||||
- goodfeeling-artifact-7
|
||||
- goodfeeling-artifact-8
|
||||
- goodfeeling-artifact-9
|
||||
- goodfeeling-artifact-10
|
||||
- goodfeeling-artifact-11
|
||||
- goodfeeling-artifact-12
|
||||
- goodfeeling-artifact-13
|
||||
- goodfeeling-artifact-14
|
||||
drastic:
|
||||
- goodfeeling-artifact-drastic-1
|
||||
- goodfeeling-artifact-drastic-2
|
||||
- goodfeeling-artifact-drastic-3
|
||||
- goodfeeling-artifact-drastic-4
|
||||
- goodfeeling-artifact-drastic-5
|
||||
- goodfeeling-artifact-drastic-6
|
||||
|
||||
# Spawners
|
||||
- type: entity
|
||||
parent: BaseXenoArtifact
|
||||
id: AngryMobsSpawnArtifact
|
||||
suffix: Angry Mobs Spawn
|
||||
components:
|
||||
- type: SpawnArtifact
|
||||
maxSpawns: 5
|
||||
possiblePrototypes:
|
||||
- MobCarpHolo
|
||||
- MobCarpMagic
|
||||
|
||||
- type: entity
|
||||
parent: BaseXenoArtifact
|
||||
id: JunkSpawnArtifact
|
||||
suffix: Junk Spawn
|
||||
components:
|
||||
- type: SpawnArtifact
|
||||
maxSpawns: 10
|
||||
possiblePrototypes:
|
||||
- FoodPacketSyndiTrash
|
||||
- FoodPacketSemkiTrash
|
||||
- RandomInstruments
|
||||
- ToySpawner
|
||||
|
||||
- type: entity
|
||||
parent: BaseXenoArtifact
|
||||
id: BananaSpawnArtifact
|
||||
suffix: Banana Spawn
|
||||
components:
|
||||
- type: SpawnArtifact
|
||||
maxSpawns: 20
|
||||
possiblePrototypes:
|
||||
- FoodBanana
|
||||
|
After Width: | Height: | Size: 572 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 304 B |
|
After Width: | Height: | Size: 656 B |
|
After Width: | Height: | Size: 1014 B |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 836 B |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 818 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 337 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 661 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 783 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1004 B |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 745 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1020 B |
|
After Width: | Height: | Size: 1023 B |
|
After Width: | Height: | Size: 787 B |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 435 B |
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from baystation at commit https://github.com/Baystation12/Baystation12/commit/a929584d9db319eb7484113221be25cfa1d5dc09",
|
||||
"states": [
|
||||
{
|
||||
"name": "ano01"
|
||||
},
|
||||
{
|
||||
"name": "ano01_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano02"
|
||||
},
|
||||
{
|
||||
"name": "ano02_on",
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.2,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano03"
|
||||
},
|
||||
{
|
||||
"name": "ano03_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano04"
|
||||
},
|
||||
{
|
||||
"name": "ano04_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano05"
|
||||
},
|
||||
{
|
||||
"name": "ano05_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano06"
|
||||
},
|
||||
{
|
||||
"name": "ano06_on",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano07"
|
||||
},
|
||||
{
|
||||
"name": "ano07_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano08"
|
||||
},
|
||||
{
|
||||
"name": "ano08_on",
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.2,
|
||||
0.2,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano09"
|
||||
},
|
||||
{
|
||||
"name": "ano09_on",
|
||||
"delays": [
|
||||
[
|
||||
0.3,
|
||||
0.3,
|
||||
0.3,
|
||||
0.3
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano10"
|
||||
},
|
||||
{
|
||||
"name": "ano10_on",
|
||||
"delays": [
|
||||
[
|
||||
1.0,
|
||||
0.2,
|
||||
0.1,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano11"
|
||||
},
|
||||
{
|
||||
"name": "ano11_on"
|
||||
},
|
||||
{
|
||||
"name": "ano12"
|
||||
},
|
||||
{
|
||||
"name": "ano12_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano13"
|
||||
},
|
||||
{
|
||||
"name": "ano13_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ano14"
|
||||
},
|
||||
{
|
||||
"name": "ano14_on",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -301,5 +301,6 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=uplink/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wirecutter/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xeno/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xenoarchaeology/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=yamls/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Zumos/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
|
||||