mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-17 13:37:47 +03:00
<!-- This is a semi-strict format, you can add/remove sections as needed but the order/format should be kept the same Remove these comments before submitting --> # Description <!-- Explain this PR in as much detail as applicable Some example prompts to consider: How might this affect the game? The codebase? What might be some alternatives to this? How/Who does this benefit/hurt [the game/codebase]? --> Check the changelog for the full list. --- # Changelog <!-- You can add an author after the `🆑` to change the name that appears in the changelog (ex: `🆑 Death`) Leaving it blank will default to your GitHub display name This includes all available types for the changelog --> 🆑 - add: Added Holopads (unmapped) - add: Intellicards are now useful for removing/adding a Station AI's brain. - add: Added the Communications Console to Station AI actions. - add: AI now has a warp point. - add: Added more things for the AI to press. - add: More AI laws have been added. - fix: Fixed the mail system - fix: Fixed AI actions - fix: Fixed invalid spawns for station AI breaking and ruining your ability to play it. - fix: The Station AI's name will now properly send in "arrived to the station" announcements. - fix: Changed the CPR sound to simply not loop until fixed. - fix: Fixed unlocalized messages being sent for the random sentience event. --------- Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: Zachary Higgs <compgeek223@gmail.com> Co-authored-by: MendaxxDev <153332064+MendaxxDev@users.noreply.github.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> (cherry picked from commit 3e8a7d9b00e19e160321eb81d69a884189dfa4e6)
125 lines
5.0 KiB
C#
125 lines
5.0 KiB
C#
using Content.Server.Atmos.Rotting;
|
|
using Content.Server.DoAfter;
|
|
using Content.Server.Nutrition.EntitySystems;
|
|
using Content.Server.Popups;
|
|
using Content.Shared.Atmos.Rotting;
|
|
using Content.Shared.Damage;
|
|
using Content.Shared.DoAfter;
|
|
using Content.Shared.Inventory;
|
|
using Content.Shared.Medical;
|
|
using Content.Shared.Mobs;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.Mobs.Systems;
|
|
using Content.Shared.Verbs;
|
|
using Robust.Server.Audio;
|
|
using Robust.Shared.Audio;
|
|
using Robust.Shared.Random;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Server.Medical.CPR;
|
|
|
|
public sealed class CPRSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
|
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
|
[Dependency] private readonly FoodSystem _foodSystem = default!;
|
|
[Dependency] private readonly DamageableSystem _damageable = default!;
|
|
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
|
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
|
[Dependency] private readonly RottingSystem _rottingSystem = default!;
|
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
|
[Dependency] private readonly AudioSystem _audio = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
SubscribeLocalEvent<CPRTrainingComponent, GetVerbsEvent<InnateVerb>>(AddCPRVerb);
|
|
SubscribeLocalEvent<CPRTrainingComponent, CPRDoAfterEvent>(OnCPRDoAfter);
|
|
}
|
|
|
|
private void AddCPRVerb(Entity<CPRTrainingComponent> performer, ref GetVerbsEvent<InnateVerb> args)
|
|
{
|
|
if (!args.CanInteract || !args.CanAccess || !TryComp<MobStateComponent>(args.Target, out var targetState)
|
|
|| targetState.CurrentState == MobState.Alive)
|
|
return;
|
|
|
|
var target = args.Target;
|
|
InnateVerb verb = new()
|
|
{
|
|
Act = () => { StartCPR(performer, target); },
|
|
Text = Loc.GetString("cpr-verb"),
|
|
Icon = new SpriteSpecifier.Rsi(new("Interface/Alerts/human_alive.rsi"), "health4"),
|
|
Priority = 2
|
|
};
|
|
|
|
args.Verbs.Add(verb);
|
|
}
|
|
|
|
private void StartCPR(Entity<CPRTrainingComponent> performer, EntityUid target)
|
|
{
|
|
if (HasComp<RottingComponent>(target))
|
|
{
|
|
_popupSystem.PopupEntity(Loc.GetString("cpr-target-rotting", ("entity", target)), performer, performer);
|
|
return;
|
|
}
|
|
|
|
if (_inventory.TryGetSlotEntity(target, "outerClothing", out var outer))
|
|
{
|
|
_popupSystem.PopupEntity(Loc.GetString("cpr-must-remove", ("clothing", outer)), performer, performer);
|
|
return;
|
|
}
|
|
|
|
if (_foodSystem.IsMouthBlocked(performer, performer) || _foodSystem.IsMouthBlocked(target, performer))
|
|
return;
|
|
|
|
_popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person", ("target", target)), target, performer);
|
|
_popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person-patient", ("user", performer)), target, target);
|
|
|
|
var doAfterArgs = new DoAfterArgs(
|
|
EntityManager, performer, performer.Comp.DoAfterDuration, new CPRDoAfterEvent(), performer, target,
|
|
performer)
|
|
{
|
|
BreakOnMove = true,
|
|
NeedHand = true,
|
|
BlockDuplicate = true
|
|
};
|
|
|
|
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
|
|
|
var playingStream = _audio.PlayPvs(performer.Comp.CPRSound, performer, AudioParams.Default);
|
|
if (!playingStream.HasValue)
|
|
return;
|
|
|
|
performer.Comp.CPRPlayingStream = playingStream.Value.Entity;
|
|
}
|
|
|
|
private void OnCPRDoAfter(Entity<CPRTrainingComponent> performer, ref CPRDoAfterEvent args)
|
|
{
|
|
if (args.Cancelled || args.Handled || !args.Target.HasValue)
|
|
{
|
|
performer.Comp.CPRPlayingStream = _audio.Stop(performer.Comp.CPRPlayingStream);
|
|
return;
|
|
}
|
|
|
|
if (!performer.Comp.CPRHealing.Empty)
|
|
_damageable.TryChangeDamage(args.Target, performer.Comp.CPRHealing, true, origin: performer);
|
|
|
|
if (performer.Comp.RotReductionMultiplier > 0)
|
|
_rottingSystem.ReduceAccumulator(
|
|
(EntityUid)args.Target, performer.Comp.DoAfterDuration * performer.Comp.RotReductionMultiplier);
|
|
|
|
if (_robustRandom.Prob(performer.Comp.ResuscitationChance)
|
|
&& _mobThreshold.TryGetThresholdForState((EntityUid)args.Target, MobState.Dead, out var threshold)
|
|
&& TryComp<DamageableComponent>(args.Target, out var damageableComponent)
|
|
&& TryComp<MobStateComponent>(args.Target, out var state)
|
|
&& damageableComponent.TotalDamage < threshold)
|
|
_mobStateSystem.ChangeMobState(args.Target.Value, MobState.Critical, state, performer);
|
|
|
|
var isAlive = _mobStateSystem.IsAlive(args.Target.Value);
|
|
args.Repeat = !isAlive;
|
|
if (isAlive)
|
|
performer.Comp.CPRPlayingStream = _audio.Stop(performer.Comp.CPRPlayingStream);
|
|
}
|
|
}
|