fix metempsychosis (#2156)
* this is an insult to my sanity * this is an insult to my sanity * Revert "Merge branch 'shitcode' of https://github.com/MilonPL/Delta-v into shitcode" This reverts commit3de8ffc704, reversing changes made tob22c053376. * FUCKING GITSHIT * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * docs and shit
This commit is contained in:
parent
a4755ff66e
commit
38d6e87dd9
|
|
@ -1,12 +1,10 @@
|
||||||
using Content.Server.Nyanotrasen.Cloning;
|
using Content.Server.DeltaV.Cloning;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Content.Shared.Random;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests.DeltaV;
|
namespace Content.IntegrationTests.Tests.DeltaV;
|
||||||
|
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[TestOf(typeof(MetempsychoticMachineSystem))]
|
|
||||||
public sealed class MetempsychosisTest
|
public sealed class MetempsychosisTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
|
@ -23,18 +21,22 @@ public sealed class MetempsychosisTest
|
||||||
|
|
||||||
await server.WaitAssertion(() =>
|
await server.WaitAssertion(() =>
|
||||||
{
|
{
|
||||||
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticHumanoidPool,
|
prototypeManager.TryIndex(metemComponent.MetempsychoticHumanoidPool,
|
||||||
out var humanoidPool);
|
out var humanoidPool);
|
||||||
prototypeManager.TryIndex<WeightedRandomPrototype>(metemComponent.MetempsychoticNonHumanoidPool,
|
prototypeManager.TryIndex(metemComponent.MetempsychoticNonHumanoidPool,
|
||||||
out var nonHumanoidPool);
|
out var nonHumanoidPool);
|
||||||
|
|
||||||
Assert.That(humanoidPool, Is.Not.Null, "MetempsychoticHumanoidPool is null!");
|
Assert.Multiple(() =>
|
||||||
Assert.That(nonHumanoidPool, Is.Not.Null, "MetempsychoticNonHumanoidPool is null!");
|
{
|
||||||
|
Assert.That(humanoidPool, Is.Not.Null, "MetempsychoticHumanoidPool is null!");
|
||||||
Assert.That(humanoidPool.Weights, Is.Not.Empty,
|
Assert.That(nonHumanoidPool, Is.Not.Null, "MetempsychoticNonHumanoidPool is null!");
|
||||||
"MetempsychoticHumanoidPool has no valid prototypes!");
|
Assert.That(humanoidPool.Weights,
|
||||||
Assert.That(nonHumanoidPool.Weights, Is.Not.Empty,
|
Is.Not.Empty,
|
||||||
"MetempsychoticNonHumanoidPool has no valid prototypes!");
|
"MetempsychoticHumanoidPool has no valid prototypes!");
|
||||||
|
Assert.That(nonHumanoidPool.Weights,
|
||||||
|
Is.Not.Empty,
|
||||||
|
"MetempsychoticNonHumanoidPool has no valid prototypes!");
|
||||||
|
});
|
||||||
|
|
||||||
foreach (var key in humanoidPool.Weights.Keys)
|
foreach (var key in humanoidPool.Weights.Keys)
|
||||||
{
|
{
|
||||||
|
|
@ -9,6 +9,8 @@ using Content.Server.Jobs;
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
|
using Content.Server.Psionics; // DeltaV
|
||||||
|
using Content.Server.Traits.Assorted; // DeltaV
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
|
|
@ -33,26 +35,10 @@ using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
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
|
namespace Content.Server.Cloning
|
||||||
{
|
{
|
||||||
public sealed class CloningSystem : EntitySystem
|
public sealed partial class CloningSystem : EntitySystem // DeltaV - Set to partial, see CloningSystem.Metempsychosis.cs
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = null!;
|
[Dependency] private readonly IPlayerManager _playerManager = null!;
|
||||||
|
|
@ -76,8 +62,6 @@ namespace Content.Server.Cloning
|
||||||
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
[Dependency] private readonly MetaDataSystem _metaSystem = default!;
|
||||||
[Dependency] private readonly SharedJobSystem _jobs = 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 readonly Dictionary<MindComponent, EntityUid> ClonesWaitingForMind = new();
|
||||||
public const float EasyModeCloningCost = 0.7f;
|
public const float EasyModeCloningCost = 0.7f;
|
||||||
|
|
@ -158,6 +142,10 @@ namespace Content.Server.Cloning
|
||||||
if (!Resolve(uid, ref clonePod))
|
if (!Resolve(uid, ref clonePod))
|
||||||
return false;
|
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))
|
if (HasComp<ActiveCloningPodComponent>(uid))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -244,13 +232,13 @@ namespace Content.Server.Cloning
|
||||||
AddComp<ActiveCloningPodComponent>(uid);
|
AddComp<ActiveCloningPodComponent>(uid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// End Nyano-code.
|
|
||||||
}
|
}
|
||||||
// end of genetic damage checks
|
// end of genetic damage checks
|
||||||
|
|
||||||
var mob = FetchAndSpawnMob(clonePod, pref, speciesPrototype, humanoid, bodyToClone, karmaBonus); //DeltaV Replaces CloneAppearance with Metem/Clone via FetchAndSpawnMob
|
// DeltaV - Replaces CloneAppearance with Metem/Clone via FetchAndSpawnMob
|
||||||
|
var mob = FetchAndSpawnMob(podEnt, pref, speciesPrototype, humanoid, bodyToClone, karmaBonus);
|
||||||
|
|
||||||
///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);
|
EnsureComp<PotentialPsionicComponent>(mob);
|
||||||
|
|
||||||
var ev = new CloningEvent(bodyToClone, mob);
|
var ev = new CloningEvent(bodyToClone, mob);
|
||||||
|
|
@ -348,6 +336,7 @@ namespace Content.Server.Cloning
|
||||||
var transform = Transform(uid);
|
var transform = Transform(uid);
|
||||||
var indices = _transformSystem.GetGridTilePositionOrDefault((uid, transform));
|
var indices = _transformSystem.GetGridTilePositionOrDefault((uid, transform));
|
||||||
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
|
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
|
||||||
|
|
||||||
if (HasComp<EmaggedComponent>(uid))
|
if (HasComp<EmaggedComponent>(uid))
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(clonePod.ScreamSound, uid);
|
_audio.PlayPvs(clonePod.ScreamSound, uid);
|
||||||
|
|
@ -375,84 +364,6 @@ namespace Content.Server.Cloning
|
||||||
RemCompDeferred<ActiveCloningPodComponent>(uid);
|
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)
|
public void Reset(RoundRestartCleanupEvent ev)
|
||||||
{
|
{
|
||||||
ClonesWaitingForMind.Clear();
|
ClonesWaitingForMind.Clear();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
using Content.Server.Bible.Components;
|
using Content.Server.Bible.Components;
|
||||||
using Content.Server.Nyanotrasen.Cloning;
|
using Content.Server.DeltaV.Cloning;
|
||||||
using Content.Shared.Abilities.Psionics;
|
using Content.Shared.Abilities.Psionics;
|
||||||
using Content.Shared.Administration.Logs;
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue