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-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 ;
2024-04-01 06:27:39 +00:00
using Content.Shared.Nutrition.EntitySystems ;
2023-12-29 04:47:43 -08:00
using Content.Shared.Popups ;
2024-03-22 10:37:46 +01:00
using Content.Shared.Verbs ;
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 ! ;
2024-03-22 10:37:46 +01:00
[Dependency] private readonly OpenableSystem _openable = 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 ) ;
2024-03-22 10:37:46 +01:00
SubscribeLocalEvent < GlueComponent , GetVerbsEvent < UtilityVerb > > ( OnUtilityVerb ) ;
2023-06-30 22:07:44 +03:00
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 ;
2024-03-22 10:37:46 +01:00
}
private void OnUtilityVerb ( Entity < GlueComponent > entity , ref GetVerbsEvent < UtilityVerb > args )
{
if ( ! args . CanInteract | | ! args . CanAccess | | args . Target is not { Valid : true } target | |
_openable . IsClosed ( entity ) )
return ;
var user = args . User ;
var verb = new UtilityVerb ( )
2023-06-03 04:31:47 +01:00
{
2024-03-22 10:37:46 +01:00
Act = ( ) = > TryGlue ( entity , target , user ) ,
IconEntity = GetNetEntity ( entity ) ,
Text = Loc . GetString ( "glue-verb-text" ) ,
Message = Loc . GetString ( "glue-verb-message" )
} ;
args . Verbs . Add ( verb ) ;
2023-06-30 22:07:44 +03:00
}
2023-06-03 04:31:47 +01:00
2024-03-22 10:37:46 +01:00
private bool TryGlue ( Entity < GlueComponent > entity , 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 ) )
{
2024-03-22 10:37:46 +01:00
_popup . PopupEntity ( Loc . GetString ( "glue-failure" , ( "target" , target ) ) , actor , actor , PopupType . Medium ) ;
2023-06-30 22:07:44 +03:00
return false ;
}
2023-06-03 04:31:47 +01:00
2024-03-22 10:37:46 +01:00
if ( HasComp < ItemComponent > ( target ) & & _solutionContainer . TryGetSolution ( entity . Owner , entity . Comp . Solution , out _ , out var solution ) )
2023-06-30 22:07:44 +03:00
{
2024-03-22 10:37:46 +01:00
var quantity = solution . RemoveReagent ( entity . Comp . Reagent , entity . Comp . ConsumptionUnit ) ;
2023-06-30 22:07:44 +03:00
if ( quantity > 0 )
2023-06-03 04:31:47 +01:00
{
2024-03-22 10:37:46 +01:00
EnsureComp < GluedComponent > ( target ) . Duration = quantity . Double ( ) * entity . Comp . DurationPerUnit ;
_adminLogger . Add ( LogType . Action , LogImpact . Medium , $"{ToPrettyString(actor):actor} glued {ToPrettyString(target):subject} with {ToPrettyString(entity.Owner):tool}" ) ;
_audio . PlayPvs ( entity . Comp . Squeeze , entity . Owner ) ;
_popup . PopupEntity ( Loc . GetString ( "glue-success" , ( "target" , target ) ) , actor , actor , PopupType . Medium ) ;
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
}
2024-03-22 10:37:46 +01:00
_popup . PopupEntity ( Loc . GetString ( "glue-failure" , ( "target" , target ) ) , actor , actor , PopupType . Medium ) ;
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
}
}