Working flashlight for hard hats (#2599)

* Add verb to toggle flashlight

* Playing with hand-held light for hard hat

* ClothingEquippedPrefix will update players sprite when changed

* Make abstract prototype for hardhat and fixed hardhat orange sprites

* Fixed all other hard hats

* Fixed requested changes

* Restore prototype and sprites changes

* Nullables

* That's actually nullable

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
Alex Evgrashin
2020-11-23 06:17:38 +03:00
committed by GitHub
parent e97763afd2
commit fb6dd4a490
44 changed files with 202 additions and 31 deletions

View File

@@ -1,9 +1,13 @@
using Content.Client.GameObjects.Components.Items; #nullable enable
using Content.Client.GameObjects.Components.HUD.Inventory;
using Content.Client.GameObjects.Components.Items;
using Content.Shared.GameObjects; using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Items;
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects.Components;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -18,8 +22,29 @@ namespace Content.Client.GameObjects.Components.Clothing
public override string Name => "Clothing"; public override string Name => "Clothing";
public override uint? NetID => ContentNetIDs.CLOTHING; public override uint? NetID => ContentNetIDs.CLOTHING;
private string? _clothingEquippedPrefix;
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public string ClothingEquippedPrefix { get; set; } public string? ClothingEquippedPrefix
{
get => _clothingEquippedPrefix;
set
{
if (_clothingEquippedPrefix == value)
return;
_clothingEquippedPrefix = value;
if (!Owner.TryGetContainer(out IContainer? container))
return;
if (!container.Owner.TryGetComponent(out ClientInventoryComponent? inventory))
return;
if (!inventory.TryFindItemSlots(Owner, out EquipmentSlotDefines.Slots? slots))
return;
inventory.SetSlotVisuals(slots.Value, Owner);
}
}
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public FemaleClothingMask FemaleMask public FemaleClothingMask FemaleMask
@@ -54,7 +79,7 @@ namespace Content.Client.GameObjects.Components.Clothing
return null; return null;
} }
public override void HandleComponentState(ComponentState curState, ComponentState nextState) public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{ {
if (curState == null) if (curState == null)
return; return;

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic; #nullable enable
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using Content.Client.GameObjects.Components.Clothing; using Content.Client.GameObjects.Components.Clothing;
using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Inventory;
@@ -22,10 +24,9 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
{ {
private readonly Dictionary<Slots, IEntity> _slots = new Dictionary<Slots, IEntity>(); private readonly Dictionary<Slots, IEntity> _slots = new Dictionary<Slots, IEntity>();
[ViewVariables] [ViewVariables] public InventoryInterfaceController InterfaceController { get; private set; } = default!;
public InventoryInterfaceController InterfaceController { get; private set; }
private ISpriteComponent _sprite; private ISpriteComponent? _sprite;
private bool _playerAttached = false; private bool _playerAttached = false;
@@ -69,7 +70,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
} }
} }
public override void HandleComponentState(ComponentState curState, ComponentState nextState) public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{ {
base.HandleComponentState(curState, nextState); base.HandleComponentState(curState, nextState);
@@ -126,7 +127,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
return; return;
} }
if (entity != null && entity.TryGetComponent(out ClothingComponent clothing)) if (entity.TryGetComponent(out ClothingComponent? clothing))
{ {
var flag = SlotMasks[slot]; var flag = SlotMasks[slot];
var data = clothing.GetEquippedStateInfo(flag); var data = clothing.GetEquippedStateInfo(flag);
@@ -155,6 +156,9 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
internal void ClearAllSlotVisuals() internal void ClearAllSlotVisuals()
{ {
if (_sprite == null)
return;
foreach (var slot in InventoryInstance.SlotMasks) foreach (var slot in InventoryInstance.SlotMasks)
{ {
if (slot != Slots.NONE) if (slot != Slots.NONE)
@@ -192,7 +196,7 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
SendNetworkMessage(new OpenSlotStorageUIMessage(slot)); SendNetworkMessage(new OpenSlotStorageUIMessage(slot));
} }
public override void HandleMessage(ComponentMessage message, IComponent component) public override void HandleMessage(ComponentMessage message, IComponent? component)
{ {
base.HandleMessage(message, component); base.HandleMessage(message, component);
@@ -210,9 +214,25 @@ namespace Content.Client.GameObjects.Components.HUD.Inventory
} }
} }
public bool TryGetSlot(Slots slot, out IEntity item) public bool TryGetSlot(Slots slot, out IEntity? item)
{ {
return _slots.TryGetValue(slot, out item); return _slots.TryGetValue(slot, out item);
} }
public bool TryFindItemSlots(IEntity item, [NotNullWhen(true)] out Slots? slots)
{
slots = null;
foreach (var (slot, entity) in _slots)
{
if (entity == item)
{
slots = slot;
return true;
}
}
return false;
}
} }
} }

View File

@@ -3,8 +3,10 @@ using System.Threading.Tasks;
using Content.Server.GameObjects.Components.Items.Clothing; using Content.Server.GameObjects.Components.Items.Clothing;
using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Items.Storage;
using Content.Server.GameObjects.Components.Power; using Content.Server.GameObjects.Components.Power;
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components;
using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility; using Content.Shared.Utility;
@@ -164,7 +166,7 @@ namespace Content.Server.GameObjects.Components.Interactable
if (Owner.TryGetComponent(out ClothingComponent? clothing)) if (Owner.TryGetComponent(out ClothingComponent? clothing))
{ {
clothing.ClothingEquippedPrefix = on ? "On" : "Off"; clothing.ClothingEquippedPrefix = on ? "on" : "off";
} }
if (Owner.TryGetComponent(out ItemComponent? item)) if (Owner.TryGetComponent(out ItemComponent? item))
@@ -226,5 +228,25 @@ namespace Content.Server.GameObjects.Components.Interactable
{ {
return new HandheldLightComponentState(GetLevel()); return new HandheldLightComponentState(GetLevel());
} }
[Verb]
public sealed class ToggleLightVerb : Verb<HandheldLightComponent>
{
protected override void GetData(IEntity user, HandheldLightComponent component, VerbData data)
{
if (!ActionBlockerSystem.CanInteract(user))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = Loc.GetString("Toggle light");
}
protected override void Activate(IEntity user, HandheldLightComponent component)
{
component.ToggleStatus(user);
}
}
} }
} }

View File

@@ -1,5 +1,29 @@
- type: entity - type: entity
parent: ClothingHeadBase parent: ClothingHeadBase
id: ClothingHeadHatHardhatBase
abstract: true
components:
- type: Sprite
layers:
- state: icon
- state: light-icon
shader: unshaded
visible: false
- type: Clothing
HeldPrefix: off
ClothingPrefix: off
- type: PointLight
enabled: false
radius: 3
- type: LoopingSound
- type: Appearance
visuals:
- type: FlashLightVisualizer
- type: HandheldLight
- type: PowerCellSlot
- type: entity
parent: ClothingHeadHatHardhatBase
id: ClothingHeadHatHardhatBlue id: ClothingHeadHatHardhatBlue
name: blue hard hat name: blue hard hat
description: A hard hat, painted in blue, used in dangerous working conditions to protect the head. Comes with a built-in flashlight. description: A hard hat, painted in blue, used in dangerous working conditions to protect the head. Comes with a built-in flashlight.
@@ -10,7 +34,7 @@
sprite: Clothing/Head/Hardhats/blue.rsi sprite: Clothing/Head/Hardhats/blue.rsi
- type: entity - type: entity
parent: ClothingHeadBase parent: ClothingHeadHatHardhatBase
id: ClothingHeadHatHardhatOrange id: ClothingHeadHatHardhatOrange
name: orange hard hat name: orange hard hat
description: A hard hat, painted in orange, used in dangerous working conditions to protect the head. Comes with a built-in flashlight. description: A hard hat, painted in orange, used in dangerous working conditions to protect the head. Comes with a built-in flashlight.
@@ -21,7 +45,7 @@
sprite: Clothing/Head/Hardhats/orange.rsi sprite: Clothing/Head/Hardhats/orange.rsi
- type: entity - type: entity
parent: ClothingHeadBase parent: ClothingHeadHatHardhatBase
id: ClothingHeadHatHardhatRed id: ClothingHeadHatHardhatRed
name: red hard hat name: red hard hat
description: A hard hat, painted in red, used in dangerous working conditions to protect the head. Comes with a built-in flashlight. description: A hard hat, painted in red, used in dangerous working conditions to protect the head. Comes with a built-in flashlight.
@@ -32,7 +56,7 @@
sprite: Clothing/Head/Hardhats/red.rsi sprite: Clothing/Head/Hardhats/red.rsi
- type: entity - type: entity
parent: ClothingHeadBase parent: ClothingHeadHatHardhatBase
id: ClothingHeadHatHardhatWhite id: ClothingHeadHatHardhatWhite
name: white hard hat name: white hard hat
description: A hard hat, painted in white, used in dangerous working conditions to protect the head. Comes with a built-in flashlight. description: A hard hat, painted in white, used in dangerous working conditions to protect the head. Comes with a built-in flashlight.
@@ -43,7 +67,7 @@
sprite: Clothing/Head/Hardhats/white.rsi sprite: Clothing/Head/Hardhats/white.rsi
- type: entity - type: entity
parent: ClothingHeadBase parent: ClothingHeadHatHardhatBase
id: ClothingHeadHatHardhatYellow id: ClothingHeadHatHardhatYellow
name: yellow hard hat name: yellow hard hat
description: A hard hat, painted in yellow, used in dangerous working conditions to protect the head. Comes with a built-in flashlight. description: A hard hat, painted in yellow, used in dangerous working conditions to protect the head. Comes with a built-in flashlight.

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -10,17 +10,33 @@
{ {
"name": "icon", "name": "icon",
"directions": 1 "directions": 1
},
{
"name": "light-icon",
"directions": 1
}, },
{ {
"name": "equipped-HELMET", "name": "off-equipped-HELMET",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-left", "name": "off-inhand-left",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-right", "name": "off-inhand-right",
"directions": 4
},
{
"name": "on-equipped-HELMET",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4 "directions": 4
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -10,17 +10,33 @@
{ {
"name": "icon", "name": "icon",
"directions": 1 "directions": 1
},
{
"name": "light-icon",
"directions": 1
}, },
{ {
"name": "equipped-HELMET", "name": "off-equipped-HELMET",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-left", "name": "off-inhand-left",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-right", "name": "off-inhand-right",
"directions": 4
},
{
"name": "on-equipped-HELMET",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4 "directions": 4
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -10,17 +10,33 @@
{ {
"name": "icon", "name": "icon",
"directions": 1 "directions": 1
},
{
"name": "light-icon",
"directions": 1
}, },
{ {
"name": "equipped-HELMET", "name": "off-equipped-HELMET",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-left", "name": "off-inhand-left",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-right", "name": "off-inhand-right",
"directions": 4
},
{
"name": "on-equipped-HELMET",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4 "directions": 4
} }
] ]

View File

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -10,17 +10,33 @@
{ {
"name": "icon", "name": "icon",
"directions": 1 "directions": 1
},
{
"name": "light-icon",
"directions": 1
}, },
{ {
"name": "equipped-HELMET", "name": "off-equipped-HELMET",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-left", "name": "off-inhand-left",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-right", "name": "off-inhand-right",
"directions": 4
},
{
"name": "on-equipped-HELMET",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4 "directions": 4
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -10,17 +10,33 @@
{ {
"name": "icon", "name": "icon",
"directions": 1 "directions": 1
},
{
"name": "light-icon",
"directions": 1
}, },
{ {
"name": "equipped-HELMET", "name": "off-equipped-HELMET",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-left", "name": "off-inhand-left",
"directions": 4 "directions": 4
}, },
{ {
"name": "inhand-right", "name": "off-inhand-right",
"directions": 4
},
{
"name": "on-equipped-HELMET",
"directions": 4
},
{
"name": "on-inhand-left",
"directions": 4
},
{
"name": "on-inhand-right",
"directions": 4 "directions": 4
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 725 B