Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into submarine
Browse files Browse the repository at this point in the history
  • Loading branch information
rosieposieeee committed Feb 18, 2024
2 parents 2af1135 + c089507 commit 9f233fb
Show file tree
Hide file tree
Showing 44 changed files with 2,039 additions and 1,988 deletions.
5 changes: 4 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/Content.*/ @DebugOk
/Content.*/SimpleStation14/ @DEATHB4DEFEAT

/Resources/ @DebugOk @Colin-Tel
/Resources/ @DebugOk
/Resources/ConfigPresets/ @DebugOk
/Resources/*.yml @DebugOk
/Resources/*/SimpleStation14/ @DEATHB4DEFEAT
Expand All @@ -14,3 +14,6 @@
/Resources/Prototypes/Maps/ @IamVelcroboy

/Tools/ @DebugOk

/* @DebugOk # Standalone files in root, shouldn't apply to subdirectories
/.github/ @DebugOk # Workflows, codeowners, templates, etc
19 changes: 2 additions & 17 deletions Content.Client/Nyanotrasen/Overlays/DogVisionSystem.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using Content.Shared.Abilities;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Player;

namespace Content.Client.Nyanotrasen.Overlays;

public sealed partial class DogVisionSystem : EntitySystem
{
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IOverlayManager _overlayMan = default!;

private DogVisionOverlay _overlay = default!;
Expand All @@ -19,28 +16,16 @@ public override void Initialize()
SubscribeLocalEvent<DogVisionComponent, ComponentInit>(OnDogVisionInit);
SubscribeLocalEvent<DogVisionComponent, ComponentShutdown>(OnDogVisionShutdown);

_player.LocalPlayerAttached += OnAttachedChanged;
_player.LocalPlayerDetached += OnAttachedChanged;

_overlay = new();
}

private void OnAttachedChanged(EntityUid uid)
{
_overlayMan.AddOverlay(_overlay);
}

private void OnDogVisionInit(EntityUid uid, DogVisionComponent component, ComponentInit args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
_overlayMan.AddOverlay(_overlay);
_overlayMan.AddOverlay(_overlay);
}

private void OnDogVisionShutdown(EntityUid uid, DogVisionComponent component, ComponentShutdown args)
{
if (_player.LocalPlayer?.ControlledEntity == uid)
{
_overlayMan.RemoveOverlay(_overlay);
}
_overlayMan.RemoveOverlay(_overlay);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ protected override void UpdateState(BoundUserInterfaceState state)

break;
case SalvageOffering salvage:
option.Title = Loc.GetString($"salvage-map-proto-{salvage.SalvageMap.ID}");
option.Title = Loc.GetString($"salvage-map-size-{salvage.SalvageMap.Size}"); // DeltaV - Replace map names with sizes
break;
default:
throw new ArgumentOutOfRangeException();
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
6 changes: 3 additions & 3 deletions Content.Server/Cloning/CloningConsoleSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public sealed class CloningConsoleSystem : EntitySystem
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly PowerReceiverSystem _powerReceiverSystem = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;

public override void Initialize()
{
base.Initialize();
Expand Down Expand Up @@ -169,8 +169,8 @@ public void TryClone(EntityUid uid, EntityUid cloningPodUid, EntityUid scannerUi

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)}.");
}

Expand Down
111 changes: 105 additions & 6 deletions Content.Server/Cloning/CloningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,22 @@
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
{
Expand Down Expand Up @@ -62,6 +76,8 @@ public sealed class CloningSystem : EntitySystem
[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;
Expand Down Expand Up @@ -136,8 +152,8 @@ private void OnExamined(EntityUid uid, CloningPodComponent component, ExaminedEv

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;
Expand Down Expand Up @@ -167,6 +183,12 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen
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;

Expand Down Expand Up @@ -222,11 +244,11 @@ public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Entity<MindComponen
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);
Expand Down Expand Up @@ -326,7 +348,6 @@ private void EndFailedCloning(EntityUid uid, CloningPodComponent clonePod)
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);
Expand Down Expand Up @@ -354,6 +375,84 @@ private void EndFailedCloning(EntityUid uid, CloningPodComponent clonePod)
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();
Expand Down
3 changes: 3 additions & 0 deletions Content.Server/Medical/Components/MedicalScannerComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ public sealed partial class MedicalScannerComponent : SharedMedicalScannerCompon

[DataField, ViewVariables(VVAccess.ReadWrite)]
public float CloningFailChanceMultiplier = 1f;

// Nyano, needed for Metem Machine.
public float MetemKarmaBonus = 0.25f;
}
}
12 changes: 12 additions & 0 deletions Content.Server/Nyanotrasen/Cloning/MetempsychosisKarmaComponent.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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";
}
}
Loading

0 comments on commit 9f233fb

Please sign in to comment.