2023-08-04 21:26:42 -05:00
using Content.Server.Administration.Logs ;
2023-12-29 04:47:43 -08:00
using Content.Server.Chemistry.Containers.EntitySystems ;
2023-09-23 03:10:04 +01:00
using Content.Server.Nutrition.EntitySystems ;
2023-08-04 21:26:42 -05:00
using Content.Shared.Database ;
2023-12-29 04:47:43 -08:00
using Content.Shared.Glue ;
2023-06-30 22:07:44 +03:00
using Content.Shared.Hands ;
2023-12-29 04:47:43 -08:00
using Content.Shared.Interaction ;
2023-06-30 22:07:44 +03:00
using Content.Shared.Interaction.Components ;
2023-12-29 04:47:43 -08:00
using Content.Shared.Item ;
using Content.Shared.Popups ;
2023-11-27 22:12:34 +11:00
using Robust.Shared.Audio.Systems ;
2023-12-29 04:47:43 -08:00
using Robust.Shared.Timing ;
2023-06-03 04:31:47 +01:00
2023-06-30 22:07:44 +03:00
namespace Content.Server.Glue ;
public sealed class GlueSystem : SharedGlueSystem
2023-06-03 04:31:47 +01:00
{
2023-06-30 22:07:44 +03:00
[Dependency] private readonly SharedAudioSystem _audio = default ! ;
[Dependency] private readonly SharedPopupSystem _popup = default ! ;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default ! ;
[Dependency] private readonly IGameTiming _timing = default ! ;
[Dependency] private readonly MetaDataSystem _metaData = default ! ;
2023-08-04 21:26:42 -05:00
[Dependency] private readonly IAdminLogManager _adminLogger = default ! ;
2023-06-30 22:07:44 +03:00
public override void Initialize ( )
2023-06-03 04:31:47 +01:00
{
2023-06-30 22:07:44 +03:00
base . Initialize ( ) ;
2023-06-03 04:31:47 +01:00
2023-09-23 03:10:04 +01:00
SubscribeLocalEvent < GlueComponent , AfterInteractEvent > ( OnInteract , after : new [ ] { typeof ( OpenableSystem ) } ) ;
2023-06-30 22:07:44 +03:00
SubscribeLocalEvent < GluedComponent , ComponentInit > ( OnGluedInit ) ;
SubscribeLocalEvent < GluedComponent , GotEquippedHandEvent > ( OnHandPickUp ) ;
}
2023-06-03 04:31:47 +01:00
2023-06-30 22:07:44 +03:00
// When glue bottle is used on item it will apply the glued and unremoveable components.
2023-12-29 04:47:43 -08:00
private void OnInteract ( Entity < GlueComponent > entity , ref AfterInteractEvent args )
2023-06-30 22:07:44 +03:00
{
if ( args . Handled )
return ;
if ( ! args . CanReach | | args . Target is not { Valid : true } target )
return ;
2023-06-03 04:31:47 +01:00
2023-12-29 04:47:43 -08:00
if ( TryGlue ( entity , target , args . User ) )
2023-06-30 22:07:44 +03:00
{
args . Handled = true ;
2023-12-29 04:47:43 -08:00
_audio . PlayPvs ( entity . Comp . Squeeze , entity ) ;
2023-06-30 22:07:44 +03:00
_popup . PopupEntity ( Loc . GetString ( "glue-success" , ( "target" , target ) ) , args . User , args . User , PopupType . Medium ) ;
}
else
2023-06-03 04:31:47 +01:00
{
2023-06-30 22:07:44 +03:00
_popup . PopupEntity ( Loc . GetString ( "glue-failure" , ( "target" , target ) ) , args . User , args . User , PopupType . Medium ) ;
}
}
2023-06-03 04:31:47 +01:00
2023-12-29 04:47:43 -08:00
private bool TryGlue ( Entity < GlueComponent > glue , EntityUid target , EntityUid actor )
2023-06-30 22:07:44 +03:00
{
// if item is glued then don't apply glue again so it can be removed for reasonable time
if ( HasComp < GluedComponent > ( target ) | | ! HasComp < ItemComponent > ( target ) )
{
return false ;
}
2023-06-03 04:31:47 +01:00
2023-12-29 04:47:43 -08:00
if ( HasComp < ItemComponent > ( target ) & & _solutionContainer . TryGetSolution ( glue . Owner , glue . Comp . Solution , out _ , out var solution ) )
2023-06-30 22:07:44 +03:00
{
2023-12-29 04:47:43 -08:00
var quantity = solution . RemoveReagent ( glue . Comp . Reagent , glue . Comp . ConsumptionUnit ) ;
2023-06-30 22:07:44 +03:00
if ( quantity > 0 )
2023-06-03 04:31:47 +01:00
{
2023-12-29 04:47:43 -08:00
EnsureComp < GluedComponent > ( target ) . Duration = quantity . Double ( ) * glue . Comp . DurationPerUnit ;
_adminLogger . Add ( LogType . Action , LogImpact . Medium , $"{ToPrettyString(actor):actor} glued {ToPrettyString(target):subject} with {ToPrettyString(glue.Owner):tool}" ) ;
2023-06-30 22:07:44 +03:00
return true ;
2023-06-03 04:31:47 +01:00
}
2023-06-30 22:07:44 +03:00
}
return false ;
}
2023-06-03 04:31:47 +01:00
2023-06-30 22:07:44 +03:00
public override void Update ( float frameTime )
{
base . Update ( frameTime ) ;
2023-06-03 04:31:47 +01:00
2024-02-07 18:43:44 -05:00
var query = EntityQueryEnumerator < GluedComponent , UnremoveableComponent , MetaDataComponent > ( ) ;
while ( query . MoveNext ( out var uid , out var glue , out var _ , out var meta ) )
2023-06-30 22:07:44 +03:00
{
if ( _timing . CurTime < glue . Until )
continue ;
2023-06-03 04:31:47 +01:00
2024-02-07 18:43:44 -05:00
// Instead of string matching, just reconstruct the expected name and compare
if ( meta . EntityName = = Loc . GetString ( "glued-name-prefix" , ( "target" , glue . BeforeGluedEntityName ) ) )
_metaData . SetEntityName ( uid , glue . BeforeGluedEntityName ) ;
2023-06-30 22:07:44 +03:00
RemComp < UnremoveableComponent > ( uid ) ;
RemComp < GluedComponent > ( uid ) ;
2023-06-03 04:31:47 +01:00
}
2023-06-30 22:07:44 +03:00
}
2023-06-03 04:31:47 +01:00
2023-12-29 04:47:43 -08:00
private void OnGluedInit ( Entity < GluedComponent > entity , ref ComponentInit args )
2023-06-30 22:07:44 +03:00
{
2023-12-29 04:47:43 -08:00
var meta = MetaData ( entity ) ;
2023-06-30 22:07:44 +03:00
var name = meta . EntityName ;
2023-12-29 04:47:43 -08:00
entity . Comp . BeforeGluedEntityName = meta . EntityName ;
_metaData . SetEntityName ( entity . Owner , Loc . GetString ( "glued-name-prefix" , ( "target" , name ) ) ) ;
2023-06-30 22:07:44 +03:00
}
2023-12-29 04:47:43 -08:00
private void OnHandPickUp ( Entity < GluedComponent > entity , ref GotEquippedHandEvent args )
2023-06-30 22:07:44 +03:00
{
2024-01-25 09:01:13 -05:00
var comp = EnsureComp < UnremoveableComponent > ( entity ) ;
comp . DeleteOnDrop = false ;
2023-12-29 04:47:43 -08:00
entity . Comp . Until = _timing . CurTime + entity . Comp . Duration ;
2023-06-03 04:31:47 +01:00
}
}