Files
OldThink/Content.Server/Body/Systems/RespiratorSystem.cs

396 lines
15 KiB
C#
Raw Normal View History

using Content.Server.Administration.Logs;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
Черри пики 7 (#592) * Remake gasp popup to emote (#27736) * fix * Silence ringtones on admin PDAs (#29801) * Silence ringtones on invisible PDAs * Revert "Silence ringtones on invisible PDAs" This reverts commit afc1041f31eebe82e83630a856a8856b877a9826. * Literally just this * Add an admin announcement for news article publishing * Fix invalid UI hover/click sounds breaking client (#30067) fixes #29561 * Display the administrator's title in ahelp and ahelp relay (#30075) * Adding the admin prefix to the ahelp * Updating the admin prefix * The second update of the admin prefix * Configuration correction * fix * Fix servers ambience sound (#30091) * Fix servers ambience * I'm silly * Clean up * Add pen clicking sound (#30531) * Add pen clicking sound * switch to OnUse and reduce distance a little * Fix exploding pen clicking (#30533) * fix pens * added a bunch more fox noises (#27578) * fuck it we ball * added recommended copyright information * revised copyright license * revised copyright license x2 * finalized the fops # reduced the number of audio clips # adjusted the volume of all fox sounds to be consistent with each other * added new sounds to the overall fox parent mob because we forgot oopsie --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
2024-08-09 02:37:34 +03:00
using Content.Server.Chat.Systems;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.DoAfter;
using Content.Server.Nutrition.Components; // WD
using Content.Server.Popups;
using Content.Shared.ActionBlocker; // WD
using Content.Shared.Alert;
using Content.Shared.Atmos;
using Content.Shared.Body.Components;
using Content.Shared.Damage;
using Content.Shared.Database;
2023-05-25 21:01:07 +03:00
using Content.Shared.DoAfter;
using Content.Shared.Humanoid; // WD
using Content.Shared.IdentityManagement; // WD
using Content.Shared.Interaction; // WD
using Content.Shared.Inventory; // WD
using Content.Shared.Mobs; // WD
using Content.Shared.Mobs.Components; // WD
using Content.Shared.Mobs.Systems;
using Content.Shared.Popups; // WD
using Content.Shared._White.CPR.Events;
using Content.Shared._White.Mood;
using Content.Shared.Changeling; // WD
using JetBrains.Annotations;
using Robust.Server.Audio; // WD
using Robust.Shared.Audio; // WD
// WD removed
using Robust.Shared.Timing;
namespace Content.Server.Body.Systems;
[UsedImplicitly]
public sealed class RespiratorSystem : EntitySystem
{
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
[Dependency] private readonly AtmosphereSystem _atmosSys = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly DamageableSystem _damageableSys = default!;
[Dependency] private readonly LungSystem _lungSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
Черри пики 7 (#592) * Remake gasp popup to emote (#27736) * fix * Silence ringtones on admin PDAs (#29801) * Silence ringtones on invisible PDAs * Revert "Silence ringtones on invisible PDAs" This reverts commit afc1041f31eebe82e83630a856a8856b877a9826. * Literally just this * Add an admin announcement for news article publishing * Fix invalid UI hover/click sounds breaking client (#30067) fixes #29561 * Display the administrator's title in ahelp and ahelp relay (#30075) * Adding the admin prefix to the ahelp * Updating the admin prefix * The second update of the admin prefix * Configuration correction * fix * Fix servers ambience sound (#30091) * Fix servers ambience * I'm silly * Clean up * Add pen clicking sound (#30531) * Add pen clicking sound * switch to OnUse and reduce distance a little * Fix exploding pen clicking (#30533) * fix pens * added a bunch more fox noises (#27578) * fuck it we ball * added recommended copyright information * revised copyright license * revised copyright license x2 * finalized the fops # reduced the number of audio clips # adjusted the volume of all fox sounds to be consistent with each other * added new sounds to the overall fox parent mob because we forgot oopsie --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
2024-08-09 02:37:34 +03:00
[Dependency] private readonly ChatSystem _chat = default!;
2024-01-27 09:34:07 +03:00
[Dependency] private readonly InventorySystem _inventorySystem = default!; // WD
[Dependency] private readonly ActionBlockerSystem _blocker = default!; // WD
[Dependency] private readonly AudioSystem _audio = default!; // WD
[Dependency] private readonly DoAfterSystem _doAfter = default!; // WD
[Dependency] private readonly DamageableSystem _damageable = default!; // WD
Черри пики 7 (#592) * Remake gasp popup to emote (#27736) * fix * Silence ringtones on admin PDAs (#29801) * Silence ringtones on invisible PDAs * Revert "Silence ringtones on invisible PDAs" This reverts commit afc1041f31eebe82e83630a856a8856b877a9826. * Literally just this * Add an admin announcement for news article publishing * Fix invalid UI hover/click sounds breaking client (#30067) fixes #29561 * Display the administrator's title in ahelp and ahelp relay (#30075) * Adding the admin prefix to the ahelp * Updating the admin prefix * The second update of the admin prefix * Configuration correction * fix * Fix servers ambience sound (#30091) * Fix servers ambience * I'm silly * Clean up * Add pen clicking sound (#30531) * Add pen clicking sound * switch to OnUse and reduce distance a little * Fix exploding pen clicking (#30533) * fix pens * added a bunch more fox noises (#27578) * fuck it we ball * added recommended copyright information * revised copyright license * revised copyright license x2 * finalized the fops # reduced the number of audio clips # adjusted the volume of all fox sounds to be consistent with each other * added new sounds to the overall fox parent mob because we forgot oopsie --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
2024-08-09 02:37:34 +03:00
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; // WD
public override void Initialize()
{
base.Initialize();
// We want to process lung reagents before we inhale new reagents.
UpdatesAfter.Add(typeof(MetabolizerSystem));
SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
2024-01-27 09:34:07 +03:00
SubscribeLocalEvent<RespiratorComponent, InteractHandEvent>(OnHandInteract); // WD
SubscribeLocalEvent<RespiratorComponent, CPREndedEvent>(OnCPRDoAfterEnd); // WD
SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
}
private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
}
private void OnUnpaused(Entity<RespiratorComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdate += args.PausedTime;
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<RespiratorComponent, BodyComponent>();
while (query.MoveNext(out var uid, out var respirator, out var body))
{
if (_gameTiming.CurTime < respirator.NextUpdate)
continue;
respirator.NextUpdate += respirator.UpdateInterval;
if (_mobState.IsDead(uid))
continue;
UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator);
if (!_mobState.IsIncapacitated(uid)) // cannot breathe in crit.
{
switch (respirator.Status)
{
case RespiratorStatus.Inhaling:
Inhale(uid, body);
respirator.Status = RespiratorStatus.Exhaling;
break;
case RespiratorStatus.Exhaling:
Exhale(uid, body);
respirator.Status = RespiratorStatus.Inhaling;
break;
}
}
2022-02-06 21:48:15 -07:00
if (respirator.Saturation < respirator.SuffocationThreshold)
{
if (TryComp(uid, out VoidAdaptationComponent? voidAdaptation))
{
voidAdaptation.ChemMultiplier = 0.75f;
2024-03-30 11:33:13 +07:00
StopSuffocation((uid, respirator));
respirator.SuffocationCycles = 0;
continue;
}
Черри пики 7 (#592) * Remake gasp popup to emote (#27736) * fix * Silence ringtones on admin PDAs (#29801) * Silence ringtones on invisible PDAs * Revert "Silence ringtones on invisible PDAs" This reverts commit afc1041f31eebe82e83630a856a8856b877a9826. * Literally just this * Add an admin announcement for news article publishing * Fix invalid UI hover/click sounds breaking client (#30067) fixes #29561 * Display the administrator's title in ahelp and ahelp relay (#30075) * Adding the admin prefix to the ahelp * Updating the admin prefix * The second update of the admin prefix * Configuration correction * fix * Fix servers ambience sound (#30091) * Fix servers ambience * I'm silly * Clean up * Add pen clicking sound (#30531) * Add pen clicking sound * switch to OnUse and reduce distance a little * Fix exploding pen clicking (#30533) * fix pens * added a bunch more fox noises (#27578) * fuck it we ball * added recommended copyright information * revised copyright license * revised copyright license x2 * finalized the fops # reduced the number of audio clips # adjusted the volume of all fox sounds to be consistent with each other * added new sounds to the overall fox parent mob because we forgot oopsie --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
2024-08-09 02:37:34 +03:00
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
{
Черри пики 7 (#592) * Remake gasp popup to emote (#27736) * fix * Silence ringtones on admin PDAs (#29801) * Silence ringtones on invisible PDAs * Revert "Silence ringtones on invisible PDAs" This reverts commit afc1041f31eebe82e83630a856a8856b877a9826. * Literally just this * Add an admin announcement for news article publishing * Fix invalid UI hover/click sounds breaking client (#30067) fixes #29561 * Display the administrator's title in ahelp and ahelp relay (#30075) * Adding the admin prefix to the ahelp * Updating the admin prefix * The second update of the admin prefix * Configuration correction * fix * Fix servers ambience sound (#30091) * Fix servers ambience * I'm silly * Clean up * Add pen clicking sound (#30531) * Add pen clicking sound * switch to OnUse and reduce distance a little * Fix exploding pen clicking (#30533) * fix pens * added a bunch more fox noises (#27578) * fuck it we ball * added recommended copyright information * revised copyright license * revised copyright license x2 * finalized the fops # reduced the number of audio clips # adjusted the volume of all fox sounds to be consistent with each other * added new sounds to the overall fox parent mob because we forgot oopsie --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: Tayrtahn <tayrtahn@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com> Co-authored-by: to4no_fix <156101927+chavonadelal@users.noreply.github.com> Co-authored-by: Winkarst <74284083+Winkarst-cpu@users.noreply.github.com> Co-authored-by: themias <89101928+themias@users.noreply.github.com> Co-authored-by: nao fujiwara <awkwarddryad@gmail.com>
2024-08-09 02:37:34 +03:00
respirator.LastGaspEmoteTime = _gameTiming.CurTime;
_chat.TryEmoteWithChat(uid, respirator.GaspEmote, ignoreActionBlocker: true);
}
TakeSuffocationDamage((uid, respirator));
respirator.SuffocationCycles += 1;
continue;
}
StopSuffocation((uid, respirator));
respirator.SuffocationCycles = 0;
}
}
public void Inhale(EntityUid uid, BodyComponent? body = null)
{
if (!Resolve(uid, ref body, logMissing: false))
return;
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
// Inhale gas
var ev = new InhaleLocationEvent();
RaiseLocalEvent(uid, ref ev, broadcast: false);
ev.Gas ??= _atmosSys.GetContainingMixture(uid, excite: true);
if (ev.Gas is null)
{
return;
}
var actualGas = ev.Gas.RemoveVolume(Atmospherics.BreathVolume);
var lungRatio = 1.0f / organs.Count;
var gas = organs.Count == 1 ? actualGas : actualGas.RemoveRatio(lungRatio);
foreach (var (lung, _) in organs)
{
// Merge doesn't remove gas from the giver.
_atmosSys.Merge(lung.Air, gas);
_lungSystem.GasToReagent(lung.Owner, lung);
}
}
public void Exhale(EntityUid uid, BodyComponent? body = null)
{
if (!Resolve(uid, ref body, logMissing: false))
return;
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(uid, body);
// exhale gas
var ev = new ExhaleLocationEvent();
RaiseLocalEvent(uid, ref ev, broadcast: false);
2022-02-13 11:08:54 +13:00
if (ev.Gas is null)
{
ev.Gas = _atmosSys.GetContainingMixture(uid, excite: true);
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
// but this also means you cannot exhale on some grids.
ev.Gas ??= GasMixture.SpaceGas;
}
var outGas = new GasMixture(ev.Gas.Volume);
foreach (var (lung, _) in organs)
{
_atmosSys.Merge(outGas, lung.Air);
lung.Air.Clear();
if (_solutionContainerSystem.ResolveSolution(lung.Owner, lung.SolutionName, ref lung.Solution))
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
}
_atmosSys.Merge(ev.Gas, outGas);
}
private void TakeSuffocationDamage(Entity<RespiratorComponent> ent)
{
if (ent.Comp.SuffocationCycles == 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
if (ent.Comp.SuffocationCycles >= ent.Comp.SuffocationCycleThreshold)
{
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(ent);
foreach (var (comp, _) in organs)
{
_alertsSystem.ShowAlert(ent, comp.Alert);
Merge remote-tracking branch 'upstream/master' into upstream # Conflicts: # Content.Client/Clothing/ClientClothingSystem.cs # Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs # Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs # Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml # Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs # Content.Server/Administration/Commands/AdminWhoCommand.cs # Content.Server/Bed/Sleep/SleepingSystem.cs # Content.Server/Body/Components/BloodstreamComponent.cs # Content.Server/Body/Components/RespiratorComponent.cs # Content.Server/Body/Systems/InternalsSystem.cs # Content.Server/Body/Systems/RespiratorSystem.cs # Content.Server/Chat/Managers/IChatManager.cs # Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs # Content.Server/DeviceNetwork/Systems/DeviceNetworkSystem.cs # Content.Server/Electrocution/ElectrocutionSystem.cs # Content.Server/Holosign/HolosignProjectorComponent.cs # Content.Server/Holosign/HolosignSystem.cs # Content.Server/Remotes/DoorRemoteSystem.cs # Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs # Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs # Content.Server/Store/Systems/StoreSystem.Ui.cs # Content.Server/VendingMachines/VendingMachineSystem.cs # Content.Server/VoiceMask/VoiceMaskSystem.Equip.cs # Content.Server/VoiceMask/VoiceMaskSystem.cs # Content.Server/VoiceMask/VoiceMaskerComponent.cs # Content.Server/Zombies/ZombieSystem.cs # Content.Shared/Bed/Sleep/SleepEmitSoundComponent.cs # Content.Shared/Cuffs/SharedCuffableSystem.cs # Content.Shared/VoiceMask/SharedVoiceMaskSystem.cs # Resources/Locale/en-US/escape-menu/ui/options-menu.ftl # Resources/Maps/bagel.yml # Resources/Maps/box.yml # Resources/Maps/centcomm.yml # Resources/Maps/cluster.yml # Resources/Maps/europa.yml # Resources/Maps/marathon.yml # Resources/Maps/meta.yml # Resources/Maps/omega.yml # Resources/Maps/origin.yml # Resources/Maps/packed.yml # Resources/Maps/reach.yml # Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml # Resources/Prototypes/Catalog/Fills/Lockers/security.yml # Resources/Prototypes/Catalog/VendingMachines/Inventories/medidrobe.yml # Resources/Prototypes/Entities/Clothing/Hands/colored.yml # Resources/Prototypes/Entities/Clothing/Neck/mantles.yml # Resources/Prototypes/Entities/Clothing/OuterClothing/wintercoats.yml # Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml # Resources/Prototypes/Entities/Objects/Misc/land_mine.yml # Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml # Resources/Prototypes/Entities/Objects/Weapons/Melee/armblade.yml # Resources/Prototypes/Entities/Structures/Decoration/curtains.yml # Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml # Resources/Prototypes/Entities/Structures/Doors/Shutter/shutters.yml # Resources/Prototypes/Entities/Structures/Holographic/projections.yml # Resources/Prototypes/Entities/Structures/Machines/lathe.yml # Resources/Prototypes/Maps/marathon.yml # Resources/Prototypes/Maps/packed.yml # Resources/Prototypes/Recipes/Lathes/security.yml # Resources/Prototypes/Roles/Jobs/Engineering/atmospheric_technician.yml # Resources/Prototypes/Roles/Jobs/Security/detective.yml # Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml # Resources/Prototypes/Roles/Jobs/Security/security_cadet.yml # Resources/Prototypes/Roles/Jobs/Security/security_officer.yml # Resources/Prototypes/Roles/Jobs/Security/warden.yml # Resources/Textures/Clothing/OuterClothing/Armor/lingarmor.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/icon-open.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/icon.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/inhand-left.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/inhand-right.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-left.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-right.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/icon-open.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/icon.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/inhand-left.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/inhand-right.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-left.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-right.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/icon-open.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/icon.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-equipped-OUTERCLOTHING.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/equipped-OUTERCLOTHING-body-slim.png # Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-equipped-OUTERCLOTHING-body-slim.png # Resources/Textures/Clothing/OuterClothing/Hardsuits/cybersun.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/lingspacesuit.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/paramed.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/spatio.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndiecommander.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Hardsuits/syndieelite.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Misc/nunrobe.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Misc/plaguedoctorsuit.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/Suits/atmos_firesuit.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coat.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatatmos.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatbar.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcap.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcargo.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatce.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcentcom.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatchem.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatclown.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcmo.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatengi.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatgen.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coathop.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coathos.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coathydro.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatjani.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmed.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmime.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatminer.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatnomi.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatparamed.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatqm.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrd.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrobo.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsci.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsec.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatviro.rsi/meta.json # Resources/Textures/Clothing/OuterClothing/WinterCoats/coatwarden.rsi/meta.json # Resources/Textures/Clothing/Shoes/Boots/combatboots.rsi/meta.json # Resources/Textures/Clothing/Shoes/Specific/bling.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/atmosf.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/centcomformaldress.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/hosformaldress.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpskirt/operative_s.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/atmos.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/centcomformal.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/hosformal.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/journalist.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/operative.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/psychologist.rsi/meta.json # Resources/Textures/Clothing/Uniforms/Jumpsuit/reporter.rsi/meta.json # Resources/Textures/Interface/Alerts/essence_counter.rsi/essence0.png # Resources/Textures/Interface/Alerts/essence_counter.rsi/essence16.png # Resources/Textures/Objects/Storage/boxes.rsi/meta.json # Resources/Textures/Structures/Doors/Airlocks/Glass/atmospherics.rsi/meta.json # Resources/Textures/Structures/Doors/Airlocks/Standard/atmospherics.rsi/meta.json # Resources/Textures/Structures/Doors/Airlocks/highsec/highsec.rsi/meta.json
2024-03-30 10:36:17 +07:00
RaiseLocalEvent(ent.Owner, new MoodEffectEvent("Suffocating")); // WD edit
}
}
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
}
private void StopSuffocation(Entity<RespiratorComponent> ent)
{
if (ent.Comp.SuffocationCycles >= 2)
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
var organs = _bodySystem.GetBodyOrganComponents<LungComponent>(ent);
foreach (var (comp, _) in organs)
{
_alertsSystem.ClearAlert(ent, comp.Alert);
}
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
}
public void UpdateSaturation(EntityUid uid, float amount,
RespiratorComponent? respirator = null)
{
if (!Resolve(uid, ref respirator, false))
return;
respirator.Saturation += amount;
respirator.Saturation =
Math.Clamp(respirator.Saturation, respirator.MinSaturation, respirator.MaxSaturation);
}
2023-05-25 21:01:07 +03:00
private void OnApplyMetabolicMultiplier(
Entity<RespiratorComponent> ent,
ref ApplyMetabolicMultiplierEvent args)
{
if (args.Apply)
{
ent.Comp.UpdateInterval *= args.Multiplier;
ent.Comp.Saturation *= args.Multiplier;
ent.Comp.MaxSaturation *= args.Multiplier;
ent.Comp.MinSaturation *= args.Multiplier;
return;
}
// This way we don't have to worry about it breaking if the stasis bed component is destroyed
ent.Comp.UpdateInterval /= args.Multiplier;
ent.Comp.Saturation /= args.Multiplier;
ent.Comp.MaxSaturation /= args.Multiplier;
ent.Comp.MinSaturation /= args.Multiplier;
}
2024-01-27 09:34:07 +03:00
// WD start
private void OnHandInteract(EntityUid uid, RespiratorComponent component, InteractHandEvent args)
{
if (!CanCPR(uid, component, args.User))
return;
2024-01-27 09:34:07 +03:00
DoCPR(uid, component, args.User);
args.Handled = true;
}
2024-01-27 09:34:07 +03:00
private bool CanCPR(EntityUid target, RespiratorComponent comp, EntityUid user)
{
if (!_blocker.CanInteract(user, target))
return false;
2024-01-27 09:34:07 +03:00
if (target == user)
return false;
2024-01-27 09:34:07 +03:00
if (comp.CPRPerformedBy != null && comp.CPRPerformedBy != user)
return false;
2024-01-27 09:34:07 +03:00
if (!TryComp<HumanoidAppearanceComponent>(target, out _) && !TryComp<HumanoidAppearanceComponent>(user, out _))
return false;
2024-01-27 09:34:07 +03:00
if (!TryComp(target, out MobStateComponent? targetState))
return false;
2024-01-27 09:34:07 +03:00
if (targetState.CurrentState == MobState.Dead)
{
_popupSystem.PopupEntity(Loc.GetString("cpr-too-late", ("target", Identity.Entity(target, EntityManager))),
target, user);
return false;
}
if (targetState.CurrentState != MobState.Critical)
return false;
2024-01-27 09:34:07 +03:00
if (_inventorySystem.TryGetSlotEntity(user, "mask", out var maskUidUser) &&
EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUidUser, out var blockerUser) &&
blockerUser.Enabled)
{
_popupSystem.PopupEntity(Loc.GetString("cpr-mask-block-user"), user, user);
return false;
}
if (!_inventorySystem.TryGetSlotEntity(target, "mask", out var maskUidTarget) ||
!EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUidTarget, out var blockerTarget) ||
!blockerTarget.Enabled)
return true;
_popupSystem.PopupEntity(
Loc.GetString("cpr-mask-block-target", ("target", Identity.Entity(target, EntityManager))), target, user);
return false;
2024-01-27 09:34:07 +03:00
}
2024-01-27 09:34:07 +03:00
private void DoCPR(EntityUid target, RespiratorComponent comp, EntityUid user)
{
var doAfterEventArgs = new DoAfterArgs(EntityManager, user, 1, new CPREndedEvent(), target, target: target)
2024-01-27 09:34:07 +03:00
{
BreakOnMove = true,
2024-01-27 09:34:07 +03:00
BreakOnDamage = true,
NeedHand = true,
BreakOnHandChange = true
};
if (!_doAfter.TryStartDoAfter(doAfterEventArgs))
{
_popupSystem.PopupEntity(Loc.GetString("cpr-failed"), user, user);
return;
}
2024-01-27 09:34:07 +03:00
comp.CPRPerformedBy = user;
_popupSystem.PopupEntity(Loc.GetString("cpr-started", ("target", Identity.Entity(target, EntityManager)),
2024-01-27 09:34:07 +03:00
("user", Identity.Entity(user, EntityManager))), target, PopupType.Medium);
2024-01-27 09:34:07 +03:00
comp.CPRPlayingStream =
_audio.PlayPvs(comp.CPRSound, target, AudioParams.Default.WithVolume(-3f).WithLoop(true)).Value.Entity;
2024-01-27 09:34:07 +03:00
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(user):entity} начал произовдить СЛР на {ToPrettyString(target):entity}");
}
2024-01-27 09:34:07 +03:00
private void OnCPRDoAfterEnd(EntityUid uid, RespiratorComponent component, CPREndedEvent args)
{
if (args.Handled)
return;
2024-01-27 09:34:07 +03:00
if (args.Cancelled || !TryComp<MobStateComponent>(args.Target, out var targetState) ||
targetState.CurrentState != MobState.Critical)
2024-01-27 09:34:07 +03:00
{
_audio.Stop(component.CPRPlayingStream);
component.CPRPerformedBy = null;
_popupSystem.PopupEntity(Loc.GetString("cpr-failed"), args.User, args.User);
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(args.User):entity} не удалось произвести СЛР на {ToPrettyString(args.Target):entity}");
return;
}
2024-01-27 09:34:07 +03:00
args.Handled = true;
2024-01-27 09:34:07 +03:00
_damageable.TryChangeDamage(uid, -component.Damage * 2, true, false);
_popupSystem.PopupEntity(Loc.GetString("cpr-cycle-ended", ("target", Identity.Entity(uid, EntityManager)),
2024-01-27 09:34:07 +03:00
("user", Identity.Entity(args.User, EntityManager))), uid);
2024-01-27 09:34:07 +03:00
_adminLogger.Add(LogType.Action, LogImpact.High,
$"{ToPrettyString(args.User):entity} произвёл СЛР на {ToPrettyString(args.Target):entity}");
2024-01-27 09:34:07 +03:00
if (args.Target != null && CanCPR(args.Target.Value, component, args.User))
{
2024-01-27 09:34:07 +03:00
args.Repeat = true;
}
2024-01-27 09:34:07 +03:00
else
{
component.CPRPerformedBy = null;
_audio.Stop(component.CPRPlayingStream);
}
2024-01-27 09:34:07 +03:00
RaiseLocalEvent(args.User, new MoodEffectEvent("SavedLife"));
}
2024-01-27 09:34:07 +03:00
//WD end
2022-02-06 21:48:15 -07:00
}
[ByRefEvent]
public record struct InhaleLocationEvent(GasMixture? Gas);
[ByRefEvent]
public record struct ExhaleLocationEvent(GasMixture? Gas);