Skip to content

Commit

Permalink
Merge pull request #2800 from Spielern/port-ipc
Browse files Browse the repository at this point in the history
Ports IPCs from Goob/EE
  • Loading branch information
deltanedas authored Feb 3, 2025
2 parents fe4c23c + 97a57c4 commit 822fa43
Show file tree
Hide file tree
Showing 183 changed files with 7,558 additions and 29 deletions.
4 changes: 3 additions & 1 deletion Content.IntegrationTests/Tests/GameRules/NukeOpsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Map.Components;
using Content.Shared._EE.Silicon.Components; // Goobstation

namespace Content.IntegrationTests.Tests.GameRules;

Expand Down Expand Up @@ -229,7 +230,8 @@ void CheckDummy(int i)
for (var tick = 0; tick < totalTicks; tick += increment)
{
await pair.RunTicksSync(increment);
Assert.That(resp.SuffocationCycles, Is.LessThanOrEqualTo(resp.SuffocationCycleThreshold));
if (!entMan.HasComponent<SiliconComponent>(player)) // Goobstation
Assert.That(resp.SuffocationCycles, Is.LessThanOrEqualTo(resp.SuffocationCycleThreshold));
Assert.That(damage.TotalDamage, Is.EqualTo(FixedPoint2.Zero));
}

Expand Down
9 changes: 8 additions & 1 deletion Content.Server/Administration/Commands/SetOutfitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using Robust.Shared.Console;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Content.Server._EE.Silicon.IPC; // Goobstation
using Content.Shared.Radio.Components; // Goobstation

namespace Content.Server.Administration.Commands
{
Expand Down Expand Up @@ -163,7 +165,12 @@ public static bool SetOutfit(EntityUid target, string gear, IEntityManager entit
var stationSpawning = entityManager.System<SharedStationSpawningSystem>();
stationSpawning.EquipRoleLoadout(target, roleLoadout, jobProto);
}


if (entityManager.HasComponent<EncryptionKeyHolderComponent>(target))
{
var encryption = new InternalEncryptionKeySpawner();
encryption.TryInsertEncryptionKey(target, startingGear, entityManager);
}
return true;
}
}
Expand Down
4 changes: 3 additions & 1 deletion Content.Server/Bed/BedSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Content.Shared.Power;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Shared._EE.Silicon.Components;

namespace Content.Server.Bed
{
Expand Down Expand Up @@ -70,7 +71,8 @@ public override void Update(float frameTime)

foreach (var healedEntity in strapComponent.BuckledEntities)
{
if (_mobStateSystem.IsDead(healedEntity))
if (_mobStateSystem.IsDead(healedEntity)
|| HasComp<SiliconComponent>(healedEntity)) // Goobstation
continue;

var damage = bedComponent.Damage;
Expand Down
6 changes: 5 additions & 1 deletion Content.Server/Chat/SuicideSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Content.Shared.Popups;
using Content.Shared.Tag;
using Robust.Shared.Player;
using Content.Shared._EE.Silicon.Components;

namespace Content.Server.Chat;

Expand Down Expand Up @@ -164,7 +165,10 @@ private void OnDamageableSuicide(Entity<DamageableComponent> victim, ref Suicide
return;
}

args.DamageType ??= "Bloodloss";
if (HasComp<SiliconComponent>(victim)) // Goobstation
args.DamageType ??= "Shock";
else
args.DamageType ??= "Bloodloss";
_suicide.ApplyLethalDamage(victim, args.DamageType);
args.Handled = true;
}
Expand Down
4 changes: 4 additions & 0 deletions Content.Server/Cloning/CloningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Content.Server.Materials;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Shared._EE.Silicon.Components; // Goobstation
using Content.Server.Psionics; // DeltaV
using Content.Server.Traits.Assorted; // DeltaV
using Content.Shared.Atmos;
Expand Down Expand Up @@ -171,6 +172,9 @@ 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

if (HasComp<SiliconComponent>(bodyToClone))
return false; // Goobstation: Don't clone IPCs.

// Begin Nyano-code: allow paradox anomalies to be cloned.
var pref = humanoid.LastProfileLoaded;

Expand Down
7 changes: 4 additions & 3 deletions Content.Server/Electrocution/ElectrocutionSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
[ValidatePrototypeId<DamageTypePrototype>]
private const string DamageType = "Shock";

// Multiply and shift the log scale for shock damage.
// Yes, this is absurdly small for a reason.
public const float ElectrifiedDamagePerWatt = 0.0015f; // Goobstation - This information is allowed to be public, and was needed in BatteryElectrocuteChargeSystem.cs
private const float RecursiveDamageMultiplier = 0.75f;
private const float RecursiveTimeMultiplier = 0.8f;

Expand Down Expand Up @@ -300,7 +301,7 @@ public override bool TryDoElectrocution(
|| !DoCommonElectrocution(uid, sourceUid, shockDamage, time, refresh, siemensCoefficient, statusEffects))
return false;

RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient), true);
RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient, shockDamage), true); // Goobstation
return true;
}

Expand Down Expand Up @@ -350,7 +351,7 @@ private bool TryDoElectrocutionPowered(
electrocutionComponent.Electrocuting = uid;
electrocutionComponent.Source = sourceUid;

RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient), true);
RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient, shockDamage), true); // Goobstation

return true;
}
Expand Down
6 changes: 6 additions & 0 deletions Content.Server/Mobs/DeathgaspComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ public sealed partial class DeathgaspComponent : Component
/// </summary>
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EmotePrototype>))]
public string Prototype = "DefaultDeathgasp";

/// <summary>
/// Goobstation: Makes sure that the deathgasp is only displayed if the entity went critical before dying
/// </summary>
[DataField]
public bool NeedsCritical = true;
}
4 changes: 3 additions & 1 deletion Content.Server/Mobs/DeathgaspSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public override void Initialize()
private void OnMobStateChanged(EntityUid uid, DeathgaspComponent component, MobStateChangedEvent args)
{
// don't deathgasp if they arent going straight from crit to dead
if (args.NewMobState != MobState.Dead || args.OldMobState != MobState.Critical)
if (component.NeedsCritical // Goobstation
&& args.OldMobState != MobState.Critical
|| args.NewMobState != MobState.Dead)
return;

Deathgasp(uid, component);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ namespace Content.Server.Objectives.Components;
[RegisterComponent, Access(typeof(KillPersonConditionSystem))]
public sealed partial class PickRandomPersonComponent : Component
{
[DataField]
public bool NeedsOrganic; // Goobstation: Only pick non-silicon players.
}
4 changes: 2 additions & 2 deletions Content.Server/PowerCell/PowerCellSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ private void OnCellEmpAttempt(EntityUid uid, PowerCellComponent component, EmpAt

private void OnCellSlotExamined(EntityUid uid, PowerCellSlotComponent component, ExaminedEvent args)
{
TryGetBatteryFromSlot(uid, out var battery);
OnBatteryExamined(uid, battery, args);
TryGetBatteryFromSlot(uid, out var batteryEnt, out var battery); // Goobstation
OnBatteryExamined(batteryEnt.GetValueOrDefault(uid), battery, args); // Goobstation
}

private void OnBatteryExamined(EntityUid uid, BatteryComponent? component, ExaminedEvent args)
Expand Down
4 changes: 3 additions & 1 deletion Content.Server/Station/Systems/StationSpawningSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
using Content.Server._EE.Silicon.IPC; // Goobstation

namespace Content.Server.Station.Systems;

Expand All @@ -50,7 +51,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
[Dependency] private readonly PdaSystem _pdaSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;

[Dependency] private readonly InternalEncryptionKeySpawner _internalEncryption = default!; // Goobstation
private bool _randomizeCharacters;

/// <inheritdoc/>
Expand Down Expand Up @@ -178,6 +179,7 @@ public EntityUid SpawnPlayerMob(
{
var startingGear = _prototypeManager.Index<StartingGearPrototype>(prototype.StartingGear);
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
_internalEncryption.TryInsertEncryptionKey(entity.Value, startingGear, EntityManager); // Goobstation
}

var gearEquippedEv = new StartingGearEquippedEvent(entity.Value);
Expand Down
31 changes: 31 additions & 0 deletions Content.Server/_EE/Power/Components/BatteryDrinkerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Content.Server._EE.Power.Components;

[RegisterComponent]
public sealed partial class BatteryDrinkerComponent : Component
{
/// <summary>
/// Is this drinker allowed to drink batteries not tagged as <see cref="BatteryDrinkSource"/>?
/// </summary>
[DataField]
public bool DrinkAll;

/// <summary>
/// How long it takes to drink from a battery, in seconds.
/// Is multiplied by the source.
/// </summary>
[DataField]
public float DrinkSpeed = 1.5f;

/// <summary>
/// The multiplier for the amount of power to attempt to drink.
/// Default amount is 1000
/// </summary>
[DataField]
public float DrinkMultiplier = 5f;

/// <summary>
/// The multiplier for how long it takes to drink a non-source battery, if <see cref="DrinkAll"/> is true.
/// </summary>
[DataField]
public float DrinkAllMultiplier = 2.5f;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Numerics;

namespace Content.Server._EE.Power.Components;

[RegisterComponent]
public sealed partial class RandomBatteryChargeComponent : Component
{
/// <summary>
/// The minimum and maximum max charge the battery can have.
/// </summary>
[DataField]
public Vector2 BatteryMaxMinMax = new(0.85f, 1.15f);

/// <summary>
/// The minimum and maximum current charge the battery can have.
/// </summary>
[DataField]
public Vector2 BatteryChargeMinMax = new(1f, 1f);

/// <summary>
/// False if the randomized charge of the battery should be a multiple of the preexisting current charge of the battery.
/// True if the randomized charge of the battery should be a multiple of the max charge of the battery post max charge randomization.
/// </summary>
[DataField]
public bool BasedOnMaxCharge = true;
}
143 changes: 143 additions & 0 deletions Content.Server/_EE/Power/Systems/BatteryDrinkerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
using System.Linq;
using Content.Server.Power.Components;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.DoAfter;
using Content.Shared.PowerCell.Components;
using Content.Shared._EE.Silicon;
using Content.Shared.Verbs;
using Robust.Shared.Utility;
using Content.Server._EE.Silicon.Charge;
using Content.Server.Power.EntitySystems;
using Content.Server.Popups;
using Content.Server.PowerCell;
using Content.Shared.Popups;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Content.Server._EE.Power.Components;
using Content.Server._EE.Silicon;

namespace Content.Server._EE.Power;

public sealed class BatteryDrinkerSystem : EntitySystem
{
[Dependency] private readonly ItemSlotsSystem _slots = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly SiliconChargeSystem _silicon = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly PowerCellSystem _powerCell = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<BatteryComponent, GetVerbsEvent<AlternativeVerb>>(AddAltVerb);

SubscribeLocalEvent<BatteryDrinkerComponent, BatteryDrinkerDoAfterEvent>(OnDoAfter);
}

private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;

if (!TryComp<BatteryDrinkerComponent>(args.User, out var drinkerComp) ||
!TestDrinkableBattery(uid, drinkerComp) ||
!_silicon.TryGetSiliconBattery(args.User, out var drinkerBattery))
return;

AlternativeVerb verb = new()
{
Act = () => DrinkBattery(uid, args.User, drinkerComp),
Text = Loc.GetString("battery-drinker-verb-drink"),
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
};

args.Verbs.Add(verb);
}

private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drinkerComp)
{
if (!drinkerComp.DrinkAll && !HasComp<BatteryDrinkerSourceComponent>(target))
return false;

return true;
}

private void DrinkBattery(EntityUid target, EntityUid user, BatteryDrinkerComponent drinkerComp)
{
var doAfterTime = drinkerComp.DrinkSpeed;

if (TryComp<BatteryDrinkerSourceComponent>(target, out var sourceComp))
doAfterTime *= sourceComp.DrinkSpeedMulti;
else
doAfterTime *= drinkerComp.DrinkAllMultiplier;

var args = new DoAfterArgs(EntityManager, user, doAfterTime, new BatteryDrinkerDoAfterEvent(), user, target) // TODO: Make this doafter loop, once we merge Upstream.
{
BreakOnDamage = true,
BreakOnMove = true,
Broadcast = false,
DistanceThreshold = 1.35f,
RequireCanInteract = true,
CancelDuplicate = false
};

_doAfter.TryStartDoAfter(args);
}

private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAfterEvent args)
{
if (args.Cancelled || args.Target == null)
return;

var source = args.Target.Value;
var drinker = uid;
var sourceBattery = Comp<BatteryComponent>(source);

_silicon.TryGetSiliconBattery(drinker, out var drinkerBatteryComponent);

if (!TryComp(uid, out PowerCellSlotComponent? batterySlot))
return;

var container = _container.GetContainer(uid, batterySlot.CellSlotId);
var drinkerBattery = container.ContainedEntities.First();

TryComp<BatteryDrinkerSourceComponent>(source, out var sourceComp);

DebugTools.AssertNotNull(drinkerBattery);

if (drinkerBattery == null)
return;

var amountToDrink = drinkerComp.DrinkMultiplier * 1000;

amountToDrink = MathF.Min(amountToDrink, sourceBattery.CurrentCharge);
amountToDrink = MathF.Min(amountToDrink, drinkerBatteryComponent!.MaxCharge - drinkerBatteryComponent.CurrentCharge);

if (sourceComp != null && sourceComp.MaxAmount > 0)
amountToDrink = MathF.Min(amountToDrink, (float) sourceComp.MaxAmount);

if (amountToDrink <= 0)
{
_popup.PopupEntity(Loc.GetString("battery-drinker-empty", ("target", source)), drinker, drinker);
return;
}

if (_battery.TryUseCharge(source, amountToDrink))
_battery.SetCharge(drinkerBattery, drinkerBatteryComponent.CurrentCharge + amountToDrink, drinkerBatteryComponent);
else
{
_battery.SetCharge(drinkerBattery, sourceBattery.CurrentCharge + drinkerBatteryComponent.CurrentCharge, drinkerBatteryComponent);
_battery.SetCharge(source, 0);
}

if (sourceComp != null && sourceComp.DrinkSound != null){
_popup.PopupEntity(Loc.GetString("ipc-recharge-tip"), drinker, drinker, PopupType.SmallCaution);
_audio.PlayPvs(sourceComp.DrinkSound, source);
Spawn("EffectSparks", Transform(source).Coordinates);
}
}
}
Loading

0 comments on commit 822fa43

Please sign in to comment.