From a030ffa08aa465cc4d3886b7e8caa29ab8e66c2f Mon Sep 17 00:00:00 2001 From: Evgeniy Kazakov Date: Sun, 7 Nov 2021 18:25:31 +0300 Subject: [PATCH] Replaced most of `make_atomizer` IO logic with vscript --- root/scripts/vscripts/community/functions.nut | 58 ++---- .../community/utility/atomizer_logic.nut | 192 ++++++++++++++++++ 2 files changed, 205 insertions(+), 45 deletions(-) create mode 100644 root/scripts/vscripts/community/utility/atomizer_logic.nut diff --git a/root/scripts/vscripts/community/functions.nut b/root/scripts/vscripts/community/functions.nut index 513886b5..c41c9b5c 100644 --- a/root/scripts/vscripts/community/functions.nut +++ b/root/scripts/vscripts/community/functions.nut @@ -1482,56 +1482,24 @@ function make_atomizer( user_strTargetname, user_strModel, user_intKillTimer ) { - SpawnEntityFromTable( "filter_activator_model", - { - targetname = g_UpdateName + user_strTargetname + "_filter", - Negated = "Allow entities that match criteria", - model = user_strModel - } ); - - SpawnEntityFromTable( "logic_timer", - { - targetname = g_UpdateName + user_strTargetname + "_timer", - StartDisabled = 1, - RefireTime = user_intKillTimer, - connections = - { - OnTimer = - { - cmd1 = g_UpdateName + "_atomizer_monitoredStartGlowing0-1" - cmd2 = g_UpdateName + "_atomizer_monitoredKill5-1" - cmd3 = "!selfDisable0-1" - cmd4 = "!selfResetTimer0-1" - } - } - } ); - - local trigger = SpawnEntityFromTable( "trigger_multiple", + local hndlTrigger = SpawnEntityFromTable( "trigger_multiple", { targetname = g_UpdateName + user_strTargetname + "_trigmult", origin = StringToVector_Valve( user_strOrigin, " " ), - spawnflags = 8, - filtername = g_UpdateName + user_strTargetname + "_filter", - connections = - { - OnStartTouch = - { - cmd1 = g_UpdateName + user_strTargetname + "_timer" + "Enable0-1" - cmd2 = "!activatorAddOutputtargetname " + g_UpdateName + "_atomizer_monitored0-1" - cmd3 = "!selfAddOutputspawnflags 00-1" - } - OnEndTouch = - { - cmd1 = g_UpdateName + user_strTargetname + "_timer" + "Disable0-1" - cmd2 = g_UpdateName + user_strTargetname + "_timer" + "ResetTimer0-1" - cmd3 = "!selfAddOutputspawnflags 80-1" - } - } + spawnflags = 8, // SF_TRIGGER_ALLOW_PHYSICS + vscripts = "community/utility/atomizer_logic" } ); - DoEntFire( "!self", "AddOutput", "mins -50 -50 0", 0, null, trigger ); - DoEntFire( "!self", "AddOutput", "maxs 50 50 100", 0, null, trigger ); - DoEntFire( "!self", "AddOutput", "solid 2", 0, null, trigger ); + DoEntFire( "!self", "AddOutput", "mins -50 -50 0", 0, null, hndlTrigger ); + DoEntFire( "!self", "AddOutput", "maxs 50 50 100", 0, null, hndlTrigger ); + DoEntFire( "!self", "AddOutput", "solid 2", 0, null, hndlTrigger ); + + hndlTrigger.ValidateScriptScope(); + local hndlScope = hndlTrigger.GetScriptScope(); + if ( hndlScope != null && "InitAtomizer" in hndlScope ) + { + hndlScope.InitAtomizer( user_strModel, user_intKillTimer ); + } if ( developer() > 0 ) { diff --git a/root/scripts/vscripts/community/utility/atomizer_logic.nut b/root/scripts/vscripts/community/utility/atomizer_logic.nut new file mode 100644 index 00000000..4a13d6dd --- /dev/null +++ b/root/scripts/vscripts/community/utility/atomizer_logic.nut @@ -0,0 +1,192 @@ +local flDeleteDelay = 30; + +local bIsAtomizerInitialized = false; + +function InitAtomizer( path, deleteAfter ) +{ + if ( !bIsAtomizerInitialized ) + { + bIsAtomizerInitialized = true; + + self.ConnectOutput( "OnStartTouch", "HandleObjectTouch" ); + self.ConnectOutput( "OnEndTouch", "HandleObjectEndTouch" ); + } + + AddModelToFilter( path ); + flDeleteDelay = deleteAfter; +} + +function ShutdownAtomizer() +{ + if ( !bIsAtomizerInitialized ) + { + return; + } + + bIsAtomizerInitialized = false; + + self.DisconnectOutput( "OnStartTouch", "HandleObjectTouch" ); + self.DisconnectOutput( "OnEndTouch", "HandleObjectEndTouch" ); +} + +local rgFilterModels = []; + +function AddModelToFilter( path ) +{ + if ( path == null ) + { + return; + } + + if ( rgFilterModels.find( path ) == null ) + { + rgFilterModels.push( path ); + } +} + +function RemoveModelFromFilter( path ) +{ + local index = rgFilterModels.find( path ); + if ( index != null ) + { + rgFilterModels.remove( index ); + } +} + +local rgTrackedObjects = []; + +local FindTrackedObject = function ( hndlEntity ) +{ + if ( hndlEntity == null ) + { + return null; + } + + foreach ( index, tblObjectData in rgTrackedObjects ) + { + if ( tblObjectData.m_hndlEntity == hndlEntity ) + { + return index; + } + } + + return null; +} + +local RemoveTrackedObjectByIndex = function ( index ) +{ + local objectData = rgTrackedObjects[ index ]; + + local hndlEntity = objectData.m_hndlEntity; + if ( hndlEntity != null && hndlEntity.IsValid() && !objectData.rawin( "m_flGlowAfter" ) ) + { + DoEntFire( "!caller", "StopGlowing", "", 0, hndlEntity, hndlEntity ); + } + + rgTrackedObjects.remove( index ); + + if ( rgTrackedObjects.len() == 0 ) + { + // BUG: Unable to remove think callback from callback + DoEntFire( "!caller", "CallScriptFunction", "MaybeStopThinking", 0, self, self ); + } +} + +// Callbacks +function HandleObjectTouch() +{ + // Msg( "HandleObjectTouch() " ); + // printl( activator ); + + // Validate model + if ( rgFilterModels.len() > 0 && rgFilterModels.find( activator.GetModelName() ) == null ) + { + return; + } + + local index = FindTrackedObject( activator ); + if ( index != null ) + { + // Reset tracking data for object + RemoveTrackedObjectByIndex( index ); + } + + local tblObjectData = + { + m_hndlEntity = activator.weakref(), + m_flDeleteAfterTime = Time() + flDeleteDelay, + }; + + if ( flDeleteDelay >= 5 ) + { + tblObjectData.rawset( "m_flGlowAfter", tblObjectData.m_flDeleteAfterTime - 5 ); + } + + rgTrackedObjects.push( tblObjectData ); + + if ( rgTrackedObjects.len() == 1 ) + { + // Msg( "Starting to Think()! \n" ); + // NOTE: Timer frequency depends on sv_script_think_interval value + AddThinkToEnt( self, "HandleAtomizerThink" ); + } +} + +function HandleObjectEndTouch() +{ + // Msg( "HandleObjectEndTouch() " ); + // printl( activator ); + + local index = FindTrackedObject( activator ); + if ( index != null ) + { + RemoveTrackedObjectByIndex( index ); + } +} + +function HandleAtomizerThink() +{ + local flTime = Time(); + + foreach ( index, tblObjectData in rgTrackedObjects ) + { + local hndlEntity = tblObjectData.m_hndlEntity; + if ( hndlEntity == null || !hndlEntity.IsValid() ) + { + // Msg( "Dead entity handle!\n" ); + RemoveTrackedObjectByIndex( index ); + + continue; + } + + if ( tblObjectData.m_flDeleteAfterTime < flTime ) + { + con_comment( "atomizer_logic: Removing blocking entity " + hndlEntity.tostring() ); + + RemoveTrackedObjectByIndex( index ); + hndlEntity.Kill(); + + continue; + } + + if ( tblObjectData.rawin( "m_flGlowAfter" ) && tblObjectData.rawget( "m_flGlowAfter" ) < flTime ) + { + // Msg( "StartGlowing() " ); + // printl( hndlEntity ); + + DoEntFire( "!caller", "StartGlowing", "", 0, hndlEntity, hndlEntity ); + + tblObjectData.rawdelete( "m_flGlowAfter" ); + } + } +} + +function MaybeStopThinking() +{ + // Since DoEntFire is asynchronous, we can't guarantee safety to remove think func - do the check first + if ( rgTrackedObjects.len() == 0 ) + { + // Msg( "Stopped Think()-ing! \n" ); + AddThinkToEnt( self, null ); + } +}