2022-08-07 20:21:56 -03:00
using System.Linq ;
2021-12-05 15:34:32 +13:00
using Content.Server.Administration.Logs ;
2022-08-07 20:21:56 -03:00
using Content.Server.Chemistry.Components.SolutionManager ;
2021-07-25 20:09:08 +10:00
using Content.Server.Explosion.Components ;
2021-09-09 16:20:41 +02:00
using Content.Server.Flash ;
2021-07-25 20:09:08 +10:00
using Content.Server.Flash.Components ;
2022-05-29 02:29:10 -04:00
using Content.Server.Sticky.Events ;
using Content.Shared.Actions ;
2019-06-07 16:15:20 +05:00
using JetBrains.Annotations ;
2021-07-25 20:09:08 +10:00
using Robust.Shared.Audio ;
2022-02-06 15:59:41 +00:00
using Robust.Shared.Physics ;
2021-07-25 20:09:08 +10:00
using Robust.Shared.Physics.Dynamics ;
using Robust.Shared.Player ;
2022-02-06 15:59:41 +00:00
using Content.Shared.Trigger ;
2022-03-25 17:17:29 +13:00
using Content.Shared.Database ;
2022-06-01 01:39:06 -07:00
using Content.Shared.Explosion ;
2022-05-29 02:29:10 -04:00
using Content.Shared.Interaction ;
2022-08-07 20:21:56 -03:00
using Content.Shared.Payload.Components ;
2022-07-10 02:28:37 -07:00
using Content.Shared.StepTrigger.Systems ;
2022-08-07 20:21:56 -03:00
using Robust.Server.Containers ;
using Robust.Shared.Containers ;
2019-06-07 16:15:20 +05:00
2021-11-09 21:24:35 +01:00
namespace Content.Server.Explosion.EntitySystems
2019-06-07 16:15:20 +05:00
{
/// <summary>
2021-07-25 20:09:08 +10:00
/// Raised whenever something is Triggered on the entity.
2019-06-07 16:15:20 +05:00
/// </summary>
2022-02-06 15:59:41 +00:00
public sealed class TriggerEvent : HandledEntityEventArgs
2019-06-07 16:15:20 +05:00
{
2021-12-05 18:09:01 +01:00
public EntityUid Triggered { get ; }
2021-12-05 15:34:32 +13:00
public EntityUid ? User { get ; }
2019-06-07 16:15:20 +05:00
2021-12-07 17:48:49 +01:00
public TriggerEvent ( EntityUid triggered , EntityUid ? user = null )
2021-03-16 15:50:20 +01:00
{
2021-07-25 20:09:08 +10:00
Triggered = triggered ;
2021-03-16 15:50:20 +01:00
User = user ;
}
2019-06-07 16:15:20 +05:00
}
[UsedImplicitly]
2022-01-29 22:45:50 +11:00
public sealed partial class TriggerSystem : EntitySystem
2019-06-07 16:15:20 +05:00
{
2021-11-09 21:24:35 +01:00
[Dependency] private readonly ExplosionSystem _explosions = default ! ;
2022-02-06 15:59:41 +00:00
[Dependency] private readonly FixtureSystem _fixtures = default ! ;
2021-09-09 16:20:41 +02:00
[Dependency] private readonly FlashSystem _flashSystem = default ! ;
2022-02-06 15:59:41 +00:00
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default ! ;
2022-08-07 20:21:56 -03:00
[Dependency] private readonly IAdminLogManager _adminLogger = default ! ;
[Dependency] private readonly SharedContainerSystem _container = default ! ;
2021-09-09 16:20:41 +02:00
2021-07-25 20:09:08 +10:00
public override void Initialize ( )
2019-06-07 16:15:20 +05:00
{
2021-07-25 20:09:08 +10:00
base . Initialize ( ) ;
2022-01-29 22:45:50 +11:00
2022-02-06 15:59:41 +00:00
InitializeProximity ( ) ;
2022-01-29 22:45:50 +11:00
InitializeOnUse ( ) ;
2022-04-22 02:54:39 -04:00
InitializeSignal ( ) ;
2022-05-29 02:29:10 -04:00
InitializeTimedCollide ( ) ;
2022-01-29 22:45:50 +11:00
2022-02-06 15:59:41 +00:00
SubscribeLocalEvent < TriggerOnCollideComponent , StartCollideEvent > ( OnTriggerCollide ) ;
2022-05-29 02:29:10 -04:00
SubscribeLocalEvent < TriggerOnActivateComponent , ActivateInWorldEvent > ( OnActivate ) ;
2022-07-10 02:28:37 -07:00
SubscribeLocalEvent < TriggerOnStepTriggerComponent , StepTriggeredEvent > ( OnStepTriggered ) ;
2019-06-07 16:15:20 +05:00
2021-07-25 20:09:08 +10:00
SubscribeLocalEvent < DeleteOnTriggerComponent , TriggerEvent > ( HandleDeleteTrigger ) ;
SubscribeLocalEvent < ExplodeOnTriggerComponent , TriggerEvent > ( HandleExplodeTrigger ) ;
SubscribeLocalEvent < FlashOnTriggerComponent , TriggerEvent > ( HandleFlashTrigger ) ;
}
private void HandleExplodeTrigger ( EntityUid uid , ExplodeOnTriggerComponent component , TriggerEvent args )
{
2022-04-01 15:39:26 +13:00
_explosions . TriggerExplosive ( uid , user : args . User ) ;
2022-06-01 01:39:06 -07:00
args . Handled = true ;
2021-07-25 20:09:08 +10:00
}
#region Flash
private void HandleFlashTrigger ( EntityUid uid , FlashOnTriggerComponent component , TriggerEvent args )
2021-09-09 16:20:41 +02:00
{
// TODO Make flash durations sane ffs.
2021-12-03 15:53:09 +01:00
_flashSystem . FlashArea ( uid , args . User , component . Range , component . Duration * 1000f ) ;
2022-06-01 01:39:06 -07:00
args . Handled = true ;
2021-09-09 16:20:41 +02:00
}
2021-07-25 20:09:08 +10:00
#endregion
private void HandleDeleteTrigger ( EntityUid uid , DeleteOnTriggerComponent component , TriggerEvent args )
{
EntityManager . QueueDeleteEntity ( uid ) ;
2022-06-01 01:39:06 -07:00
args . Handled = true ;
2021-07-25 20:09:08 +10:00
}
2022-02-06 15:59:41 +00:00
private void OnTriggerCollide ( EntityUid uid , TriggerOnCollideComponent component , StartCollideEvent args )
2021-07-25 20:09:08 +10:00
{
2022-05-26 21:18:57 -04:00
if ( args . OurFixture . ID = = component . FixtureID )
Trigger ( component . Owner ) ;
2021-07-25 20:09:08 +10:00
}
2022-05-29 02:29:10 -04:00
private void OnActivate ( EntityUid uid , TriggerOnActivateComponent component , ActivateInWorldEvent args )
{
Trigger ( component . Owner , args . User ) ;
2022-06-01 01:39:06 -07:00
args . Handled = true ;
2022-05-29 02:29:10 -04:00
}
2021-12-07 17:48:49 +01:00
2022-07-10 02:28:37 -07:00
private void OnStepTriggered ( EntityUid uid , TriggerOnStepTriggerComponent component , ref StepTriggeredEvent args )
{
Trigger ( uid , args . Tripper ) ;
}
2022-06-01 01:39:06 -07:00
public bool Trigger ( EntityUid trigger , EntityUid ? user = null )
2021-07-25 20:09:08 +10:00
{
var triggerEvent = new TriggerEvent ( trigger , user ) ;
2022-06-22 09:53:41 +10:00
EntityManager . EventBus . RaiseLocalEvent ( trigger , triggerEvent , true ) ;
2022-06-01 01:39:06 -07:00
return triggerEvent . Handled ;
2021-07-25 20:09:08 +10:00
}
2022-03-25 17:17:29 +13:00
public void HandleTimerTrigger ( EntityUid uid , EntityUid ? user , float delay , float beepInterval , float? initialBeepDelay , SoundSpecifier ? beepSound , AudioParams beepParams )
2021-07-25 20:09:08 +10:00
{
2022-03-25 17:17:29 +13:00
if ( delay < = 0 )
2021-07-25 20:09:08 +10:00
{
2022-03-25 17:17:29 +13:00
RemComp < ActiveTimerTriggerComponent > ( uid ) ;
Trigger ( uid , user ) ;
2021-07-25 20:09:08 +10:00
return ;
}
2022-03-25 17:17:29 +13:00
if ( HasComp < ActiveTimerTriggerComponent > ( uid ) )
return ;
if ( user ! = null )
2021-07-25 20:09:08 +10:00
{
2022-08-07 20:21:56 -03:00
// Check if entity is bomb/mod. grenade/etc
if ( _container . TryGetContainer ( uid , "payload" , out IContainer ? container ) & &
TryComp ( container . ContainedEntities . First ( ) , out ChemicalPayloadComponent ? chemicalPayloadComponent ) )
{
// If a beaker is missing, the entity won't explode, so no reason to log it
if ( ! TryComp ( chemicalPayloadComponent ? . BeakerSlotA . Item , out SolutionContainerManagerComponent ? beakerA ) | |
! TryComp ( chemicalPayloadComponent ? . BeakerSlotB . Item , out SolutionContainerManagerComponent ? beakerB ) )
return ;
_adminLogger . Add ( LogType . Trigger ,
$"{ToPrettyString(user.Value):user} started a {delay} second timer trigger on entity {ToPrettyString(uid):timer}, which contains [{string.Join(" , ", beakerA.Solutions.Values.First())}] in one beaker and [{string.Join(" , ", beakerB.Solutions.Values.First())}] in the other." ) ;
}
else
{
_adminLogger . Add ( LogType . Trigger ,
$"{ToPrettyString(user.Value):user} started a {delay} second timer trigger on entity {ToPrettyString(uid):timer}" ) ;
}
2022-03-25 17:17:29 +13:00
}
else
{
2022-05-28 23:41:17 -07:00
_adminLogger . Add ( LogType . Trigger ,
2022-03-25 17:17:29 +13:00
$"{delay} second timer trigger started on entity {ToPrettyString(uid):timer}" ) ;
}
var active = AddComp < ActiveTimerTriggerComponent > ( uid ) ;
active . TimeRemaining = delay ;
active . User = user ;
active . BeepParams = beepParams ;
active . BeepSound = beepSound ;
active . BeepInterval = beepInterval ;
active . TimeUntilBeep = initialBeepDelay = = null ? active . BeepInterval : initialBeepDelay . Value ;
if ( TryComp < AppearanceComponent > ( uid , out var appearance ) )
appearance . SetData ( TriggerVisuals . VisualState , TriggerVisualState . Primed ) ;
2019-06-07 16:15:20 +05:00
}
2022-02-06 15:59:41 +00:00
public override void Update ( float frameTime )
{
base . Update ( frameTime ) ;
UpdateProximity ( frameTime ) ;
2022-03-25 17:17:29 +13:00
UpdateTimer ( frameTime ) ;
2022-05-29 02:29:10 -04:00
UpdateTimedCollide ( frameTime ) ;
2022-03-25 17:17:29 +13:00
}
private void UpdateTimer ( float frameTime )
{
HashSet < EntityUid > toRemove = new ( ) ;
foreach ( var timer in EntityQuery < ActiveTimerTriggerComponent > ( ) )
{
timer . TimeRemaining - = frameTime ;
timer . TimeUntilBeep - = frameTime ;
if ( timer . TimeRemaining < = 0 )
{
Trigger ( timer . Owner , timer . User ) ;
toRemove . Add ( timer . Owner ) ;
continue ;
}
if ( timer . BeepSound = = null | | timer . TimeUntilBeep > 0 )
continue ;
timer . TimeUntilBeep + = timer . BeepInterval ;
var filter = Filter . Pvs ( timer . Owner , entityManager : EntityManager ) ;
2022-06-12 19:45:47 -04:00
SoundSystem . Play ( timer . BeepSound . GetSound ( ) , filter , timer . Owner , timer . BeepParams ) ;
2022-03-25 17:17:29 +13:00
}
foreach ( var uid in toRemove )
{
RemComp < ActiveTimerTriggerComponent > ( uid ) ;
// In case this is a re-usable grenade, un-prime it.
if ( TryComp < AppearanceComponent > ( uid , out var appearance ) )
appearance . SetData ( TriggerVisuals . VisualState , TriggerVisualState . Unprimed ) ;
}
2022-02-06 15:59:41 +00:00
}
2019-06-07 16:15:20 +05:00
}
2020-07-06 14:27:03 -07:00
}