Metempsychosis Returns (#685)

* Metempsychosis Returns

* Last updates

* Fixin the linter

* Update lathe.yml

* Update CloningSystem.cs

* Fixing the random name bug

* Fugitive, rough but functional

* Update fugitive.yml

* Update humanoid.yml

* Checking if its the floortile

* Guh

* Update EntityTest.cs

* Revert "Update EntityTest.cs"

This reverts commit 82375acd67.

* Revert "Guh"

This reverts commit bc98f0f858.

* Revert "Checking if its the floortile"

This reverts commit 51d3355cc1.

* Revert "Update humanoid.yml"

This reverts commit 5af8fbdabe.

* Revert "Update fugitive.yml"

This reverts commit 13124dbc77.

* Revert "Fugitive, rough but functional"

This reverts commit 47586c3b15.

* Update Content.Server/Medical/Components/MedicalScannerComponent.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Content.Server/Nyanotrasen/Cloning/MetempsychosisKarmaComponent.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineComponent.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Resources/Prototypes/Nyanotrasen/Entities/Structures/Machines/metempsychoticMachine.yml

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Resources/Prototypes/Nyanotrasen/Research/biochemical.yml.yml

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update Resources/Textures/Nyanotrasen/Structures/Machines/metempsychotic.rsi/meta.json

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningSystem.cs

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningSystem.cs

* Update Content.Server/Nyanotrasen/Cloning/MetempsychoticMachineSystem.cs

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update MetempsychoticMachineSystem.cs

* Cleaning up some of the Metem code

* Update CloningConsoleSystem.cs

reordering for less merge conflict

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Reordering usings for less merge conflicts

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update HumanoidAppearanceComponent.cs

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningSystem.cs

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Apply suggestions from code review

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningConsoleSystem.cs

Somehow this got removed during cleanup

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningConsoleSystem.cs

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningSystem.cs

I put it back in the wrong file...

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update CloningConsoleSystem.cs

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Apply suggestions from code review

Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Requested changes but need assistance with test fail

* biochem is gone apparently

* Update experimental.yml

Signed-off-by: VMSolidus <evilexecutive@gmail.com>

* Update MetempsychosisTest.cs

* Update CloningSystem.cs

---------

Signed-off-by: VMSolidus <evilexecutive@gmail.com>
Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com>
This commit is contained in:
VMSolidus 2024-02-17 21:36:16 -05:00 committed by GitHub
parent 1e83a0ed6e
commit 8df7cc309e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 359 additions and 19 deletions

View File

@ -0,0 +1,53 @@
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]
public async Task AllHumanoidPoolSpeciesExist()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
// Per RobustIntegrationTest.cs, wait until state is settled to access it.
await server.WaitIdleAsync();
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
var metemComponent = new MetempsychoticMachineComponent();
await server.WaitAssertion(() =>
{
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticHumanoidPool,
out var humanoidPool);
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticNonHumanoidPool,
out var nonHumanoidPool);
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)
{
Assert.That(prototypeManager.TryIndex<SpeciesPrototype>(key, out _),
$"MetempsychoticHumanoidPool has invalid prototype {key}!");
}
foreach (var key in nonHumanoidPool.Weights.Keys)
{
Assert.That(prototypeManager.TryIndex<EntityPrototype>(key, out _),
$"MetempsychoticNonHumanoidPool has invalid prototype {key}!");
}
});
await pair.CleanReturnAsync();
}
}

View File

@ -32,7 +32,7 @@ namespace Content.Server.Cloning
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly PowerReceiverSystem _powerReceiverSystem = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
public override void Initialize()
{
base.Initialize();
@ -169,8 +169,8 @@ namespace Content.Server.Cloning
if (mind.UserId.HasValue == false || mind.Session == null)
return;
if (_cloningSystem.TryCloning(cloningPodUid, body.Value, (mindId, mind), cloningPod, scannerComp.CloningFailChanceMultiplier))
// Nyano: Adds scannerComp.MetemKarmaBonus
if (_cloningSystem.TryCloning(cloningPodUid, body.Value, (mindId, mind), cloningPod, scannerComp.CloningFailChanceMultiplier, scannerComp.MetemKarmaBonus))
_adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(uid)} successfully cloned {ToPrettyString(body.Value)}.");
}

View File

@ -33,8 +33,22 @@ using Robust.Shared.Containers;
using Robust.Shared.Physics.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Content.Server.Psionics;
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
{
@ -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;
@ -136,8 +152,8 @@ namespace Content.Server.Cloning
args.PushMarkup(Loc.GetString("cloning-pod-biomass", ("number", _material.GetMaterialAmount(uid, component.RequiredMaterial))));
}
public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponent> mindEnt, CloningPodComponent? clonePod, float failChanceModifier = 1)
// Nyano: Adds float karmaBonus
public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponent> mindEnt, CloningPodComponent? clonePod, float failChanceModifier = 1, float karmaBonus = 0.25f)
{
if (!Resolve(uid, ref clonePod))
return false;
@ -167,6 +183,12 @@ namespace Content.Server.Cloning
if (!TryComp<HumanoidAppearanceComponent>(bodyToClone, out var humanoid))
return false; // whatever body was to be cloned, was not a humanoid
// Begin Nyano-code: allow paradox anomalies to be cloned.
var pref = humanoid.LastProfileLoaded;
if (pref == null)
return false;
// End Nyano-code
if (!_prototype.TryIndex(humanoid.Species, out var speciesPrototype))
return false;
@ -222,11 +244,11 @@ namespace Content.Server.Cloning
AddComp<ActiveCloningPodComponent>(uid);
return true;
}
// End Nyano-code.
}
// end of genetic damage checks
var mob = Spawn(speciesPrototype.Prototype, Transform(uid).MapPosition);
_humanoidSystem.CloneAppearance(bodyToClone, mob);
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.
EnsureComp<PotentialPsionicComponent>(mob);
@ -326,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);
@ -354,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, Transform(clonePod.Owner).MapPosition);
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(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

@ -15,5 +15,8 @@ namespace Content.Server.Medical.Components
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float CloningFailChanceMultiplier = 1f;
// Nyano, needed for Metem Machine.
public float MetemKarmaBonus = 0.25f;
}
}

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

@ -6,6 +6,7 @@ using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Content.Shared.Preferences; //DeltaV, used for Metempsychosis, Fugitive, and Paradox Anomaly
namespace Content.Shared.Humanoid;

View File

@ -1,2 +1,3 @@
research-technology-psionic-countermeasures = Psionic Countermeasures
research-technology-teleportation = Teleportation
research-technology-metempsychosis = Metempsychosis

View File

@ -466,7 +466,7 @@
- MailingUnitElectronics
- SalvageMagnetMachineCircuitboard
- StationMapElectronics
# - MetempsychoticMachineCircuitboard
- MetempsychoticMachineCircuitboard
- DeepFryerMachineCircuitboard
# End Nyano additions
- SalvageExpeditionsComputerCircuitboard # DeltaV

View File

@ -1,3 +1,24 @@
- type: entity
id: MetempsychoticMachineCircuitboard
parent: BaseMachineCircuitboard
name: metempsychotic machine machine board
description: A machine printed circuit board for a cloning pod
components:
- type: Sprite
state: medical
- type: MachineBoard
prototype: MetempsychoticMachine
requirements:
Capacitor: 2
Manipulator: 2
materialRequirements:
Glass: 1
Cable: 1
- type: ReverseEngineering
difficulty: 3
recipes:
- MetempsychoticMachineCircuitboard
- type: entity
id: ReverseEngineeringMachineCircuitboard
parent: BaseMachineCircuitboard

View File

@ -0,0 +1,25 @@
- type: entity
parent: CloningPod
id: MetempsychoticMachine
name: metempsychotic machine
description: Speeds along the transmigration of a soul to its next vessel.
components:
- type: MetempsychoticMachine
- type: CloningPod
- type: Machine
board: MetempsychoticMachineCircuitboard
- type: Sprite
sprite: Nyanotrasen/Structures/Machines/metempsychotic.rsi
snapCardinals: true
layers:
- state: pod_0
- type: Appearance
- type: GenericVisualizer
visuals:
enum.CloningPodVisuals.Status:
base:
Cloning: { state: pod_1 }
NoMind: { state: pod_1 }
Gore: { state: pod_1 }
Idle: { state: pod_0 }
- type: Psionic

View File

@ -1,11 +1,11 @@
#- type: latheRecipe
# id: MetempsychoticMachineCircuitboard
# result: MetempsychoticMachineCircuitboard
# completetime: 4
# materials:
# Steel: 100
# Glass: 900
# Gold: 100
- type: latheRecipe
id: MetempsychoticMachineCircuitboard
result: MetempsychoticMachineCircuitboard
completetime: 4
materials:
Steel: 100
Glass: 900
Gold: 100
- type: latheRecipe
id: ReverseEngineeringMachineCircuitboard
@ -50,4 +50,4 @@
completetime: 4
materials:
Steel: 100
Glass: 900
Glass: 900

View File

@ -14,6 +14,22 @@
- ClothingHeadCage
# - ShellSoulbreaker # DeltaV - Placing it under Exotic Ammunition because that's what it is.
- type: technology
id: Metempsychosis
name: research-technology-metempsychosis
icon:
sprite: Nyanotrasen/Structures/Machines/metempsychotic.rsi
state: pod_0
discipline: Experimental
tier: 2
cost: 15000
recipeUnlocks:
- BiomassReclaimerMachineCircuitboard
- CloningConsoleComputerCircuitboard
- MedicalScannerMachineCircuitboard
- MetempsychoticMachineCircuitboard
# Tier 3
# - type: technology

View File

@ -0,0 +1,13 @@
- type: weightedRandom
id: MetempsychoticHumanoidPool # Species prototypes
weights:
Human: 1
Felinid: 1
Oni: 1
Arachnid: 1
Harpy: 1
Moth: 1
Diona: 0.5
Reptilian: 0.5
SlimePerson: 0.5
Vulpkanin: 0.5

View File

@ -0,0 +1,9 @@
- type: weightedRandom
id: MetempsychoticNonhumanoidPool # Entity prototypes
weights:
MobMonkey: 1
MobGorilla: 1
# MobKangaroo: 0.5 # Mobs here need to be either VERY funny or up to standard.
MobXenoQueen: 0.01
MobCrab: 0.01
MobPenguin: 1 #ODJ's orders

View File

@ -0,0 +1,18 @@
{
"version": 1,
"license": "CC-BY-4.0",
"copyright": "Created by discord user Four Hydra Heads#2075 (971500282364178512)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "pod_0"
},
{
"name": "pod_1",
"delays": [ [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ] ]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB