Skip to content

Commit

Permalink
Allow Cloning Living People (#1679)
Browse files Browse the repository at this point in the history
# Description

Allows living people to be cloned. Implements (but does not cherry-pick)
Goob-Station/Goob-Station#932. Whether living
people can be cloned or not can be set with a new CVar
`cloning.allow_living_people`.

Also prevents Plasmamen from self-igniting while being cloned in a
cloning pod. (Lore reason: They are literally submerged in fluids while
being cloned)

Fixes a bug in `EndFailedCloning` that caused the server to crash if the
used biomass was too low:
02c020b

Fixed a bug that caused the cloning timer to be made twice:
d4620fd

## Media

Cloned living person


![2025-01-28-093759_hyprshot](https://github.com/user-attachments/assets/0af0737a-6f4d-40af-acf5-ce73754f1420)

# Changelog

:cl: Skubman
- tweak: You can now clone living people.
- tweak: Plasmamen no longer ignite while being cloned in a cloning pod.
  • Loading branch information
angelofallars authored Jan 28, 2025
1 parent 7d345cf commit 695f476
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 7 deletions.
2 changes: 2 additions & 0 deletions Content.Server/Atmos/EntitySystems/IgniteFromGasSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.Bed.Components;
using Content.Server.Cloning.Components;
using Content.Shared._Shitmed.Targeting;
using Content.Shared._Shitmed.Body.Events;
using Content.Shared.Body.Part;
Expand Down Expand Up @@ -123,6 +124,7 @@ public override void Update(float frameTime)
if (ignite.FireStacksPerUpdate == 0 ||
mobState.CurrentState is MobState.Dead ||
HasComp<InStasisComponent>(uid) ||
HasComp<BeingClonedComponent>(uid) ||
_atmos.GetContainingMixture(uid, excite: true) is not { } gas ||
gas[(int) ignite.Gas] < ignite.MolesToIgnite
)
Expand Down
5 changes: 4 additions & 1 deletion Content.Server/Cloning/CloningConsoleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.UserInterface;
using Content.Shared.CCVar;
using Content.Shared.Cloning;
using Content.Shared.Cloning.CloningConsole;
using Content.Shared.Database;
Expand All @@ -19,6 +20,7 @@
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Configuration;

namespace Content.Server.Cloning
{
Expand All @@ -33,6 +35,7 @@ public sealed class CloningConsoleSystem : EntitySystem
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly PowerReceiverSystem _powerReceiverSystem = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly IConfigurationManager _config = default!;

public override void Initialize()
{
Expand Down Expand Up @@ -220,7 +223,7 @@ private CloningConsoleBoundUserInterfaceState GetUserInterfaceState(CloningConso
{
scanBodyInfo = MetaData(scanBody.Value).EntityName;

if (!_mobStateSystem.IsDead(scanBody.Value))
if (!_config.GetCVar(CCVars.CloningAllowLivingPeople) && !_mobStateSystem.IsDead(scanBody.Value))
clonerStatus = ClonerStatus.ScannerOccupantAlive;
else if (!_mindSystem.TryGetMind(scanBody.Value, out _, out var mind)
|| mind.UserId == null
Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Cloning/CloningSystem.Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private void EndFailedCloning(EntityUid uid, CloningPodComponent clonePod)
}

if (!HasComp<EmaggedComponent>(uid))
_material.SpawnMultipleFromMaterial(_random.Next(1, (int) (clonePod.UsedBiomass / 2.5)), clonePod.RequiredMaterial, Transform(uid).Coordinates);
_material.SpawnMultipleFromMaterial(_random.Next(1, Math.Max(1, (int) (clonePod.UsedBiomass / 2.5))), clonePod.RequiredMaterial, Transform(uid).Coordinates);

clonePod.UsedBiomass = 0;
clonePod.ActivelyCloning = false;
Expand Down
20 changes: 15 additions & 5 deletions Content.Server/Cloning/CloningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ public sealed partial class CloningSystem : EntitySystem
[Dependency] private readonly MobThresholdSystem _thresholds = default!;
public readonly Dictionary<MindComponent, EntityUid> ClonesWaitingForMind = new();

// <summary>
// The minimum mass an entity needs for its mass to affect the cloning timer with a MassContest.
// </summary>
private const float MinMassContestMass = 71f;

public override void Initialize()
{
base.Initialize();
Expand Down Expand Up @@ -179,7 +184,8 @@ private void Reset(RoundRestartCleanupEvent ev)
/// </summary>
public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponent> mindEnt, CloningPodComponent clonePod, float failChanceModifier = 1)
{
if (!_mobStateSystem.IsDead(bodyToClone)
var allowLivingPeople = _config.GetCVar(CCVars.CloningAllowLivingPeople);
if ((!allowLivingPeople && !_mobStateSystem.IsDead(bodyToClone))
|| clonePod.ActivelyCloning
|| clonePod.ConnectedConsole == null
|| !CheckUncloneable(uid, bodyToClone, clonePod, out var cloningCostMultiplier)
Expand All @@ -190,7 +196,8 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen
var mind = mindEnt.Comp;
if (ClonesWaitingForMind.TryGetValue(mind, out var clone))
{
if (EntityManager.EntityExists(clone) &&
if (!allowLivingPeople &&
EntityManager.EntityExists(clone) &&
!_mobStateSystem.IsDead(clone) &&
TryComp<MindContainerComponent>(clone, out var cloneMindComp) &&
(cloneMindComp.Mind == null || cloneMindComp.Mind == mindEnt))
Expand All @@ -199,12 +206,12 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen
ClonesWaitingForMind.Remove(mind);
}

if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)
if ((!allowLivingPeople && mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value))
|| mind.UserId == null
|| !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)
|| !CheckBiomassCost(uid, physics, clonePod, cloningCostMultiplier))
return false;

// Special handling for humanoid data related to metempsychosis. This function is needed for Paradox Anomaly code to play nice with reincarnated people
var pref = humanoid.LastProfileLoaded;
if (pref == null
Expand Down Expand Up @@ -250,8 +257,11 @@ public void AttemptCloning(EntityUid cloningPod, CloningPodComponent cloningPodC
{
if (cloningPodComponent.BodyContainer.ContainedEntity is { Valid: true } entity
&& TryComp<PhysicsComponent>(entity, out var physics)
&& physics.Mass > 71)
&& physics.Mass > MinMassContestMass)
{
Timer.Spawn(TimeSpan.FromSeconds(cloningPodComponent.CloningTime * _contests.MassContest(entity, physics, true)), () => EndCloning(cloningPod, cloningPodComponent));
return;
}

Timer.Spawn(TimeSpan.FromSeconds(cloningPodComponent.CloningTime), () => EndCloning(cloningPod, cloningPodComponent));
}
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/CCVar/CCVars.Cloning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,10 @@ public sealed partial class CCVars
/// </summary>
public static readonly CVarDef<bool> CloningPreserveFlavorText =
CVarDef.Create("cloning.preserve_flavor_text", true, CVar.SERVERONLY);

/// <summary>
/// Controls whether or not living people can be cloned.
/// </summary>
public static readonly CVarDef<bool> CloningAllowLivingPeople =
CVarDef.Create("cloning.allow_living_people", true, CVar.SERVERONLY);
}

0 comments on commit 695f476

Please sign in to comment.