Caching next exent

This commit is contained in:
SolStar2 2024-11-12 18:29:41 -05:00
commit 9f1bee4131
53 changed files with 445 additions and 686 deletions

View File

@ -1,5 +0,0 @@
using Content.Shared.Abilities.Psionics;
namespace Content.Client.Abilities.Psionics;
public sealed class TelegnosisPowerSystem : SharedTelegnosisPowerSystem;

View File

@ -1,10 +1,12 @@
using Content.Server.DeltaV.Cloning;
using Content.Server.Nyanotrasen.Cloning;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.DeltaV;
[TestFixture]
[TestOf(typeof(MetempsychoticMachineSystem))]
public sealed class MetempsychosisTest
{
[Test]
@ -21,22 +23,18 @@ public sealed class MetempsychosisTest
await server.WaitAssertion(() =>
{
prototypeManager.TryIndex(metemComponent.MetempsychoticHumanoidPool,
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticHumanoidPool,
out var humanoidPool);
prototypeManager.TryIndex(metemComponent.MetempsychoticNonHumanoidPool,
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticNonHumanoidPool,
out var nonHumanoidPool);
Assert.Multiple(() =>
{
Assert.That(humanoidPool, Is.Not.Null, "MetempsychoticHumanoidPool is null!");
Assert.That(nonHumanoidPool, Is.Not.Null, "MetempsychoticNonHumanoidPool is null!");
Assert.That(humanoidPool.Weights,
Is.Not.Empty,
"MetempsychoticHumanoidPool has no valid prototypes!");
Assert.That(nonHumanoidPool.Weights,
Is.Not.Empty,
"MetempsychoticNonHumanoidPool has no valid prototypes!");
});
Assert.That(humanoidPool, Is.Not.Null, "MetempsychoticHumanoidPool is null!");
Assert.That(nonHumanoidPool, Is.Not.Null, "MetempsychoticNonHumanoidPool is null!");
Assert.That(humanoidPool.Weights, Is.Not.Empty,
"MetempsychoticHumanoidPool has no valid prototypes!");
Assert.That(nonHumanoidPool.Weights, Is.Not.Empty,
"MetempsychoticNonHumanoidPool has no valid prototypes!");
foreach (var key in humanoidPool.Weights.Keys)
{

View File

@ -9,8 +9,6 @@ using Content.Server.Jobs;
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Server.Psionics; // DeltaV
using Content.Server.Traits.Assorted; // DeltaV
using Content.Shared.Atmos;
using Content.Shared.CCVar;
using Content.Shared.Chemistry.Components;
@ -35,10 +33,26 @@ using Robust.Shared.Containers;
using Robust.Shared.Physics.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Content.Server.Traits.Assorted; //Nyano - Summary: allows the potential psionic ability to be written to the character.
using Content.Server.Psionics; //DeltaV needed for Psionic Systems
using Content.Shared.Speech; //DeltaV Start Metem Usings
using Content.Shared.Tag;
using Content.Shared.Preferences;
using Content.Shared.Emoting;
using Content.Server.Speech.Components;
using Content.Server.StationEvents.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Nyanotrasen.Cloning;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.GameObjects.Components.Localization; //DeltaV End Metem Usings
using Content.Server.EntityList;
using Content.Shared.SSDIndicator;
using Content.Shared.Damage.ForceSay;
using Content.Server.Polymorph.Components;
namespace Content.Server.Cloning
{
public sealed partial class CloningSystem : EntitySystem // DeltaV - Set to partial, see CloningSystem.Metempsychosis.cs
public sealed class CloningSystem : EntitySystem
{
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
[Dependency] private readonly IPlayerManager _playerManager = null!;
@ -62,6 +76,8 @@ namespace Content.Server.Cloning
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly SharedJobSystem _jobs = default!;
[Dependency] private readonly MetempsychoticMachineSystem _metem = default!; //DeltaV
[Dependency] private readonly TagSystem _tag = default!; //DeltaV
public readonly Dictionary<MindComponent, EntityUid> ClonesWaitingForMind = new();
public const float EasyModeCloningCost = 0.7f;
@ -142,10 +158,6 @@ namespace Content.Server.Cloning
if (!Resolve(uid, ref clonePod))
return false;
// DeltaV - This method should use Entity<CloningPodComponent> pod instead
// But I don't want to completely mangle it so we do this here
var podEnt = new Entity<CloningPodComponent>(uid, clonePod);
if (HasComp<ActiveCloningPodComponent>(uid))
return false;
@ -232,13 +244,13 @@ namespace Content.Server.Cloning
AddComp<ActiveCloningPodComponent>(uid);
return true;
}
// End Nyano-code.
}
// end of genetic damage checks
// DeltaV - Replaces CloneAppearance with Metem/Clone via FetchAndSpawnMob
var mob = FetchAndSpawnMob(podEnt, pref, speciesPrototype, humanoid, bodyToClone, karmaBonus);
var mob = FetchAndSpawnMob(clonePod, pref, speciesPrototype, humanoid, bodyToClone, karmaBonus); //DeltaV Replaces CloneAppearance with Metem/Clone via FetchAndSpawnMob
// Nyano - Summary: adds the potential psionic trait to the reanimated mob.
///Nyano - Summary: adds the potential psionic trait to the reanimated mob.
EnsureComp<PotentialPsionicComponent>(mob);
var ev = new CloningEvent(bodyToClone, mob);
@ -336,7 +348,6 @@ namespace Content.Server.Cloning
var transform = Transform(uid);
var indices = _transformSystem.GetGridTilePositionOrDefault((uid, transform));
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
if (HasComp<EmaggedComponent>(uid))
{
_audio.PlayPvs(clonePod.ScreamSound, uid);
@ -364,6 +375,84 @@ namespace Content.Server.Cloning
RemCompDeferred<ActiveCloningPodComponent>(uid);
}
/// <summary>
/// Start Nyano Code: Handles fetching the mob and any appearance stuff...
/// </summary>
private EntityUid FetchAndSpawnMob(CloningPodComponent clonePod, HumanoidCharacterProfile pref, SpeciesPrototype speciesPrototype, HumanoidAppearanceComponent humanoid, EntityUid bodyToClone, float karmaBonus)
{
List<Sex> sexes = new();
bool switchingSpecies = false;
bool applyKarma = false;
var toSpawn = speciesPrototype.Prototype;
TryComp<MetempsychosisKarmaComponent>(bodyToClone, out var oldKarma);
if (TryComp<MetempsychoticMachineComponent>(clonePod.Owner, out var metem))
{
toSpawn = _metem.GetSpawnEntity(clonePod.Owner, karmaBonus, metem, speciesPrototype, out var newSpecies, oldKarma?.Score);
applyKarma = true;
if (newSpecies != null)
{
sexes = newSpecies.Sexes;
if (speciesPrototype.ID != newSpecies.ID)
switchingSpecies = true;
speciesPrototype = newSpecies;
}
}
var mob = Spawn(toSpawn, _transformSystem.GetMapCoordinates(clonePod.Owner));
if (TryComp<HumanoidAppearanceComponent>(mob, out var newHumanoid))
{
if (switchingSpecies || HasComp<MetempsychosisKarmaComponent>(bodyToClone))
{
pref = HumanoidCharacterProfile.RandomWithSpecies(newHumanoid.Species);
if (sexes.Contains(humanoid.Sex))
pref = pref.WithSex(humanoid.Sex);
pref = pref.WithGender(humanoid.Gender);
pref = pref.WithAge(humanoid.Age);
}
_humanoidSystem.LoadProfile(mob, pref);
}
if (applyKarma)
{
var karma = EnsureComp<MetempsychosisKarmaComponent>(mob);
karma.Score++;
if (oldKarma != null)
karma.Score += oldKarma.Score;
}
var ev = new CloningEvent(bodyToClone, mob);
RaiseLocalEvent(bodyToClone, ref ev);
if (!ev.NameHandled)
_metaSystem.SetEntityName(mob, MetaData(bodyToClone).EntityName);
var grammar = EnsureComp<GrammarComponent>(mob);
grammar.ProperNoun = true;
grammar.Gender = humanoid.Gender;
Dirty(mob, grammar);
EnsureComp<PotentialPsionicComponent>(mob);
EnsureComp<SpeechComponent>(mob);
EnsureComp<DamageForceSayComponent>(mob);
EnsureComp<EmotingComponent>(mob);
EnsureComp<MindContainerComponent>(mob);
EnsureComp<SSDIndicatorComponent>(mob);
RemComp<ReplacementAccentComponent>(mob);
RemComp<MonkeyAccentComponent>(mob);
RemComp<SentienceTargetComponent>(mob);
RemComp<GhostTakeoverAvailableComponent>(mob);
_tag.AddTag(mob, "DoorBumpOpener");
return mob;
}
//End Nyano Code
public void Reset(RoundRestartCleanupEvent ev)
{
ClonesWaitingForMind.Clear();

View File

@ -1,79 +0,0 @@
using Content.Server.Chat.Systems;
using Content.Shared.Administration;
using Robust.Shared.Audio;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.Prototypes;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Fun)]
public sealed class AnnounceCustomCommand : IConsoleCommand
{
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IResourceManager _res = default!;
public string Command => "announcecustom";
public string Description => Loc.GetString("cmd-announcecustom-desc");
public string Help => Loc.GetString("cmd-announcecustom-help", ("command", Command));
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var chat = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>();
switch (args.Length)
{
case 0:
shell.WriteError(Loc.GetString("shell-need-minimum-one-argument"));
return;
case > 4:
shell.WriteError(Loc.GetString("shell-wrong-arguments-number"));
return;
}
var message = args[0];
var sender = "Central Command";
var color = Color.Gold;
var sound = new SoundPathSpecifier("/Audio/Announcements/announce.ogg");
// Optional sender argument
if (args.Length >= 2)
sender = args[1];
// Optional color argument
if (args.Length >= 3)
{
try
{
color = Color.FromHex(args[2]);
}
catch
{
shell.WriteError(Loc.GetString("shell-invalid-color-hex"));
return;
}
}
// Optional sound argument
if (args.Length >= 4)
sound = new SoundPathSpecifier(args[3]);
chat.DispatchGlobalAnnouncement(message, sender, true, sound, color);
shell.WriteLine(Loc.GetString("shell-command-success"));
}
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
return args.Length switch
{
1 => CompletionResult.FromHint(Loc.GetString("cmd-announcecustom-arg-message")),
2 => CompletionResult.FromHint(Loc.GetString("shell-argument-username-optional-hint")),
3 => CompletionResult.FromHint(Loc.GetString("cmd-announcecustom-arg-color")),
4 => CompletionResult.FromHintOptions(
CompletionHelper.AudioFilePath(args[3], _protoManager, _res),
Loc.GetString("cmd-announcecustom-arg-sound")
),
_ => CompletionResult.Empty
};
}
}

View File

@ -1,5 +1,5 @@
using Content.Server.Bible.Components;
using Content.Server.DeltaV.Cloning;
using Content.Server.Nyanotrasen.Cloning;
using Content.Shared.Abilities.Psionics;
using Content.Shared.Administration.Logs;
using Content.Shared.Body.Components;

View File

@ -1,172 +0,0 @@
using Content.Server.DeltaV.Cloning;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences;
using Content.Shared.Speech;
using Content.Shared.Emoting;
using Content.Shared.Damage.ForceSay;
using Content.Shared.SSDIndicator;
using Content.Server.Speech.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.StationEvents.Components;
using Content.Server.Psionics;
using Robust.Shared.Random;
using Content.Shared.Mind.Components;
using Content.Shared.Tag;
using Content.Shared.Cloning;
using Content.Shared.Random.Helpers;
using Robust.Shared.GameObjects.Components.Localization;
namespace Content.Server.Cloning;
public sealed partial class CloningSystem
{
[Dependency] private readonly TagSystem _tag = default!;
[Dependency] private readonly GrammarSystem _grammar = default!;
/// <summary>
/// Gets the entity prototype to spawn for a clone based on karma and chance calculations.
/// </summary>
private string GetSpawnEntity(Entity<MetempsychoticMachineComponent> ent, float karmaBonus, SpeciesPrototype oldSpecies, out SpeciesPrototype? species, int karma = 0)
{
// First time being cloned - return original species
if (karma == 0)
{
species = oldSpecies;
return oldSpecies.Prototype;
}
var chance = ent.Comp.HumanoidBaseChance + karmaBonus;
chance -= (1 - ent.Comp.HumanoidBaseChance) * karma;
// Perfect clone chance
if (chance > 1 && _robustRandom.Prob(chance - 1))
{
species = oldSpecies;
return oldSpecies.Prototype;
}
// Roll for humanoid vs non-humanoid
chance = Math.Clamp(chance, 0, 1);
if (_robustRandom.Prob(chance))
{
if (_prototype.TryIndex(ent.Comp.MetempsychoticHumanoidPool, out var humanoidPool))
{
var protoId = humanoidPool.Pick();
if (_prototype.TryIndex<SpeciesPrototype>(protoId, out var speciesPrototype))
{
species = speciesPrototype;
return speciesPrototype.Prototype;
}
}
}
else if (_prototype.TryIndex(ent.Comp.MetempsychoticNonHumanoidPool, out var nonHumanoidPool))
{
// For non-humanoids, return the entity prototype directly
species = null;
return nonHumanoidPool.Pick();
}
// Fallback to original species if prototype indexing fails
Log.Error("Failed to get valid clone type - falling back to original species");
species = oldSpecies;
return oldSpecies.Prototype;
}
/// <summary>
/// Handles fetching the mob and managing appearance for cloning with metempsychosis mechanics
/// </summary>
private EntityUid FetchAndSpawnMob(
Entity<CloningPodComponent> pod,
HumanoidCharacterProfile pref,
SpeciesPrototype speciesPrototype,
HumanoidAppearanceComponent humanoid,
EntityUid bodyToClone,
float karmaBonus)
{
List<Sex> sexes = [];
var switchingSpecies = false;
var applyKarma = false;
var toSpawn = speciesPrototype.Prototype;
// Get existing karma score or start at 0
var karmaScore = 0;
if (TryComp<MetempsychosisKarmaComponent>(bodyToClone, out var oldKarma))
{
karmaScore = oldKarma.Score;
}
if (TryComp<MetempsychoticMachineComponent>(pod.Owner, out var metem))
{
var metemEntity = new Entity<MetempsychoticMachineComponent>(pod.Owner, metem);
toSpawn = GetSpawnEntity(metemEntity, karmaBonus, speciesPrototype, out var newSpecies, karmaScore);
applyKarma = true;
if (newSpecies != null)
{
sexes = newSpecies.Sexes;
speciesPrototype = newSpecies;
if (speciesPrototype.ID != newSpecies.ID)
switchingSpecies = true;
}
}
var mob = Spawn(toSpawn, _transformSystem.GetMapCoordinates(pod.Owner));
// Only try to handle humanoid appearance if we have a humanoid component
if (TryComp<HumanoidAppearanceComponent>(mob, out var newHumanoid))
{
if (switchingSpecies || HasComp<MetempsychosisKarmaComponent>(bodyToClone))
{
pref = HumanoidCharacterProfile.RandomWithSpecies(newHumanoid.Species);
if (sexes.Contains(humanoid.Sex))
pref = pref.WithSex(humanoid.Sex);
pref = pref.WithGender(humanoid.Gender);
pref = pref.WithAge(humanoid.Age);
}
_humanoidSystem.LoadProfile(mob, pref);
}
if (applyKarma)
{
var karma = EnsureComp<MetempsychosisKarmaComponent>(mob);
karma.Score = karmaScore + 1; // Increment karma score
}
var ev = new CloningEvent(bodyToClone, mob);
RaiseLocalEvent(bodyToClone, ref ev);
if (!ev.NameHandled)
_metaSystem.SetEntityName(mob, MetaData(bodyToClone).EntityName);
var grammar = EnsureComp<GrammarComponent>(mob);
var grammarEnt = new Entity<GrammarComponent>(mob, grammar);
_grammar.SetProperNoun(grammarEnt, true);
_grammar.SetGender(grammarEnt, humanoid.Gender);
Dirty(mob, grammar);
SetupBasicComponents(mob);
return mob;
}
// I hate this
private void SetupBasicComponents(EntityUid mob)
{
EnsureComp<PotentialPsionicComponent>(mob);
EnsureComp<SpeechComponent>(mob);
EnsureComp<DamageForceSayComponent>(mob);
EnsureComp<EmotingComponent>(mob);
EnsureComp<MindContainerComponent>(mob);
EnsureComp<SSDIndicatorComponent>(mob);
RemComp<ReplacementAccentComponent>(mob);
RemComp<MonkeyAccentComponent>(mob);
RemComp<SentienceTargetComponent>(mob);
RemComp<GhostTakeoverAvailableComponent>(mob);
_tag.AddTag(mob, "DoorBumpOpener");
}
}

View File

@ -1,11 +0,0 @@
namespace Content.Server.DeltaV.Cloning;
/// <summary>
/// This tracks how many times you have already been cloned and lowers your chance of getting a humanoid each time.
/// </summary>
[RegisterComponent]
public sealed partial class MetempsychosisKarmaComponent : Component
{
[DataField]
public int Score;
}

View File

@ -1,27 +0,0 @@
using Content.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.Server.DeltaV.Cloning;
[RegisterComponent]
public sealed partial class MetempsychoticMachineComponent : Component
{
/// <summary>
/// Base probability of remaining humanoid during cloning. Higher karma reduces this chance.
/// </summary>
[DataField]
public float HumanoidBaseChance = 0.75f;
/// <summary>
/// Species prototypes pool to use for humanoids.
/// </summary>
[DataField]
public ProtoId<WeightedRandomPrototype> MetempsychoticHumanoidPool = "MetempsychoticHumanoidPool";
/// <summary>
/// Entitiy prototypes pool to use for non-humanoids.
/// </summary>
[DataField]
public ProtoId<WeightedRandomPrototype> MetempsychoticNonHumanoidPool = "MetempsychoticNonhumanoidPool";
}

View File

@ -1,60 +1,42 @@
using Content.Server.Fluids.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Fluids.EntitySystems;
using Content.Shared.Fluids.Components;
using JetBrains.Annotations;
namespace Content.Server.Destructible.Thresholds.Behaviors;
[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillBehavior : IThresholdBehavior
namespace Content.Server.Destructible.Thresholds.Behaviors
{
/// <summary>
/// Optional fallback solution name if SpillableComponent is not present.
/// </summary>
[DataField]
public string? Solution;
/// <summary>
/// When triggered, spills the entity's solution onto the ground.
/// Will first try to use the solution from a SpillableComponent if present,
/// otherwise falls back to the solution specified in the behavior's data fields.
/// The solution is properly drained/split before spilling to prevent double-spilling with other behaviors.
/// </summary>
/// <param name="owner">Entity whose solution will be spilled</param>
/// <param name="system">System calling this behavior</param>
/// <param name="cause">Optional entity that caused this behavior to trigger</param>
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillBehavior : IThresholdBehavior
{
var solutionContainerSystem = system.EntityManager.System<SharedSolutionContainerSystem>();
var spillableSystem = system.EntityManager.System<PuddleSystem>();
var coordinates = system.EntityManager.GetComponent<TransformComponent>(owner).Coordinates;
[DataField]
public string? Solution;
Solution targetSolution;
// First try to get solution from SpillableComponent
if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out var solution, out var compSolution))
/// <summary>
/// If there is a SpillableComponent on EntityUidowner use it to create a puddle/smear.
/// Or whatever solution is specified in the behavior itself.
/// If none are available do nothing.
/// </summary>
/// <param name="owner">Entity on which behavior is executed</param>
/// <param name="system">system calling the behavior</param>
/// <param name="cause"></param>
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
// If entity is drainable, drain the solution. Otherwise just split it.
// Both methods ensure the solution is properly removed.
targetSolution = system.EntityManager.HasComponent<DrainableSolutionComponent>(owner)
? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent<DrainableSolutionComponent>(owner)), solution.Value, compSolution.Volume)
: compSolution.SplitSolution(compSolution.Volume);
}
// Fallback to solution specified in behavior data
else if (Solution != null &&
solutionContainerSystem.TryGetSolution(owner, Solution, out var solutionEnt, out var behaviorSolution))
{
targetSolution = system.EntityManager.HasComponent<DrainableSolutionComponent>(owner)
? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent<DrainableSolutionComponent>(owner)), solutionEnt.Value, behaviorSolution.Volume)
: behaviorSolution.SplitSolution(behaviorSolution.Volume);
}
else
return;
var solutionContainerSystem = system.EntityManager.System<SharedSolutionContainerSystem>();
var spillableSystem = system.EntityManager.System<PuddleSystem>();
// Spill the solution that was drained/split
spillableSystem.TrySplashSpillAt(owner, coordinates, targetSolution, out _, false, cause);
var coordinates = system.EntityManager.GetComponent<TransformComponent>(owner).Coordinates;
if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out _, out var compSolution))
{
spillableSystem.TrySplashSpillAt(owner, coordinates, compSolution, out _, false, user: cause);
}
else if (Solution != null &&
solutionContainerSystem.TryGetSolution(owner, Solution, out _, out var behaviorSolution))
{
spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, user: cause);
}
}
}
}

View File

@ -3,7 +3,6 @@ using Content.Server.Body.Systems;
using Content.Server.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared.Chat;
using Content.Shared.Body.Part; // DeltaV
using Content.Shared.Damage;
using Content.Shared.Database;
using Content.Shared.DoAfter;
@ -161,12 +160,9 @@ namespace Content.Server.Kitchen.EntitySystems
_transform.SetCoordinates(victimUid, Transform(uid).Coordinates);
// THE WHAT?
// TODO: Need to be able to leave them on the spike to do DoT, see ss13.
var gibs = _bodySystem.GibBody(victimUid, gibOrgans: true); // DeltaV: spawn organs
var gibs = _bodySystem.GibBody(victimUid);
foreach (var gib in gibs) {
// Begin DeltaV changes: Only delete limbs instead of organs
if (HasComp<BodyPartComponent>(gib))
QueueDel(gib);
// End DeltaV changes
QueueDel(gib);
}
_audio.PlayEntity(component.SpikeSound, Filter.Pvs(uid), uid, true);

View File

@ -9,7 +9,7 @@ using Content.Shared.Actions.Events;
namespace Content.Server.Abilities.Psionics
{
public sealed class TelegnosisPowerSystem : SharedTelegnosisPowerSystem
public sealed class TelegnosisPowerSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;

View File

@ -0,0 +1,12 @@
namespace Content.Server.Nyanotrasen.Cloning
{
/// <summary>
/// This tracks how many times you have already been cloned and lowers your chance of getting a humanoid each time.
/// </summary>
[RegisterComponent]
public sealed partial class MetempsychosisKarmaComponent : Component
{
[DataField("score")]
public int Score = 0;
}
}

View File

@ -0,0 +1,22 @@
using Content.Shared.Random;
namespace Content.Server.Nyanotrasen.Cloning
{
[RegisterComponent]
public sealed partial class MetempsychoticMachineComponent : Component
{
/// <summary>
/// Chance you will spawn as a humanoid instead of a non humanoid.
/// </summary>
[DataField("humanoidBaseChance")]
public float HumanoidBaseChance = 0.75f;
[ValidatePrototypeId<WeightedRandomPrototype>]
[DataField("metempsychoticHumanoidPool")]
public string MetempsychoticHumanoidPool = "MetempsychoticHumanoidPool";
[ValidatePrototypeId<WeightedRandomPrototype>]
[DataField("metempsychoticNonHumanoidPool")]
public string MetempsychoticNonHumanoidPool = "MetempsychoticNonhumanoidPool";
}
}

View File

@ -0,0 +1,47 @@
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Robust.Shared.Random;
using Robust.Shared.Prototypes;
namespace Content.Server.Nyanotrasen.Cloning
{
public sealed class MetempsychoticMachineSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private ISawmill _sawmill = default!;
public string GetSpawnEntity(EntityUid uid, float karmaBonus, MetempsychoticMachineComponent component, SpeciesPrototype oldSpecies, out SpeciesPrototype? species, int? karma = null)
{
var chance = component.HumanoidBaseChance + karmaBonus;
if (karma != null)
chance -= ((1 - component.HumanoidBaseChance) * (float) karma);
if (chance > 1 && _random.Prob(chance - 1))
{
species = oldSpecies;
return oldSpecies.Prototype;
}
else
chance = 1;
chance = Math.Clamp(chance, 0, 1);
if (_random.Prob(chance) &&
_prototypeManager.TryIndex<WeightedRandomPrototype>(component.MetempsychoticHumanoidPool, out var humanoidPool) &&
_prototypeManager.TryIndex<SpeciesPrototype>(humanoidPool.Pick(), out var speciesPrototype))
{
species = speciesPrototype;
return speciesPrototype.Prototype;
}
else
{
species = null;
_sawmill.Error("Could not index species for metempsychotic machine...");
return "MobHuman";
}
}
}
}

View File

@ -33,6 +33,14 @@ namespace Content.Server.StationEvents
{
// A little starting variance so schedulers dont all proc at once.
component.TimeUntilNextEvent = RobustRandom.NextFloat(component.MinimumTimeUntilFirstEvent, component.MinimumTimeUntilFirstEvent + 120);
// DeltaV - end init NextEventComp
NextEventComponent? nextEventComponent = null;
if (Resolve(uid, ref nextEventComponent, false)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
&& firstEvent != null)
_next.UpdateNextEvent(nextEventComponent, firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent));
// DeltaV - end init NextEventComp
}
protected override void Ended(EntityUid uid, BasicStationEventSchedulerComponent component, GameRuleComponent gameRule,
@ -60,19 +68,21 @@ namespace Content.Server.StationEvents
eventScheduler.TimeUntilNextEvent -= frameTime;
continue;
}
NextEventComponent? nextEventComponent = null;
// DeltaV events using NextEventComponent
NextEventComponent? nextEventComponent = null;
if (Resolve(uid, ref nextEventComponent, false)) // If there is a nextEventComponent use the stashed event instead of running it directly.
{
if (!_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, out string? generatedEvent) || generatedEvent == null)
ResetTimer(eventScheduler);
TimeSpan nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(eventScheduler.TimeUntilNextEvent);
if (!_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, out string? generatedEvent, nextEventTime) || generatedEvent == null)
continue;
// Cycle the stashed event with the new generated event and time.
string storedEvent= _next.UpdateNextEvent(nextEventComponent, generatedEvent, (float)_timing.CurTime.TotalSeconds + eventScheduler.TimeUntilNextEvent);
string storedEvent= _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
if (storedEvent == null || storedEvent == string.Empty) //If there was no stored event don't try to run it.
continue;
GameTicker.AddGameRule(storedEvent);
ResetTimer(eventScheduler);
continue;
}
// DeltaV end events using NextEventComponent

View File

@ -58,16 +58,23 @@ public sealed class EventManagerSystem : EntitySystem
/// </summary>
public void RunRandomEvent(EntityTableSelector limitedEventsTable)
{
if(TryGenerateRandomEvent(limitedEventsTable, out string? randomLimitedEvent) && randomLimitedEvent != null) // DeltaV seperated into own method
if(TryGenerateRandomEvent(limitedEventsTable, out string? randomLimitedEvent) && randomLimitedEvent != null) // DeltaV - seperated into own method
GameTicker.AddGameRule(randomLimitedEvent);
}
// DeltaV seperate event generation method
// DeltaV - overloaded for backwards compatiblity
public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, out string? randomLimitedEvent)
{
return TryGenerateRandomEvent(limitedEventsTable, out randomLimitedEvent, null);
}
// DeltaV - end overloaded for backwards compatiblity
// DeltaV - seperate event generation method
public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, out string? randomLimitedEvent, TimeSpan? eventRunTime) // Event time checks compared to eventRunTime
// unless its null in which case current time is used
{
randomLimitedEvent = null;
// Snippet from upstreams RunRandomEvent
if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents))
if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents, eventRunTime))
{
Log.Warning("Provided event table could not build dict!");
return false;
@ -86,21 +93,27 @@ public sealed class EventManagerSystem : EntitySystem
Log.Warning("A requested event is not available!");
return false;
}
// End snippet from upstreams RunRandomEvent
return true;
}
// DeltaV end seperate event generation method
// DeltaV - end seperate event generation method
// DeltaV - overloaded for backwards compatiblity
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents)
{
return TryBuildLimitedEvents(limitedEventsTable, out limitedEvents, null);
}
// DeltaV - end overloaded for backwards compatiblity
/// <summary>
/// Returns true if the provided EntityTableSelector gives at least one prototype with a StationEvent comp.
/// </summary>
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents)
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents, TimeSpan? eventRunTime) // DeltaV - Add a time overide
{
limitedEvents = new Dictionary<EntityPrototype, StationEventComponent>();
var availableEvents = AvailableEvents(); // handles the player counts and individual event restrictions
var availableEvents = AvailableEvents(eventRunTime); // handles the player counts and individual event restrictions
// DeltaV - Overide time for stashing events
if (availableEvents.Count == 0)
{
Log.Warning("No events were available to run!");
@ -186,6 +199,16 @@ public sealed class EventManagerSystem : EntitySystem
return null;
}
// DeltaV - overloaded for backwards compatiblity
public Dictionary<EntityPrototype, StationEventComponent> AvailableEvents(
bool ignoreEarliestStart = false,
int? playerCountOverride = 100,
TimeSpan? currentTimeOverride = null)
{
return AvailableEvents(null, ignoreEarliestStart, playerCountOverride, currentTimeOverride);
}
// DeltaV - end overloaded for backwards compatiblity
/// <summary>
/// Gets the events that have met their player count, time-until start, etc.
/// </summary>
@ -193,16 +216,21 @@ public sealed class EventManagerSystem : EntitySystem
/// <param name="currentTimeOverride">Override for round time, if using this to simulate events rather than in an actual round.</param>
/// <returns></returns>
public Dictionary<EntityPrototype, StationEventComponent> AvailableEvents(
bool ignoreEarliestStart = true,
TimeSpan? eventRunTime,
bool ignoreEarliestStart = false,
int? playerCountOverride = 100,
TimeSpan? currentTimeOverride = null)
TimeSpan? currentTimeOverride = null
)
{
var playerCount = playerCountOverride ?? _playerManager.PlayerCount;
// playerCount does a lock so we'll just keep the variable here
var currentTime = currentTimeOverride ?? (!ignoreEarliestStart
? GameTicker.RoundDuration()
: TimeSpan.Zero);
var currentTime = currentTimeOverride ?? (
(!ignoreEarliestStart
? eventRunTime // DeltaV - Use eventRunTime instead of RoundDuration if provided
?? GameTicker.RoundDuration()
: TimeSpan.Zero)
);
var result = new Dictionary<EntityPrototype, StationEventComponent>();

View File

@ -1,16 +1,20 @@
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.StationEvents.Components;
using Content.Shared.DeltaV.StationEvents;
using Content.Shared.GameTicking.Components;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.StationEvents;
public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingStationEventSchedulerComponent>
{
[Dependency] private readonly IGameTiming _timing = default!; // DeltaV
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly EventManagerSystem _event = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly NextEventSystem _next = default!; // DeltaV
/// <summary>
/// Returns the ChaosModifier which increases as round time increases to a point.
@ -36,6 +40,14 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingS
component.StartingChaos = component.MaxChaos / 10;
PickNextEventTime(uid, component);
// DeltaV - end init NextEventComp
NextEventComponent? nextEventComponent = null;
if (Resolve(uid, ref nextEventComponent, false)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
&& firstEvent != null)
_next.UpdateNextEvent(nextEventComponent, firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent));
// DeltaV - end init NextEventComp
}
public override void Update(float frameTime)
@ -57,6 +69,24 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingS
continue;
}
// DeltaV events using NextEventComponent
NextEventComponent? nextEventComponent = null;
if (Resolve(uid, ref nextEventComponent, false)) // If there is a nextEventComponent use the stashed event instead of running it directly.
{
PickNextEventTime(uid, scheduler);
TimeSpan nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(scheduler.TimeUntilNextEvent);
if (!_event.TryGenerateRandomEvent(scheduler.ScheduledGameRules, out string? generatedEvent, nextEventTime) || generatedEvent == null)
continue;
// Cycle the stashed event with the new generated event and time.
string storedEvent = _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
if (storedEvent == null || storedEvent == string.Empty) //If there was no stored event don't try to run it.
continue;
GameTicker.AddGameRule(storedEvent);
continue;
}
// DeltaV end events using NextEventComponent
PickNextEventTime(uid, scheduler);
_event.RunRandomEvent(scheduler.ScheduledGameRules);
}

View File

@ -15,5 +15,5 @@ public sealed partial class NextEventComponent : Component
/// Round time of the scheduler's next station event.
/// </summary>
[DataField]
public float NextEventTime;
public TimeSpan NextEventTime;
}

View File

@ -7,7 +7,7 @@ public sealed partial class NextEventSystem : EntitySystem
/// <summary>
/// Updates the NextEventComponent with the provided id and time and returns the previously stored id.
/// </summary>
public EntProtoId UpdateNextEvent(NextEventComponent component, EntProtoId newEventId, float newEventTime)
public EntProtoId UpdateNextEvent(NextEventComponent component, EntProtoId newEventId, TimeSpan newEventTime)
{
EntProtoId oldEventId = component.NextEventId; // Store components current NextEventId for return
component.NextEventId = newEventId;

View File

@ -1,19 +0,0 @@
using Content.Shared.Interaction.Events;
namespace Content.Shared.Abilities.Psionics;
public abstract class SharedTelegnosisPowerSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TelegnosticProjectionComponent, InteractionAttemptEvent>(OnInteractionAttempt);
}
private void OnInteractionAttempt(Entity<TelegnosticProjectionComponent> ent, ref InteractionAttemptEvent args)
{
// no astrally stealing someones shoes
args.Cancelled = true;
}
}

View File

@ -5,7 +5,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Shared.Abilities.Psionics
{
[RegisterComponent, Access(typeof(SharedTelegnosisPowerSystem))]
[RegisterComponent]
public sealed partial class TelegnosisPowerComponent : Component
{
[DataField("prototype")]
@ -20,4 +20,4 @@ namespace Content.Shared.Abilities.Psionics
[DataField("telegnosisActionEntity")]
public EntityUid? TelegnosisActionEntity;
}
}
}

View File

@ -1,4 +1,6 @@
namespace Content.Shared.Abilities.Psionics;
[RegisterComponent, Access(typeof(SharedTelegnosisPowerSystem))]
public sealed partial class TelegnosticProjectionComponent : Component;
namespace Content.Shared.Abilities.Psionics
{
[RegisterComponent]
public sealed partial class TelegnosticProjectionComponent : Component
{}
}

View File

@ -1,4 +1,86 @@
Entries:
- author: Ygg01
changes:
- message: Digging dirt.
type: Add
id: 158
time: '2023-12-06T15:58:00.0000000+00:00'
- author: Velcroboy
changes:
- message: Buffed Food Cart storage. Get out there and slang some burgers, chefs!
type: Tweak
id: 159
time: '2023-12-06T15:58:43.0000000+00:00'
- author: ps3moira
changes:
- message: Added mouse operative reinforcements, which can be bought from the Syndicate
uplink
type: Add
id: 160
time: '2023-12-06T16:03:07.0000000+00:00'
- author: evilexecutive
changes:
- message: Harpies now have a visual indication when they're playing a Midi.
type: Add
- message: Harpies have been re-balanced so that they now actually have a numerical
positive.
type: Tweak
id: 161
time: '2023-12-06T20:10:49.0000000+00:00'
- author: DebugOk
changes:
- message: Due to abuse, prisoners now require whitelist to play.
type: Tweak
id: 162
time: '2023-12-07T13:22:03.0000000+00:00'
- author: ps3moira
changes:
- message: Removed bionic syrinx implanter from surplus crate.
type: Remove
id: 163
time: '2023-12-11T23:11:41.0000000+00:00'
- author: ps3moira
changes:
- message: Removed Carpotoxin from Sashimi, now they are sushi-grade!
type: Remove
id: 164
time: '2023-12-13T20:12:46.0000000+00:00'
- author: Adrian16199
changes:
- message: Crew has learned how to make a straw hat out of wheat bushels!
type: Add
id: 165
time: '2023-12-13T20:13:45.0000000+00:00'
- author: IamVelcroboy
changes:
- message: Added Yule! Happy Holidays!
type: Add
id: 166
time: '2023-12-13T20:21:34.0000000+00:00'
- author: ps3moira
changes:
- message: Added Fish n' Chips. Thank the British!
type: Add
id: 167
time: '2023-12-13T20:32:51.0000000+00:00'
- author: Adrian16199
changes:
- message: Felinids now meow out their words. They can also sigh now.
type: Tweak
id: 168
time: '2023-12-13T21:28:39.0000000+00:00'
- author: VMSolidus
changes:
- message: Harpies no longer choke on completely breathable air
type: Fix
id: 169
time: '2023-12-14T05:13:43.0000000+00:00'
- author: UnicornOnLSD
changes:
- message: Changed bags of holding cost to be more consistent.
type: Tweak
id: 170
time: '2023-12-14T09:17:35.0000000+00:00'
- author: Adrian16199
changes:
- message: Fixed non-wizden species not having markings.
@ -3632,100 +3714,3 @@
id: 657
time: '2024-11-08T13:38:47.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2148
- author: Aikakakah
changes:
- message: Added a black turtleneck!
type: Add
id: 658
time: '2024-11-08T20:50:40.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/1905
- author: deltanedas
changes:
- message: Butchering people now drops organs.
type: Tweak
id: 659
time: '2024-11-09T04:40:16.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2154
- author: MilonPL
changes:
- message: The metempsychosis will always use your player character on the first
cloning attempt.
type: Tweak
- message: Fixed metempsychosis never selecting non-humanoid characters.
type: Fix
id: 660
time: '2024-11-09T10:47:17.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2156
- author: MilonPL
changes:
- message: Fixed beaker solutions duplicating whenever it's thrown.
type: Fix
id: 661
time: '2024-11-09T12:46:34.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2157
- author: deltanedas
changes:
- message: The Synthesis Specialist's vendor can now be restocked.
type: Tweak
id: 662
time: '2024-11-09T13:16:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2143
- author: deltanedas
changes:
- message: Fixed telegnostic projections being able to interact with things.
type: Tweak
id: 663
time: '2024-11-09T19:27:59.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2117
- author: Unkn0wnGh0st333
changes:
- message: Synthesis Specialist ghost rules have been slightly adjusted.
type: Tweak
id: 664
time: '2024-11-09T19:44:28.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2152
- author: Colin-Tel
changes:
- message: Removed the "Raise Glimmer" objective for traitors.
type: Remove
id: 665
time: '2024-11-10T20:18:53.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2107
- author: Colin-Tel
changes:
- message: Adjusted antagonist rule C3 and the line about bribery in C1.
type: Tweak
id: 666
time: '2024-11-10T20:20:26.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2164
- author: Stop-Signs
changes:
- message: Removed the T3 Lockout on epi techs
type: Remove
id: 667
time: '2024-11-11T02:57:13.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2144
- author: Radezolid
changes:
- message: The syringe gun is now a researcheable technology in the T2 civilian
category. Get it from the medical techfab once it's researched.
type: Tweak
id: 668
time: '2024-11-11T15:41:44.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2169
- author: Tomce795
changes:
- message: Added a new stamp for Prosecutor and added it to their starting loadout.
Also added the Space Law book to the starting loadout for both Prosec and Clerk.
type: Add
id: 669
time: '2024-11-12T04:15:14.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2158
- author: Unkn0wnGh0st333
changes:
- message: Whoops someone forgot to give Clerk and Prosecutor their company-mandated
mindshields... that's fixed now.
type: Tweak
id: 670
time: '2024-11-12T06:21:28.0000000+00:00'
url: https://github.com/DeltaV-Station/Delta-v/pull/2175

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
## AnnounceCustomCommand
cmd-announcecustom-desc = Send an in-game announcement with custom color and sound.
cmd-announcecustom-help = {$command} <message> [sender] [color] [sound] - Send announcement. Sender defaults to CentCom, color to Gold, sound to announce.ogg
# Completion hints
cmd-announcecustom-arg-message = message
cmd-announcecustom-arg-color = color in #RRGGBB format (optional)
cmd-announcecustom-arg-sound = sound path (optional)

View File

@ -30,12 +30,11 @@ ghost-role-information-silvia-rules = Keep the medical team company and help out
ghost-role-information-synthesis-name = Synthesis Specialist
ghost-role-information-synthesis-description = You are a member of Interdyne Pharmaceutics! You are provided all the tools to manufacture a variety of medical cocktails. Establish your craft, peddle your poisons, and make profit.
ghost-role-information-synthesis-rules =
You are a [color=yellow][bold]Free-Agent[/bold][/color]. You are free to act as either an antagonist or a non-antagonist.
You are just a chemist so do not act like a full-on antagonist, i.e. no killing people yourself unless your ship is in danger.
Brew deadly poisons, marvelous medicines, and anything in between.
Sell your concoctions to [color=red]local agents[/color], crew, and anyone with supplies.
Stay on your ship; it is your job, home, and lifeblood.
Sell your concoctions to local agents, crew, and anyone with supplies.
Stay on your ship, it is your lifeblood!
You are just a chemist so do not act like a full-on antagonist, i.e. no killing people yourself unless your ship is in danger.
ghost-role-information-closet-skeleton-rules = You are a old member of the station, try to get your previous job back or dwell in the maintenance tunnels!.
You are a [color=green][bold]Non-antagonist[/bold][/color]. You should generally not seek to harm the station and its crew.

View File

@ -5,4 +5,3 @@ research-technology-energy-gun = Energy Guns
research-technology-energy-gun-advance = Advanced Energy Manipulation
research-technology-advance-laser = Advanced Laser Manipulation
research-technology-robust-melee = Robust Melee
research-technology-syringe-gun = Syringe Gun

View File

@ -16,7 +16,6 @@
ClothingOuterPonchoClassic: 2
ClothingUniformJumpsuitKilt: 3 # DeltaV - SCOTTTTLANDDDDD FURREVERRRRR!!
ClothingEyesEyepatch: 2 # Delta-V Yarrr
ClothingUniformBlackTurtleneck : 2 # DeltaV - Clothing addition
ClothingHeadHatPwig: 2
ClothingOuterRobesJudge: 2
ClothingOuterPoncho: 2

View File

@ -1,45 +0,0 @@
- type: entity
parent: CrateEngineering
id: CrateEngineEssentials
name: engine essentials crate
description: Everything you need to power the station, in a superposition of containing both a singularity and a tesla.
suffix: 1 per map MAX
components:
- type: EntityTableContainerFill
containers:
entity_storage: !type:GroupSelector
children:
- !type:NestedSelector
tableId: TeslaEssentials
- !type:NestedSelector
tableId: SingularityEssentials
- type: entityTable
id: TeslaEssentials
table: !type:AllSelector
children:
- id: TeslaGeneratorFlatpack
- id: TeslaGeneratorFlatpack
prob: 0.3 # Small chance of a free backup
- id: TeslaCoilFlatpack
amount: !type:RangeNumberSelector
range: 4, 6
- id: TeslaGroundingRodFlatpack
amount: !type:ConstantNumberSelector
value: 4
- type: entityTable
id: SingularityEssentials
table: !type:AllSelector
children:
- id: SingularityGeneratorFlatpack
- id: SingularityGeneratorFlatpack
prob: 0.3 # Small chance of a free backup
# intentionally separate rolls so they are probably mismatched
# you might get spare tanks you might have to get more from the tank dispenser
- id: RadiationCollectorFlatpack
amount: !type:RangeNumberSelector
range: 8, 12
- id: PlasmaTankFilled
amount: !type:RangeNumberSelector
range: 8, 12

View File

@ -397,13 +397,3 @@
- type: Clothing
sprite: DeltaV/Clothing/Uniforms/Jumpsuit/prosecutorred.rsi
- type: entity
parent: ClothingUniformFoldableBase
id: ClothingUniformBlackTurtleneck
name: black turtleneck
description: A simple black turtleneck. Perfect for any wannabe spy.
components:
- type: Sprite
sprite: DeltaV/Clothing/Uniforms/Jumpsuit/black_turtleneck.rsi
- type: Clothing
sprite: DeltaV/Clothing/Uniforms/Jumpsuit/black_turtleneck.rsi

View File

@ -38,12 +38,4 @@
sprite: DeltaV/Structures/Wallmounts/signs.rsi
state: direction_court
- type: entity
parent: BaseSignDirectional
id: SignDirectionaAI
name: AI sign
description: A direction sign, pointing out which way the AI core is.
components:
- type: Sprite
sprite: DeltaV/Structures/Wallmounts/signs.rsi
state: direction_aicore

View File

@ -17,7 +17,6 @@
parent: BaseGameRule
id: GlimmerEventScheduler
components:
- type: NextEvent
- type: BasicStationEventScheduler
minMaxEventTiming:
min: 300

View File

@ -5,20 +5,3 @@
materials:
Steel: 300
Glass: 100
- type: latheRecipe
id: LauncherSyringe
result: LauncherSyringe
completetime: 3
materials:
Steel: 1000
Glass: 500
Plastic: 500
- type: latheRecipe
id: MiniSyringe
result: MiniSyringe
completetime: 1
materials:
Plastic: 150
Steel: 50

View File

@ -1,12 +0,0 @@
- type: technology
id: SyringeGun
name: research-technology-syringe-gun
icon:
sprite: Objects/Weapons/Guns/Cannons/syringe_gun.rsi
state: syringe_gun
discipline: CivilianServices
tier: 2
cost: 10000
recipeUnlocks:
- LauncherSyringe
- MiniSyringe

View File

@ -482,7 +482,6 @@
- type: VendingMachineRestock
canRestock:
- ChemVendInventory
- ChemVendInventorySyndicate # DeltaV: Let it restock synthesis/nukie vendor
- type: Sprite
layers:
- state: base

View File

@ -436,8 +436,6 @@
- MagazineBoxSpecialHoly
- MagazineBoxSpecialMindbreaker
- AdvancedTruncheon
- LauncherSyringe
- MiniSyringe
# End DeltaV additions
- type: entity
@ -1068,10 +1066,6 @@
- WhiteCane
- AACTablet # DeltaV
dynamicRecipes:
# Begin DeltaV additions
- LauncherSyringe
- MiniSyringe
# End DeltaV additions
- ChemicalPayload
- CryostasisBeaker
- BluespaceBeaker

View File

@ -2160,7 +2160,7 @@
parent: VendingMachineChemicals
id: VendingMachineChemicalsSyndicate
name: SyndieJuice
description: Not made with freshly squeezed syndies I hope. Backwards compatible with standard ChemVend restocks. # DeltaV: Add chemvend part
description: Not made with freshly squeezed syndies I hope.
components:
- type: VendingMachine
pack: ChemVendInventorySyndicate

View File

@ -55,6 +55,7 @@
parent: BaseGameRule
id: MeteorSwarmScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
@ -68,6 +69,7 @@
parent: BaseGameRule
id: MeteorSwarmMildScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
@ -82,6 +84,7 @@
parent: BaseGameRule
id: KesslerSyndromeScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: RampingStationEventScheduler
scheduledGameRules: !type:NestedSelector
@ -94,6 +97,7 @@
id: GameRuleMeteorSwarm
abstract: true
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: StationEvent
reoccurrenceDelay: 1

View File

@ -309,6 +309,7 @@
id: RampingStationEventScheduler
parent: BaseGameRule
components:
- type: NextEvent # DeltaV: Queue Event
- type: RampingStationEventScheduler
averageChaos: 4.5 # DeltaV
averageEndTime: 180 # DeltaV

View File

@ -50,3 +50,18 @@
# components:
# - BecomePsionicCondition
# - type: BecomeGolemCondition
- type: entity
id: RaiseGlimmerObjective
parent: BaseTraitorObjective
name: Raise Glimmer.
description: Get the glimmer above the specified amount.
components:
- type: Objective
difficulty: 2.5
#unique: false
icon:
sprite: Nyanotrasen/Icons/psi.rsi
state: psi
- type: RaiseGlimmerCondition
target: 500

View File

@ -49,6 +49,8 @@
weights:
RandomTraitorAliveObjective: 1
RandomTraitorProgressObjective: 1
RaiseGlimmerObjective: 0.5 # Nyanotrasen - Raise glimmer to a target amount, see Resources/Prototypes/Nyanotrasen/Objectives/traitor.yml
#Thief groups
- type: weightedRandom

View File

@ -5,11 +5,10 @@
icon:
sprite: Interface/Misc/research_disciplines.rsi
state: industrial
lockoutTier: 4 # DeltaV: Lockout occurs at t4
tierPrerequisites:
1: 0
2: 1 # DeltaV: raised to 1
3: 1 # DeltaV: raised to 1
2: 0.75
3: 0.75
- type: techDiscipline
id: Arsenal
@ -18,11 +17,10 @@
icon:
sprite: Interface/Misc/research_disciplines.rsi
state: arsenal
lockoutTier: 4 # DeltaV: Lockout occurs at t4
tierPrerequisites:
1: 0
2: 1 # DeltaV: raised to 1
3: 1 # DeltaV: raised to 1
2: 0.75
3: 0.75
- type: techDiscipline
id: Experimental
@ -31,11 +29,10 @@
icon:
sprite: Interface/Misc/research_disciplines.rsi
state: experimental
lockoutTier: 4 # DeltaV: Lockout occurs at t4
tierPrerequisites:
1: 0
2: 1 # DeltaV: raised to 1
3: 1 # DeltaV: raised to 1
2: 0.75
3: 0.75
- type: techDiscipline
id: CivilianServices
@ -44,8 +41,7 @@
icon:
sprite: Interface/Misc/research_disciplines.rsi
state: civilianservices
lockoutTier: 4 # DeltaV: Lockout occurs at t4
tierPrerequisites:
1: 0
2: 1 # DeltaV: raised to 1
3: 1 # DeltaV: raised to 1
2: 0.75
3: 0.75

View File

@ -116,6 +116,7 @@
- Giving a character additional access or a job because you are friends with the player who is playing that character.
- Trusting a character because you are friends with the player who is playing that character.
- Not fighting a character because you are friends with the player who is playing that character.
- Ignoring your objective to kill a character because your character and theirs became friends in a previous round.
## Metagrudging Examples
These are all examples of things that are prohibited by at least one metashield item that is never revealed IC.

View File

@ -4,7 +4,7 @@ Security, Justice, and Command roles are held to a higher standard of roleplay,
- Your character must act in a manner that NanoTrasen would reasonably hire them to this position.
- Your character is presumed to be sane, competent in their duties, and able to make decisions to the benefit of the station.
- Giving away Traitor objective items and sensitive equipment should be avoided in these roles. Your character should value them deeply.
- Leeway is given to making deals with criminals if the deal benefits the safety or situation of the crew and station OR if the deal involves items of a primarily sentimental value (e.g. HoP's Ian scrapbook, LO's lucky dollar).
- Leeway is given to making deals with criminals if the deal benefits the safety or situation of the crew and station.
- Leeway can be given in [color=#ff0000]extreme circumstances[/color] of emergency/crisis.
- The three departments are required to read and follow Delta-V Space Law, Standard Operating Procedure, Alert Procedure, and Company Policy to the best of their ability.
- [color=#ff0000]Circumstances and context may permit you to break these laws. However, the fact that this rule is malleable is not an excuse to ignore it entirely.[/color]

View File

@ -1,12 +1,9 @@
<Document>
# Rule C3: Antagonist Guidelines
[color=#ffff00]Being an antagonist does not allow you to stop playing a character. Determine how your character would react to being given these objectives, and work through it appropriately.[/color]
Through engaging in antagonistic activity, you should seek to make the round more engaging and fun as the primary driver of the narrative of a round. Succeeding as an antagonist should not be your goal, but rather telling the most interesting story for everyone involved.
- [color=#ff0000]Antagonists are free to complete their objectives through committing proportional damage. Through roleplay, damage becomes more proportional.[/color] Example: Holding the singulo hostage for a theft objective is acceptable, while simply singuloosing and using that chaos is unacceptable.
- Killing players unrelated to your immediate objective in a manner that results in their round removal should be avoided. Crew that do not make an attempt at self preservation, or engage in valid-hunting, are exempt from this.
- If you are concerned as to whether or not what you're about to do is allowed, feel free to AHelp and ask an admin for clarification. [color=#ff0000]Lack of administrator response does not constitute approval.[/color]
- While antagonists are [color=#ffff00]not required[/color] to complete their objectives, they are still encouraged to act as an antagonist in the round while roleplaying.
- Other antagonists are not necessarily your friends. Other antagonists are often free agents that you may negotiate with at your own risk.
- If you are a team antagonist, you must work with your partners to complete any shared objectives.
- Excessively lame tactics are strictly forbidden for all antags except for station-destroying antags, such as nuclear operatives or space dragons. Examples include:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

View File

@ -1,30 +0,0 @@
{
"version": 1,
"license": "CC-BY-SA-4.0",
"copyright": "Created by Aikakakah (github) for Delta-V",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
},
{
"name": "equipped-INNERCLOTHING",
"directions": 4
},
{
"name": "rolled-equipped-INNERCLOTHING",
"directions": 4
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

View File

@ -23,10 +23,6 @@
"name": "direction_justice",
"directions": 4
},
{
"name": "direction_aicore",
"directions": 4
},
{
"name": "chapel"
}