Реворк Интердайн дефибриллятора. (#3249)
Co-authored-by: worstplayerever <worstplayerever912@gmail.com> Co-authored-by: banumbas <banumbas1@gmail.com> Co-authored-by: KaiserMaus <kaiser.ratte@gmail.com> Co-authored-by: Vigers Ray <60344369+VigersRay@users.noreply.github.com>
This commit is contained in:
parent
f122d9bdd4
commit
3e4bbda502
17 changed files with 284 additions and 10 deletions
|
|
@ -23,6 +23,12 @@ using Content.Shared.Timing;
|
|||
using Content.Shared.Toggleable;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
// Sunrise-Start
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
// Sunrise-End
|
||||
|
||||
namespace Content.Server.Medical;
|
||||
|
||||
|
|
@ -46,6 +52,7 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; // Sunrise-Edit
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
|
|
@ -70,7 +77,7 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
if (args.Target is not { } target)
|
||||
return;
|
||||
|
||||
if (!CanZap(uid, target, args.User, component))
|
||||
if (!CanZap(uid, target, args.User, component, component.AllowUseOnAlive)) // Sunrise-Edit
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
|
@ -111,6 +118,13 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
if (!_powerCell.HasActivatableCharge(uid, user: user))
|
||||
return false;
|
||||
|
||||
// Sunrise-Start
|
||||
var canZapEvent = new SunriseCanZapEvent(uid, target, user);
|
||||
RaiseLocalEvent(uid, ref canZapEvent);
|
||||
if (canZapEvent.Cancelled)
|
||||
return false;
|
||||
// Sunrise-End
|
||||
|
||||
if (!targetCanBeAlive && _mobState.IsAlive(target, mobState))
|
||||
return false;
|
||||
|
||||
|
|
@ -135,7 +149,7 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
if (!CanZap(uid, target, user, component))
|
||||
if (!CanZap(uid, target, user, component, component.AllowUseOnAlive)) // Sunrise-Edit
|
||||
return false;
|
||||
|
||||
_audio.PlayPvs(component.ChargeSound, uid);
|
||||
|
|
@ -164,7 +178,7 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
target = selfEvent.DefibTarget;
|
||||
|
||||
// Ensure thet new target is still valid.
|
||||
if (selfEvent.Cancelled || !CanZap(uid, target, user, component, true))
|
||||
if (selfEvent.Cancelled || !CanZap(uid, target, user, component, component.AllowUseOnAlive)) // Sunrise-Edit
|
||||
return;
|
||||
|
||||
var targetEvent = new TargetBeforeDefibrillatorZapsEvent(user, uid, target);
|
||||
|
|
@ -172,7 +186,7 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
|
||||
target = targetEvent.DefibTarget;
|
||||
|
||||
if (targetEvent.Cancelled || !CanZap(uid, target, user, component, true))
|
||||
if (targetEvent.Cancelled || !CanZap(uid, target, user, component, component.AllowUseOnAlive)) // Sunrise-Edit
|
||||
return;
|
||||
|
||||
if (!TryComp<MobStateComponent>(target, out var mob) ||
|
||||
|
|
@ -229,6 +243,18 @@ public sealed class DefibrillatorSystem : EntitySystem
|
|||
}
|
||||
}
|
||||
|
||||
// Sunrise-Start
|
||||
// Inject reagents if any are specified
|
||||
if (component.Reagents.Count > 0 && TryComp<BloodstreamComponent>(target, out var bloodstream))
|
||||
{
|
||||
if (_solutionContainer.TryGetSolution(target, bloodstream.ChemicalSolutionName, out var solution))
|
||||
{
|
||||
foreach (var (reagent, amount) in component.Reagents)
|
||||
_solutionContainer.TryAddReagent(solution.Value, reagent, FixedPoint2.New(amount), out _);
|
||||
}
|
||||
}
|
||||
// Sunrise-End
|
||||
|
||||
var sound = dead || session == null
|
||||
? component.FailureSound
|
||||
: component.SuccessSound;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
using Content.Server.Popups;
|
||||
using Content.Shared._Sunrise.Biocode;
|
||||
using Content.Shared.Medical;
|
||||
|
||||
namespace Content.Server._Sunrise.Biocode.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// System that handles biocode checks for defibrillators.
|
||||
/// </summary>
|
||||
public sealed class BiocodeDefibrillatorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly BiocodeSystem _biocode = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<BiocodeComponent, SunriseCanZapEvent>(OnCanZap);
|
||||
}
|
||||
|
||||
private void OnCanZap(EntityUid uid, BiocodeComponent component, ref SunriseCanZapEvent args)
|
||||
{
|
||||
if (args.User == null)
|
||||
return;
|
||||
|
||||
if (_biocode.CanUse(args.User.Value, component.Factions))
|
||||
return;
|
||||
|
||||
// User is not authorized, cancel the zap
|
||||
if (!string.IsNullOrEmpty(component.AlertText))
|
||||
_popup.PopupEntity(component.AlertText, uid, args.User.Value);
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.PowerCell;
|
||||
using Content.Shared.Item.ItemToggle;
|
||||
using Content.Shared.Item.ItemToggle.Components;
|
||||
using Content.Shared.Power.Components;
|
||||
using Content.Shared.PowerCell.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared._Sunrise.Weapons.Melee.Components;
|
||||
|
||||
namespace Content.Server._Sunrise.Weapons.Melee.Systems;
|
||||
|
||||
public sealed class PowerDrainOnMeleeHitSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ItemToggleSystem _itemToggle = default!;
|
||||
[Dependency] private readonly PowerCellSystem _powerCell = default!;
|
||||
[Dependency] private readonly BatterySystem _battery = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<PowerDrainOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
|
||||
}
|
||||
|
||||
private void OnMeleeHit(EntityUid uid, PowerDrainOnMeleeHitComponent comp, ref MeleeHitEvent args)
|
||||
{
|
||||
if (comp.ChargePerHit <= 0)
|
||||
return;
|
||||
|
||||
if (!args.IsHit)
|
||||
return;
|
||||
|
||||
if (comp.RequireActualHit && (args.HitEntities == null || args.HitEntities.Count == 0))
|
||||
return;
|
||||
|
||||
// Check if item is toggled on (if it has ItemToggleComponent)
|
||||
if (TryComp<ItemToggleComponent>(uid, out var toggle) && !_itemToggle.IsActivated((uid, toggle)))
|
||||
return;
|
||||
|
||||
// Prefer slotted power cell if present
|
||||
if (HasComp<PowerCellSlotComponent>(uid))
|
||||
{
|
||||
if (!_powerCell.HasCharge(uid, comp.ChargePerHit, null, args.User))
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_powerCell.TryUseCharge(uid, comp.ChargePerHit, null, args.User))
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fall back to direct BatteryComponent on the same entity
|
||||
if (TryComp<BatteryComponent>(uid, out var directBattery))
|
||||
{
|
||||
if (directBattery.CurrentCharge < comp.ChargePerHit)
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_battery.TryUseCharge(uid, comp.ChargePerHit, directBattery))
|
||||
{
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +77,20 @@ public sealed partial class DefibrillatorComponent : Component
|
|||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("readySound")]
|
||||
public SoundSpecifier? ReadySound = new SoundPathSpecifier("/Audio/Items/Defib/defib_ready.ogg");
|
||||
|
||||
// Sunrise-Start
|
||||
/// <summary>
|
||||
/// Whether the defibrillator can be used on alive targets
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool AllowUseOnAlive = false;
|
||||
|
||||
/// <summary>
|
||||
/// The reagents to inject when defibrillation is completed
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public Dictionary<string, float> Reagents = new();
|
||||
// Sunrise-End
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
|
|
|
|||
|
|
@ -37,3 +37,15 @@ public sealed class TargetBeforeDefibrillatorZapsEvent : BeforeDefibrillatorZaps
|
|||
{
|
||||
public TargetBeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibtarget) : base(entityUsingDefib, defib, defibtarget) { }
|
||||
}
|
||||
|
||||
// Sunrise-Start
|
||||
/// <summary>
|
||||
/// This event is raised to check if the defibrillator can be used.
|
||||
/// Systems can cancel this event to prevent defibrillation.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct SunriseCanZapEvent(EntityUid Defibrillator, EntityUid Target, EntityUid? User)
|
||||
{
|
||||
public bool Cancelled = false;
|
||||
}
|
||||
// Sunrise-End
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._Sunrise.Weapons.Melee.Components;
|
||||
|
||||
/// <summary>
|
||||
/// When attached to a melee weapon, drains power on successful melee hit.
|
||||
/// Drains from a slotted power cell if present, otherwise from a direct BatteryComponent.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class PowerDrainOnMeleeHitComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Amount of charge to drain per successful hit (in joules).
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public float ChargePerHit = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// If true, only drain when there is at least one entity hit.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public bool RequireActualHit = true;
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ ent-ClothingBackpackDuffelSyndicateHardsuitExtrasBundle = набор допол
|
|||
ent-ClothingBackpackDuffelZombieBundle = зомби набор Синдиката
|
||||
.desc = Универсальный набор для создания зомби на станции.
|
||||
ent-ClothingBackpackDuffelSyndicateMedicalBundleFilled = набор медикаментов
|
||||
.desc = Все, что нужно для возвращения в строй ваших товарищей: главным образом, боевая аптечка, дефибриллятор и три боевых медипена.
|
||||
.desc = Все, что нужно для возвращения в строй ваших товарищей: главным образом, боевая аптечка и три боевых медипена.
|
||||
ent-ClothingBackpackDuffelSyndicateDecoyKitFilled = набор обманок
|
||||
.desc = Содержит отвлекающие устройства, как звуковые, так и визуальные. Скоро появятся и обонятельные.
|
||||
ent-ClothingBackpackDuffelAcolyteBundle = набор брони послушника
|
||||
|
|
|
|||
|
|
@ -3,3 +3,6 @@ ent-SyndicateTeleporter = телепортер синдиката
|
|||
|
||||
ent-SyndicateTeleporterBiocode = { ent-SyndicateTeleporter }
|
||||
.desc = { ent-SyndicateTeleporter.desc }
|
||||
|
||||
ent-DefibrillatorSyndicateBiocode = { ent-DefibrillatorSyndicate }
|
||||
.desc = { ent-DefibrillatorSyndicate.desc }
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@ ent-DefibrillatorOneHandedUnpowered = { ent-BaseDefibrillator }
|
|||
ent-DefibrillatorCompact = компактный дефибриллятор
|
||||
.desc = Теперь в забавном размере!
|
||||
ent-DefibrillatorSyndicate = дефибриллятор Interdyne
|
||||
.desc = Двойное оружие самообороны против склонных к военным преступлениям тайдеров.
|
||||
.desc = Особый дефибриллятор фирмы Interdyne. Для настоящих медиков Синдиката!
|
||||
|
|
|
|||
|
|
@ -371,3 +371,5 @@ uplink-fake-mindshield-name = Имитатор защиты разума
|
|||
uplink-fake-mindshield-desc = Переключаемый имплант, воспроизводящий сигнатуры настоящего щита. Обманывает сканеры командования, создавая ложное присутствие защиты. (Имплантер NT не включён в поставку.)
|
||||
uplink-handcuffs-name = Наручники
|
||||
uplink-handcuffs-desc = Используется для удержания жертв.
|
||||
uplink-interdyne-defibrillator-name = Дефибриллятор Interdyne
|
||||
uplink-interdyne-defibrillator-desc = Превосходный дефибриллятор, предназначенный для помощи и самообороны. Для настоящих медиков Синдиката.
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@
|
|||
components:
|
||||
- type: StorageFill
|
||||
contents:
|
||||
- id: DefibrillatorSyndicate
|
||||
#- id: DefibrillatorSyndicate
|
||||
- id: MedkitCombatFilled
|
||||
amount: 4
|
||||
- id: Tourniquet
|
||||
|
|
|
|||
|
|
@ -899,9 +899,9 @@
|
|||
productEntity: ClothingBackpackDuffelSyndicateMedicalBundleFilled
|
||||
discountCategory: rareDiscounts
|
||||
discountDownTo:
|
||||
Telecrystal: 16
|
||||
Telecrystal: 12
|
||||
cost:
|
||||
Telecrystal: 24
|
||||
Telecrystal: 16
|
||||
categories:
|
||||
- UplinkChemicals
|
||||
conditions:
|
||||
|
|
|
|||
|
|
@ -112,6 +112,24 @@
|
|||
- state: ready
|
||||
map: ["enum.PowerDeviceVisualLayers.Powered"]
|
||||
shader: unshaded
|
||||
# Sunrise-Start
|
||||
- type: Defibrillator
|
||||
allowUseOnAlive: true
|
||||
reagents:
|
||||
Omnizine: 10
|
||||
Epinephrine: 5
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
cell_slot:
|
||||
name: power-cell-slot-component-slot-name-default
|
||||
startingItem: PowerCellDefibrillatorSyndicate
|
||||
disableEject: true
|
||||
locked: true
|
||||
- type: PowerCellDraw
|
||||
useRate: 85
|
||||
- type: PowerDrainOnMeleeHit
|
||||
chargePerHit: 30
|
||||
# Sunrise-End
|
||||
- type: MeleeWeapon
|
||||
damage:
|
||||
types:
|
||||
|
|
|
|||
|
|
@ -2252,7 +2252,7 @@
|
|||
sprite: /Textures/_Starlight/Objects/Weapons/Melee/cybermantisblade.rsi,
|
||||
state: cybermantisblade,
|
||||
}
|
||||
productEntity: MantisBladeArmsKit #ClothingBackpackDufelSyndicateFilledMantisBladeArms #Скучно и не практично в сумке ради 4 слота
|
||||
productEntity: MantisBladeArmsKit
|
||||
discountCategory: rareDiscounts
|
||||
discountDownTo:
|
||||
Telecrystal: 8
|
||||
|
|
@ -2443,6 +2443,29 @@
|
|||
categories:
|
||||
- UplinkDeception
|
||||
conditions:
|
||||
- !type:StoreWhitelistCondition
|
||||
whitelist:
|
||||
- Science
|
||||
tags:
|
||||
- NukeOpsUplink
|
||||
- LoneOpsUplink
|
||||
- AssaultOpsUplink
|
||||
|
||||
- type: listing
|
||||
id: UplinkDefibrillatorSyndicate
|
||||
name: uplink-interdyne-defibrillator-name
|
||||
description: uplink-interdyne-defibrillator-desc
|
||||
productEntity: DefibrillatorSyndicateBiocode
|
||||
discountCategory: rareDiscounts
|
||||
discountDownTo:
|
||||
Telecrystal: 4
|
||||
cost:
|
||||
Telecrystal: 8
|
||||
categories:
|
||||
- UplinkChemicals
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
- !type:StoreWhitelistCondition
|
||||
whitelist:
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -8,3 +8,17 @@
|
|||
- Syndicate
|
||||
- Thief
|
||||
alertText: Данный предмет биокодирован. Вы не можете его использовать.
|
||||
|
||||
- type: entity
|
||||
parent: DefibrillatorSyndicate
|
||||
id: DefibrillatorSyndicateBiocode
|
||||
suffix: BIOCODE
|
||||
components:
|
||||
- type: Biocode
|
||||
factions:
|
||||
- Syndicate
|
||||
alertText: Данный предмет биокодирован. Вы не можете его использовать.
|
||||
- type: FactionWeaponBlocker
|
||||
factions:
|
||||
- Syndicate
|
||||
alertText: Данное оружие биокодировано. Вы не можете его использовать.
|
||||
|
|
|
|||
|
|
@ -59,3 +59,35 @@
|
|||
graph: MakeshiftPowerCage
|
||||
node: makeshiftcage
|
||||
|
||||
- type: entity
|
||||
name: powercell defibrillator syndicate
|
||||
id: PowerCellDefibrillatorSyndicate
|
||||
suffix: Full
|
||||
parent: SyndicateDefibrillatorPowercell
|
||||
components:
|
||||
- type: Battery
|
||||
maxCharge: 300
|
||||
startingCharge: 300
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 4.5
|
||||
autoRecharge: true
|
||||
autoRechargePause: true
|
||||
autoRechargePauseTime: 25
|
||||
|
||||
- type: entity
|
||||
name: syndicate defibrillator power cell
|
||||
description: A rechargeable standardized power cell. This one looks like a rare and powerful Syndicate combat variant.
|
||||
id: SyndicateDefibrillatorPowercell
|
||||
suffix: Full
|
||||
parent: BasePowerCell
|
||||
components:
|
||||
- type: Sprite
|
||||
layers:
|
||||
- map: [ "enum.PowerCellVisualLayers.Base" ]
|
||||
state: syndicate
|
||||
- map: [ "enum.PowerCellVisualLayers.Unshaded" ]
|
||||
state: o2
|
||||
shader: unshaded
|
||||
- type: Battery
|
||||
maxCharge: 1800
|
||||
startingCharge: 1800
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue