CatStation/Content.Shared/GameTicking/Rules/ParadoxCloneRuleSystem.cs
Princess Cheeseballs 2c6ffecf62
Move GameTicker to Shared (#45834)
* Scope creep my ass

* why was this shit not pushed????

* gone...

* fix that

* review plus buildd

* asfsafsafsafsafas

* grug

* burber

* I'll fix this later

* shrimply die

* also this

* it's snerf or snuthin

* assaads

* round snend

* aaaa

* fix this shit for real

* actually, don't start GameRules until MapInit now that I think aboot it.

* forgot u

* don't actually need this part nullable

* Deffer comp removal

* one liner

* do that too

* chungus

* Honestly makes more sense here, plus WHY are we doing all that shit on "GameRuleAdded" rather than GameRuleStarted(?)

* deferred removal :V

* aaaaaaaaaaaaaaa

* whhop

* Whoop

* better

* landmine that I placed for myself then forgot about lmao

* cleanup

* FUCKING `!`

* gotovo

* amogus

* please don't check by metadata I beg

* waawsasfdfsasfa

* sfafsasfafsas

* fdsaasffsasfa

* code

* fix

* fasasffasfasfsad

* chungaas

* I may be stupid

* gra

* graaaaaaaaaaaaaaaaa

* comment

* gra

* clearing is not predicted and would require major refactors, so don't cache on client.

* lame shit :P

* last holes

* nukeopsfsafsasafsfafsa

* why  was that shit public bruh

* bubrbgwahrghfaka

* dynamic

* revert change that did nothing lmao
2026-09-16 19:34:19 +00:00

98 lines
4.1 KiB
C#

using Content.Shared.Antag;
using Content.Shared.Cloning;
using Content.Shared.GameTicking.Components;
using Content.Shared.GameTicking.Rules.Components;
using Content.Shared.Gibbing.Components;
using Content.Shared.Medical.SuitSensors;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Content.Shared.Objectives.Systems;
using Robust.Shared.Random;
namespace Content.Shared.GameTicking.Rules;
public sealed partial class ParadoxCloneRuleSystem : GameRuleSystem<ParadoxCloneRuleComponent>
{
[Dependency] private IRobustRandom _random = default!;
[Dependency] private SharedCloningSystem _cloning = default!;
[Dependency] private SharedMindSystem _mind = default!;
[Dependency] private SharedSuitSensorSystem _sensor = default!;
[Dependency] private AliveHumanoidTargetSystem _target = default!;
protected override void Started(Entity<ParadoxCloneRuleComponent, GameRuleComponent> rule, ref GameRuleStartedEvent args)
{
base.Started(rule, ref args);
// check if we got enough potential cloning targets, otherwise cancel the gamerule so that the ghost role does not show up
var allHumans = _target.GetMinds();
if (allHumans.Count == 0)
{
Log.Info("Could not find any alive players to create a paradox clone from! Ending gamerule.");
ForceEndSelf((rule, rule.Comp2));
}
}
// we have to do the spawning here so we can transfer the mind to the correct entity and can assign the objectives correctly
[SubscribeLocalEvent]
private void OnAntagSelectEntity(Entity<ParadoxCloneRuleComponent> ent, ref AntagSelectEntityEvent args)
{
if (ent.Comp.OriginalBody != null) // target was overridden, for example by admin antag control
{
if (Deleted(ent.Comp.OriginalBody.Value) || !_mind.TryGetMind(ent.Comp.OriginalBody.Value, out var originalMindId, out var _))
{
Log.Warning("Could not find mind of target player to paradox clone!");
return;
}
ent.Comp.OriginalMind = originalMindId;
}
else
{
// get possible targets
var allAliveHumanoids = _target.GetMinds();
// we already checked when starting the gamerule, but someone might have died since then.
if (allAliveHumanoids.Count == 0)
{
Log.Warning("Could not find any alive players to create a paradox clone from!");
return;
}
// pick a random player
var randomHumanoidMind = _random.Pick(allAliveHumanoids);
ent.Comp.OriginalMind = randomHumanoidMind;
ent.Comp.OriginalBody = randomHumanoidMind.Comp.OwnedEntity;
}
if (ent.Comp.OriginalBody == null || !_cloning.TryCloning(ent.Comp.OriginalBody.Value, args.Coords, ent.Comp.Settings, out var clone))
{
Log.Error($"Unable to make a paradox clone of entity {ToPrettyString(ent.Comp.OriginalBody)}");
return;
}
var targetComp = EnsureComp<TargetOverrideComponent>(clone.Value);
targetComp.Target = ent.Comp.OriginalMind; // set the kill target
var gibComp = EnsureComp<GibOnRoundEndComponent>(clone.Value);
gibComp.SpawnProto = ent.Comp.GibProto;
gibComp.PreventGibbingObjectives = new() { "ParadoxCloneKillObjective" }; // don't gib them if they killed the original.
// turn their suit sensors off so they don't immediately get noticed
_sensor.SetAllSensors(clone.Value, SuitSensorMode.SensorOff);
args.Entity = clone;
}
[SubscribeLocalEvent]
private void AfterAntagEntitySelected(Entity<ParadoxCloneRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
{
if (ent.Comp.OriginalMind == null)
return;
if (!_mind.TryGetMind(args.EntityUid, out var cloneMindId, out var cloneMindComp))
return;
_mind.CopyObjectives(ent.Comp.OriginalMind.Value, (cloneMindId, cloneMindComp), ent.Comp.ObjectiveWhitelist, ent.Comp.ObjectiveBlacklist);
}
}