Add action to pull down mask (#9015)

* Add action to pull down mask

* Update based on review comments

* fix access

* cleanup

* Update based on review comments

* revert change to ToggleableClothingSystem

* switch to unequip

* Specify the unequip is for togglemaskevent only

* fix issue of activating mask in hands with something else in mask slot

* Update based on review comments

* switch to dependency for ActionSystem for consistency

* whoops other instance too

* review changes
This commit is contained in:
themias
2022-06-30 03:44:53 -04:00
committed by GitHub
parent 11ac60ca2b
commit a18aac158e
6 changed files with 155 additions and 10 deletions

View File

@@ -0,0 +1,20 @@
using Content.Shared.Actions;
using Content.Shared.Actions.ActionTypes;
namespace Content.Server.Clothing.Components
{
[Access(typeof(MaskSystem))]
[RegisterComponent]
public sealed class MaskComponent : Component
{
/// <summary>
/// This mask can be toggled (pulled up/down)
/// </summary>
[DataField("toggleAction")]
public InstantAction? ToggleAction = null;
public bool IsToggled = false;
}
public sealed class ToggleMaskEvent : InstantActionEvent { }
}

View File

@@ -0,0 +1,106 @@
using Content.Shared.Actions;
using Content.Shared.Toggleable;
using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
using Content.Server.Actions;
using Content.Server.Atmos.Components;
using Content.Server.Body.Components;
using Content.Server.Clothing.Components;
using Content.Server.Disease.Components;
using Content.Server.Nutrition.EntitySystems;
using Content.Server.Popups;
using Robust.Shared.Player;
namespace Content.Server.Clothing
{
public sealed class MaskSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly InventorySystem _inventorySystem = default!;
[Dependency] private readonly ActionsSystem _actionSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MaskComponent, ToggleMaskEvent>(OnToggleMask);
SubscribeLocalEvent<MaskComponent, GetItemActionsEvent>(OnGetActions);
SubscribeLocalEvent<MaskComponent, GotUnequippedEvent>(OnGotUnequipped);
}
private void OnGetActions(EntityUid uid, MaskComponent component, GetItemActionsEvent args)
{
if (component.ToggleAction != null && !args.InHands)
args.Actions.Add(component.ToggleAction);
}
private void OnToggleMask(EntityUid uid, MaskComponent mask, ToggleMaskEvent args)
{
if (mask.ToggleAction == null)
return;
if (!_inventorySystem.TryGetSlotEntity(args.Performer, "mask", out var existing) || !mask.Owner.Equals(existing))
return;
mask.IsToggled ^= true;
_actionSystem.SetToggled(mask.ToggleAction, mask.IsToggled);
if (mask.IsToggled)
_popupSystem.PopupEntity(Loc.GetString("action-mask-pull-down-popup-message", ("mask", mask.Owner)), args.Performer, Filter.Entities(args.Performer));
else
_popupSystem.PopupEntity(Loc.GetString("action-mask-pull-up-popup-message", ("mask", mask.Owner)), args.Performer, Filter.Entities(args.Performer));
ToggleMaskComponents(uid, mask, args.Performer);
}
// set to untoggled when unequipped, so it isn't left in a 'pulled down' state
private void OnGotUnequipped(EntityUid uid, MaskComponent mask, GotUnequippedEvent args)
{
if (mask.ToggleAction == null)
return;
mask.IsToggled = false;
_actionSystem.SetToggled(mask.ToggleAction, mask.IsToggled);
ToggleMaskComponents(uid, mask, args.Equipee, true);
}
private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false)
{
//toggle visuals
if (TryComp<SharedItemComponent>(mask.Owner, out var item))
{
//TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix
item.EquippedPrefix = mask.IsToggled ? "toggled" : null;
Dirty(item);
}
//toggle ingestion blocking
if (TryComp<IngestionBlockerComponent>(uid, out var blocker))
blocker.Enabled = !mask.IsToggled;
//toggle disease protection
if (TryComp<DiseaseProtectionComponent>(uid, out var diseaseProtection))
diseaseProtection.IsActive = !mask.IsToggled;
//toggle breath tool connection (skip during equip since that is handled in LungSystem)
if (isEquip || !TryComp<BreathToolComponent>(uid, out var breathTool))
return;
if (mask.IsToggled)
{
breathTool.DisconnectInternals();
}
else
{
breathTool.IsFunctional = true;
if (TryComp(wearer, out InternalsComponent? internals))
{
breathTool.ConnectedInternalsEntity = wearer;
internals.ConnectBreathTool(uid);
}
}
}
}
}

View File

@@ -1,3 +1,5 @@
using Content.Server.Clothing;
namespace Content.Server.Nutrition.EntitySystems; namespace Content.Server.Nutrition.EntitySystems;
/// <summary> /// <summary>
@@ -7,7 +9,7 @@ namespace Content.Server.Nutrition.EntitySystems;
/// In the event that more head-wear & mask functionality is added (like identity systems, or raising/lowering of /// In the event that more head-wear & mask functionality is added (like identity systems, or raising/lowering of
/// masks), then this component might become redundant. /// masks), then this component might become redundant.
/// </remarks> /// </remarks>
[RegisterComponent, Access(typeof(FoodSystem), typeof(DrinkSystem))] [RegisterComponent, Access(typeof(FoodSystem), typeof(DrinkSystem), typeof(MaskSystem))]
public sealed class IngestionBlockerComponent : Component public sealed class IngestionBlockerComponent : Component
{ {
/// <summary> /// <summary>

View File

@@ -0,0 +1,4 @@
action-name-mask = Toggle Mask
action-description-mask-toggle = Handy, but prevents insertion of pie into your pie hole.
action-mask-pull-up-popup-message = You pull up your {$mask}.
action-mask-pull-down-popup-message = You pull down your {$mask}.

View File

@@ -7,3 +7,16 @@
state: icon state: icon
- type: Clothing - type: Clothing
Slots: [mask] Slots: [mask]
- type: entity
abstract: true
parent: ClothingMaskBase
id: ClothingMaskPullableBase
components:
- type: Mask
toggleAction:
name: action-name-mask
description: action-description-mask-toggle
icon: Clothing/Mask/gas.rsi/icon.png
iconOn: Interface/Inventory/blocked.png
event: !type:ToggleMaskEvent

View File

@@ -1,5 +1,5 @@
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskGas id: ClothingMaskGas
name: gas mask name: gas mask
description: A face-covering mask that can be connected to an air supply. description: A face-covering mask that can be connected to an air supply.
@@ -14,7 +14,7 @@
protection: 0.05 protection: 0.05
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskGasSecurity id: ClothingMaskGasSecurity
name: security gas mask name: security gas mask
description: A standard issue Security gas mask. description: A standard issue Security gas mask.
@@ -29,7 +29,7 @@
protection: 0.05 protection: 0.05
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskGasSyndicate id: ClothingMaskGasSyndicate
name: syndicate gas mask name: syndicate gas mask
description: A close-fitting tactical mask that can be connected to an air supply. description: A close-fitting tactical mask that can be connected to an air supply.
@@ -45,7 +45,7 @@
- type: FlashImmunity - type: FlashImmunity
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskGasAtmos id: ClothingMaskGasAtmos
name: atmospheric gas mask name: atmospheric gas mask
description: Improved gas mask utilized by atmospheric technicians. It's flameproof! description: Improved gas mask utilized by atmospheric technicians. It's flameproof!
@@ -94,7 +94,7 @@
protection: 0.05 protection: 0.05
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskGasExplorer id: ClothingMaskGasExplorer
name: explorer gas mask name: explorer gas mask
description: A military-grade gas mask that can be connected to an air supply. description: A military-grade gas mask that can be connected to an air supply.
@@ -116,7 +116,7 @@
Heat: 0.95 Heat: 0.95
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskBreathMedical id: ClothingMaskBreathMedical
name: medical mask name: medical mask
description: A close-fitting sterile mask that can be connected to an air supply. description: A close-fitting sterile mask that can be connected to an air supply.
@@ -131,7 +131,7 @@
protection: 0.10 protection: 0.10
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskBreath id: ClothingMaskBreath
name: breath mask name: breath mask
description: Might as well keep this on 24/7. description: Might as well keep this on 24/7.
@@ -182,7 +182,7 @@
- type: BreathMask - type: BreathMask
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskSterile id: ClothingMaskSterile
name: sterile mask name: sterile mask
description: A sterile mask designed to help prevent the spread of diseases. description: A sterile mask designed to help prevent the spread of diseases.
@@ -211,7 +211,7 @@
replacement: mumble replacement: mumble
- type: entity - type: entity
parent: ClothingMaskBase parent: ClothingMaskPullableBase
id: ClothingMaskPlague id: ClothingMaskPlague
name: plague doctor mask name: plague doctor mask
description: A bad omen. description: A bad omen.