2022-02-07 14:59:22 +11:00
using System.Collections.Generic ;
2021-12-30 22:56:10 +01:00
using Content.Client.Inventory ;
using Content.Shared.CharacterAppearance ;
using Content.Shared.Clothing ;
using Content.Shared.Inventory ;
using Content.Shared.Inventory.Events ;
2022-01-14 03:09:46 +13:00
using Content.Shared.Item ;
2021-12-30 22:56:10 +01:00
using Robust.Client.GameObjects ;
using Robust.Client.Graphics ;
using Robust.Client.ResourceManagement ;
using Robust.Shared.GameObjects ;
2022-02-07 14:59:22 +11:00
using Robust.Shared.GameStates ;
2021-12-30 22:56:10 +01:00
using Robust.Shared.IoC ;
namespace Content.Client.Clothing ;
public class ClothingSystem : EntitySystem
{
/// <summary>
/// This is a shitty hotfix written by me (Paul) to save me from renaming all files.
/// For some context, im currently refactoring inventory. Part of that is slots not being indexed by a massive enum anymore, but by strings.
/// Problem here: Every rsi-state is using the old enum-names in their state. I already used the new inventoryslots ALOT. tldr: its this or another week of renaming files.
/// </summary>
private static readonly Dictionary < string , string > TemporarySlotMap = new ( )
{
{ "head" , "HELMET" } ,
{ "eyes" , "EYES" } ,
{ "ears" , "EARS" } ,
{ "mask" , "MASK" } ,
{ "outerClothing" , "OUTERCLOTHING" } ,
{ "jumpsuit" , "INNERCLOTHING" } ,
{ "neck" , "NECK" } ,
{ "back" , "BACKPACK" } ,
{ "belt" , "BELT" } ,
{ "gloves" , "HAND" } ,
{ "shoes" , "FEET" } ,
{ "id" , "IDCARD" } ,
{ "pocket1" , "POCKET1" } ,
{ "pocket2" , "POCKET2" } ,
} ;
[Dependency] private IResourceCache _cache = default ! ;
[Dependency] private InventorySystem _inventorySystem = default ! ;
public override void Initialize ( )
{
base . Initialize ( ) ;
SubscribeLocalEvent < ClothingComponent , GotEquippedEvent > ( OnGotEquipped ) ;
2022-01-14 03:09:46 +13:00
SubscribeLocalEvent < ClothingComponent , GotUnequippedEvent > ( OnGotUnequipped ) ;
2022-02-07 14:59:22 +11:00
SubscribeLocalEvent < ClientInventoryComponent , ItemPrefixChangeEvent > ( OnPrefixChanged ) ;
2021-12-30 22:56:10 +01:00
SubscribeLocalEvent < SpriteComponent , DidUnequipEvent > ( OnDidUnequip ) ;
}
2022-02-07 14:59:22 +11:00
private void OnPrefixChanged ( EntityUid uid , ClientInventoryComponent component , ItemPrefixChangeEvent args )
2022-01-14 03:09:46 +13:00
{
if ( ! TryComp ( args . Item , out ClothingComponent ? clothing ) | | clothing . InSlot = = null )
return ;
RenderEquipment ( uid , args . Item , clothing . InSlot , component , null , clothing ) ;
}
private void OnGotUnequipped ( EntityUid uid , ClothingComponent component , GotUnequippedEvent args )
{
component . InSlot = null ;
}
2021-12-30 22:56:10 +01:00
private void OnDidUnequip ( EntityUid uid , SpriteComponent component , DidUnequipEvent args )
{
2022-02-07 14:59:22 +11:00
component . LayerSetVisible ( args . Slot , false ) ;
2021-12-30 22:56:10 +01:00
}
public void InitClothing ( EntityUid uid , ClientInventoryComponent ? component = null , SpriteComponent ? sprite = null )
{
if ( ! _inventorySystem . TryGetSlots ( uid , out var slots , component ) | | ! Resolve ( uid , ref sprite , ref component ) ) return ;
foreach ( var slot in slots )
{
2022-02-07 14:59:22 +11:00
sprite . LayerMapReserveBlank ( slot . Name ) ;
2021-12-30 22:56:10 +01:00
if ( ! _inventorySystem . TryGetSlotContainer ( uid , slot . Name , out var containerSlot , out _ , component ) | |
! containerSlot . ContainedEntity . HasValue ) continue ;
RenderEquipment ( uid , containerSlot . ContainedEntity . Value , slot . Name , component , sprite ) ;
}
}
private void OnGotEquipped ( EntityUid uid , ClothingComponent component , GotEquippedEvent args )
{
2022-01-14 03:09:46 +13:00
component . InSlot = args . Slot ;
2022-02-07 14:59:22 +11:00
if ( ! TryComp < SpriteComponent > ( args . Equipee , out var sprite ) | | ! TryComp < ClientInventoryComponent > ( args . Equipee , out var invComp ) )
{
return ;
}
var data = GetEquippedStateInfo ( args . Equipment , args . Slot , invComp . SpeciesId , component ) ;
if ( data ! = null )
{
var ( rsi , state ) = data . Value ;
sprite . LayerSetVisible ( args . Slot , true ) ;
sprite . LayerSetState ( args . Slot , state , rsi ) ;
sprite . LayerSetAutoAnimated ( args . Slot , true ) ;
if ( args . Slot = = "jumpsuit" & & sprite . LayerMapTryGet ( HumanoidVisualLayers . StencilMask , out _ ) )
{
sprite . LayerSetState ( HumanoidVisualLayers . StencilMask , component . FemaleMask switch
{
FemaleClothingMask . NoMask = > "female_none" ,
FemaleClothingMask . UniformTop = > "female_top" ,
_ = > "female_full" ,
} ) ;
}
return ;
}
sprite . LayerSetVisible ( args . Slot , false ) ;
2021-12-30 22:56:10 +01:00
}
2022-02-07 14:59:22 +11:00
private void RenderEquipment ( EntityUid uid , EntityUid equipment , string slot ,
ClientInventoryComponent ? inventoryComponent = null , SpriteComponent ? sprite = null , ClothingComponent ? clothingComponent = null )
2021-12-30 22:56:10 +01:00
{
2022-02-07 14:59:22 +11:00
if ( ! Resolve ( uid , ref inventoryComponent , ref sprite ) )
2021-12-30 22:56:10 +01:00
return ;
2022-02-07 14:59:22 +11:00
if ( ! Resolve ( equipment , ref clothingComponent , false ) )
{
sprite . LayerSetVisible ( slot , false ) ;
return ;
}
var data = GetEquippedStateInfo ( equipment , slot , inventoryComponent . SpeciesId , clothingComponent ) ;
if ( data = = null ) return ;
var ( rsi , state ) = data . Value ;
sprite . LayerSetVisible ( slot , true ) ;
sprite . LayerSetState ( slot , state , rsi ) ;
sprite . LayerSetAutoAnimated ( slot , true ) ;
2021-12-30 22:56:10 +01:00
if ( slot = = "jumpsuit" & & sprite . LayerMapTryGet ( HumanoidVisualLayers . StencilMask , out _ ) )
{
sprite . LayerSetState ( HumanoidVisualLayers . StencilMask , clothingComponent . FemaleMask switch
{
FemaleClothingMask . NoMask = > "female_none" ,
FemaleClothingMask . UniformTop = > "female_top" ,
_ = > "female_full" ,
} ) ;
}
2022-02-07 14:59:22 +11:00
}
2021-12-30 22:56:10 +01:00
2022-02-07 14:59:22 +11:00
public ( RSI rsi , RSI . StateId stateId ) ? GetEquippedStateInfo ( EntityUid uid , string slot , string? speciesId = null , ClothingComponent ? component = null )
{
if ( ! Resolve ( uid , ref component ) )
return null ;
2022-02-07 16:37:57 +13:00
2022-02-07 14:59:22 +11:00
if ( component . RsiPath = = null )
return null ;
2021-12-30 22:56:10 +01:00
2022-02-07 14:59:22 +11:00
var rsi = _cache . GetResource < RSIResource > ( SharedSpriteComponent . TextureRoot / component . RsiPath ) . RSI ;
var correctedSlot = slot ;
TemporarySlotMap . TryGetValue ( correctedSlot , out correctedSlot ) ;
var stateId = component . EquippedPrefix ! = null ? $"{component.EquippedPrefix}-equipped-{correctedSlot}" : $"equipped-{correctedSlot}" ;
if ( speciesId ! = null )
2021-12-30 22:56:10 +01:00
{
2022-02-07 14:59:22 +11:00
var speciesState = $"{stateId}-{speciesId}" ;
if ( rsi . TryGetState ( speciesState , out _ ) )
2022-02-07 16:37:57 +13:00
{
2022-02-07 14:59:22 +11:00
return ( rsi , speciesState ) ;
2022-02-07 16:37:57 +13:00
}
2022-02-07 14:59:22 +11:00
}
2022-02-07 16:37:57 +13:00
2022-02-07 14:59:22 +11:00
if ( rsi . TryGetState ( stateId , out _ ) )
{
return ( rsi , stateId ) ;
2021-12-30 22:56:10 +01:00
}
2022-02-07 14:59:22 +11:00
return null ;
2021-12-30 22:56:10 +01:00
}
}