Skip to content

Commit

Permalink
add CPR and remove roundstart cloning (#18)
Browse files Browse the repository at this point in the history
* just one more PR

* un-migrate because funny
  • Loading branch information
MilonPL authored Jan 11, 2025
1 parent cd9f73a commit 556343f
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 14 deletions.
6 changes: 6 additions & 0 deletions Content.Client/_Emberfall/Medical/CPR/CPRSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Content.Shared._Emberfall.Medical.CPR.Systems;

namespace Content.Client._Emberfall.Medical.CPR;

// ReSharper disable InconsistentNaming
public sealed class CPRSystem : SharedCPRSystem;
6 changes: 6 additions & 0 deletions Content.Server/_Emberfall/Medical/CPR/CPRSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Content.Shared._Emberfall.Medical.CPR.Systems;

namespace Content.Server._Emberfall.Medical.CPR;

// ReSharper disable InconsistentNaming
public sealed class CPRSystem : SharedCPRSystem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Content.Shared._Emberfall.Medical.CPR.Systems;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Shared._Emberfall.Medical.CPR.Components;

// ReSharper disable InconsistentNaming
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCPRSystem))]
[AutoGenerateComponentState, AutoGenerateComponentPause]
public sealed partial class CPRReceivedComponent : Component
{
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoNetworkedField, AutoPausedField]
public TimeSpan Last;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared._Emberfall.Medical.CPR.Systems;
using Robust.Shared.GameStates;

namespace Content.Shared._Emberfall.Medical.CPR.Components;

[RegisterComponent, NetworkedComponent]
[Access(typeof(SharedCPRSystem))]
public sealed partial class ReceivingCPRComponent : Component;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;

namespace Content.Shared._Emberfall.Medical.CPR.Events;

// ReSharper disable InconsistentNaming
[Serializable, NetSerializable]
public sealed partial class CPRDoAfterEvent : SimpleDoAfterEvent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Content.Shared._Emberfall.Medical.CPR.Events;

// ReSharper disable InconsistentNaming
[ByRefEvent]
public record struct PerformCPRAttemptEvent(EntityUid Target, bool Cancelled = false);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Content.Shared.Inventory;

namespace Content.Shared._Emberfall.Medical.CPR.Events;

// ReSharper disable InconsistentNaming
[ByRefEvent]
public record struct ReceiveCPRAttemptEvent(
EntityUid Performer,
EntityUid Target,
bool Start,
SlotFlags TargetSlots = SlotFlags.MASK,
bool Cancelled = false) : IInventoryRelayEvent;
202 changes: 202 additions & 0 deletions Content.Shared/_Emberfall/Medical/CPR/Systems/SharedCPRSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
using Content.Shared._Emberfall.Medical.CPR.Components;
using Content.Shared._Emberfall.Medical.CPR.Events;
using Content.Shared.Atmos.Rotting;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.DoAfter;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Humanoid;
using Content.Shared.Interaction;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;

namespace Content.Shared._Emberfall.Medical.CPR.Systems;

// ReSharper disable InconsistentNaming
public abstract class SharedCPRSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedPopupSystem _popups = default!;
[Dependency] private readonly SharedRottingSystem _rotting = default!;

// TODO: move this to a component
private readonly ProtoId<DamageTypePrototype> _healType = "Asphyxiation";

private static readonly FixedPoint2 HealAmount = FixedPoint2.New(10);

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

SubscribeLocalEvent<HumanoidAppearanceComponent, InteractHandEvent>(OnInteractHand,
[typeof(InteractionPopupSystem)]);
SubscribeLocalEvent<HumanoidAppearanceComponent, CPRDoAfterEvent>(OnDoAfter);

SubscribeLocalEvent<ReceivingCPRComponent, ReceiveCPRAttemptEvent>(OnReceivingCPRAttempt);
SubscribeLocalEvent<CPRReceivedComponent, ReceiveCPRAttemptEvent>(OnReceivedCPRAttempt);
SubscribeLocalEvent<MobStateComponent, ReceiveCPRAttemptEvent>(OnMobStateCPRAttempt);
}

private void OnInteractHand(Entity<HumanoidAppearanceComponent> ent, ref InteractHandEvent args)
{
if (args.Handled)
return;

args.Handled = StartCPR(args.User, args.Target);
}

private void OnDoAfter(Entity<HumanoidAppearanceComponent> ent, ref CPRDoAfterEvent args)
{
var performer = args.User;

if (args.Target != null)
RemComp<ReceivingCPRComponent>(args.Target.Value);

if (args.Cancelled ||
args.Handled ||
args.Target is not { } target ||
!CanCPRPopup(performer, target, false, out var damage))
return;

args.Handled = true;

if (_net.IsServer)
_rotting.ReduceAccumulator(target, TimeSpan.FromSeconds(7));

if (!TryComp(target, out DamageableComponent? damageable) ||
!damageable.Damage.DamageDict.TryGetValue(_healType, out damage))
return;

var heal = -FixedPoint2.Min(damage, HealAmount);
var healSpecifier = new DamageSpecifier();
healSpecifier.DamageDict.Add(_healType, heal);
_damageable.TryChangeDamage(target, healSpecifier, true);
EnsureComp<CPRReceivedComponent>(target).Last = _timing.CurTime;

if (_net.IsClient)
return;

// TODO RMC14 move this value to a component
var selfPopup = Loc.GetString("cpr-self-perform", ("target", target), ("seconds", 7));
_popups.PopupEntity(selfPopup, target, performer);

var othersPopup = Loc.GetString("cpr-other-perform", ("performer", performer), ("target", target));
var othersFilter = Filter.Pvs(performer).RemoveWhereAttachedEntity(e => e == performer);
_popups.PopupEntity(othersPopup, performer, othersFilter, true, PopupType.Medium);
}

private void OnReceivingCPRAttempt(Entity<ReceivingCPRComponent> ent, ref ReceiveCPRAttemptEvent args)
{
args.Cancelled = true;

if (_net.IsClient)
return;

var popup = Loc.GetString("cpr-already-being-performed", ("target", ent.Owner));
_popups.PopupEntity(popup, ent, args.Performer, PopupType.Medium);
}

private void OnReceivedCPRAttempt(Entity<CPRReceivedComponent> ent, ref ReceiveCPRAttemptEvent args)
{
if (args.Start)
return;

var target = ent.Owner;
var performer = args.Performer;

// TODO move this value to a component
if (ent.Comp.Last > _timing.CurTime - TimeSpan.FromSeconds(7))
{
args.Cancelled = true;

if (_net.IsClient)
return;

var selfPopup = Loc.GetString("cpr-self-perform-fail-received-too-recently", ("target", target));
_popups.PopupEntity(selfPopup, target, performer, PopupType.SmallCaution);

var othersPopup = Loc.GetString("cpr-other-perform-fail", ("performer", performer), ("target", target));
var othersFilter = Filter.Pvs(performer).RemoveWhereAttachedEntity(e => e == performer);
_popups.PopupEntity(othersPopup, performer, othersFilter, true, PopupType.SmallCaution);
}
}

private void OnMobStateCPRAttempt(Entity<MobStateComponent> ent, ref ReceiveCPRAttemptEvent args)
{
if (args.Cancelled)
return;

if (_mobState.IsAlive(ent) || _rotting.IsRotten(ent))
args.Cancelled = true;
}

private bool CanCPRPopup(EntityUid performer, EntityUid target, bool start, out FixedPoint2 damage)
{
damage = default;

if (!HasComp<HumanoidAppearanceComponent>(target) || !HasComp<HumanoidAppearanceComponent>(performer))
return false;

var performAttempt = new PerformCPRAttemptEvent(target);
RaiseLocalEvent(performer, ref performAttempt);

if (performAttempt.Cancelled)
return false;

var receiveAttempt = new ReceiveCPRAttemptEvent(performer, target, start);
RaiseLocalEvent(target, ref receiveAttempt);

if (receiveAttempt.Cancelled)
return false;

if (!_hands.TryGetEmptyHand(performer, out _))
return false;

return true;
}

private bool StartCPR(EntityUid performer, EntityUid target)
{
if (!CanCPRPopup(performer, target, true, out _))
return false;

EnsureComp<ReceivingCPRComponent>(target);

var doAfter = new DoAfterArgs(EntityManager,
performer,
TimeSpan.FromSeconds(4),
new CPRDoAfterEvent(),
performer,
target)
{
BreakOnMove = true,
NeedHand = true,
BlockDuplicate = true,
DuplicateCondition = DuplicateConditions.SameEvent,
};
_doAfter.TryStartDoAfter(doAfter);

if (_net.IsClient)
return true;

var selfPopup = Loc.GetString("cpr-self-start-perform", ("target", target));
_popups.PopupEntity(selfPopup, target, performer);

var othersPopup = Loc.GetString("cpr-other-start-perform", ("performer", performer), ("target", target));
var othersFilter = Filter.Pvs(performer).RemoveWhereAttachedEntity(e => e == performer);
_popups.PopupEntity(othersPopup, performer, othersFilter, true);

return true;
}
}
7 changes: 7 additions & 0 deletions Resources/Locale/en-US/_emberfall/medical/cpr.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cpr-already-being-performed = CPR is already being performed on {$target}!
cpr-self-start-perform = You start performing CPR on {$target}!
cpr-other-start-perform = {$performer} starts performing CPR on {$target}!
cpr-self-perform = You perform CPR on {$target}. Repeat at least every {$seconds} seconds.
cpr-other-perform = {$performer} performs CPR on {$target}.
cpr-self-perform-fail-received-too-recently = You fail to perform CPR on {$target}. Incorrect rhythm. Do it slower.
cpr-other-perform-fail = {$performer} fails to perform CPR on {$target}!
3 changes: 3 additions & 0 deletions Resources/Migrations/emberfallMigration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ WeaponRifleLecter: WeaponRifleLecterEmberfall
WeaponRifleM90GrenadeLauncher: WeaponRifleM90
WeaponSubMachineGunVector: WeaponSubMachineGunVectorEmberfall
GunSafeLecter: GunSafeLightRifleLecter

# 01-06-2025
ComputerCloningConsole: null
6 changes: 3 additions & 3 deletions Resources/Prototypes/Entities/Structures/Machines/lathe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@
- ThermomachineFreezerMachineCircuitBoard
- HellfireFreezerMachineCircuitBoard
- PortableScrubberMachineCircuitBoard
- CloningPodMachineCircuitboard
- MedicalScannerMachineCircuitboard
# - CloningPodMachineCircuitboard
# - MedicalScannerMachineCircuitboard
- CryoPodMachineCircuitboard
- VaccinatorMachineCircuitboard
- DiagnoserMachineCircuitboard
Expand All @@ -509,7 +509,7 @@
- RadarConsoleCircuitboard
- TechDiskComputerCircuitboard
- DawInstrumentMachineCircuitboard
- CloningConsoleComputerCircuitboard
# - CloningConsoleComputerCircuitboard
- StasisBedMachineCircuitboard
- OreProcessorIndustrialMachineCircuitboard
- CargoTelepadMachineCircuitboard
Expand Down
6 changes: 3 additions & 3 deletions Resources/Prototypes/Procedural/salvage_rewards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
CratePartsT3T4: 0.5
TechnologyDiskRare: 0.5
# cloning boards
CloningPodMachineCircuitboard: 0.5
MedicalScannerMachineCircuitboard: 0.5
CloningConsoleComputerCircuitboard: 0.5
# CloningPodMachineCircuitboard: 0.5
# MedicalScannerMachineCircuitboard: 0.5
# CloningConsoleComputerCircuitboard: 0.5
BiomassReclaimerMachineCircuitboard: 0.5
# basic weapons
Machete: 0.25
Expand Down
16 changes: 8 additions & 8 deletions Resources/Prototypes/Recipes/Lathes/electronics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@
id: SignalTimerElectronics
result: SignalTimerElectronics

- type: latheRecipe
parent: BaseGoldCircuitboardRecipe
id: CloningPodMachineCircuitboard
result: CloningPodMachineCircuitboard
#- type: latheRecipe # Emberfall
# parent: BaseGoldCircuitboardRecipe
# id: CloningPodMachineCircuitboard
# result: CloningPodMachineCircuitboard

- type: latheRecipe
parent: BaseGoldCircuitboardRecipe
Expand Down Expand Up @@ -429,10 +429,10 @@
id: SolarTrackerElectronics
result: SolarTrackerElectronics

- type: latheRecipe
parent: BaseCircuitboardRecipe
id: CloningConsoleComputerCircuitboard
result: CloningConsoleComputerCircuitboard
#- type: latheRecipe # Emberfall
# parent: BaseCircuitboardRecipe
# id: CloningConsoleComputerCircuitboard
# result: CloningConsoleComputerCircuitboard

- type: latheRecipe
parent: BaseCircuitboardRecipe
Expand Down

0 comments on commit 556343f

Please sign in to comment.