aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut318
1 files changed, 318 insertions, 0 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut b/Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut
new file mode 100644
index 00000000..c5e026b3
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/_script_triggers.gnut
@@ -0,0 +1,318 @@
+
+untyped
+
+globalize_all_functions
+
+// flags defaults to player only
+entity function CreateTriggerRadiusMultiple( vector origin, float radius, array<entity> ents = [], int flags = TRIG_FLAG_PLAYERONLY, float top = 16384.0, float bottom = -16384.0 )
+{
+ return _CreateScriptCylinderTriggerInternal( origin, radius, flags, ents, top, bottom )
+}
+
+// flags defaults to player only
+entity function CreateTriggerRadiusOnce( vector origin, float radius, array<entity> ents = [], int flags = TRIG_FLAG_PLAYERONLY )
+{
+ return _CreateScriptCylinderTriggerInternal( origin, radius, flags | TRIG_FLAG_ONCE, ents, null, null )
+}
+
+entity function CreateScriptCylinderTrigger( vector origin, float radius, float ornull top = null, float ornull bottom = null )
+{
+ return _CreateScriptCylinderTriggerInternal( origin, radius, TRIG_FLAG_PLAYERONLY | TRIG_FLAG_START_DISABLED, [], top, bottom )
+}
+
+entity function _CreateScriptCylinderTriggerInternal( vector origin, float radius, int flags, array<entity> ents, float ornull top, float ornull bottom )
+{
+ entity trigger = CreateScriptRef( origin, < 0.0, 0.0, 0.0 > )
+
+
+ if ( flags & TRIG_FLAG_START_DISABLED )
+ trigger.e.scriptTriggerData.enabled = false
+ else
+ trigger.e.scriptTriggerData.enabled = true
+ trigger.e.scriptTriggerData.radius = radius
+
+ trigger.e.scriptTriggerData.top = 16384.0
+
+ if ( top != null )
+ trigger.e.scriptTriggerData.top = origin.z + expect float( top )
+
+ trigger.e.scriptTriggerData.bottom = -16384.0
+ if ( bottom != null )
+ trigger.e.scriptTriggerData.bottom = origin.z + expect float( bottom )
+
+ trigger.e.scriptTriggerData.flags = flags
+ trigger.e.scriptTriggerData.managedEntArrayHandle = -1
+
+ if ( ents.len() )
+ {
+ trigger.e.scriptTriggerData.flags = (flags | TRIG_FLAG_EXCLUSIVE)
+ trigger.e.scriptTriggerData.managedEntArrayHandle = CreateScriptManagedEntArray()
+
+ foreach ( ent in ents )
+ AddToScriptManagedEntArray( trigger.e.scriptTriggerData.managedEntArrayHandle, ent )
+ }
+
+ if ( flags & TRIG_FLAG_DEVDRAW )
+ DebugDrawTrigger( origin, radius, RandomInt( 255 ), RandomInt( 255 ), RandomInt( 255 ) )
+
+ thread CylinderTriggerThink( trigger )
+
+ return trigger
+}
+
+void function ScriptTriggerSetEnabled( entity trigger, bool state )
+{
+ trigger.e.scriptTriggerData.enabled = state
+}
+
+void function CylinderTriggerThink( entity triggerEnt )
+{
+ //Ensures that any callbacks the user sets are in place when the user spawns.
+ WaitFrame()
+
+ bool wasEnabled = triggerEnt.e.scriptTriggerData.enabled
+ int flags = triggerEnt.e.scriptTriggerData.flags
+
+ while ( IsValid( triggerEnt ) )
+ {
+ if ( !triggerEnt.e.scriptTriggerData.enabled )
+ {
+ if ( wasEnabled )
+ {
+ array<entity> entitiesToRemove // build an array since looping through a table and removing elements is undefined
+ foreach( ent in triggerEnt.e.scriptTriggerData.entities )
+ {
+ entitiesToRemove.append( ent )
+ }
+
+ foreach ( ent in entitiesToRemove )
+ {
+ ScriptTriggerRemoveEntity( triggerEnt, ent )
+ }
+
+ Assert( !triggerEnt.e.scriptTriggerData.entities.len() )
+ }
+ }
+ else
+ {
+ array<entity> entities
+ if ( flags & TRIG_FLAG_EXCLUSIVE )
+ {
+ entities = GetScriptManagedEntArray( triggerEnt.e.scriptTriggerData.managedEntArrayHandle )
+ // all of the entites from this array are gone, this trigger is of no use
+ if ( !entities.len() )
+ {
+ triggerEnt.Kill_Deprecated_UseDestroyInstead()
+ return
+ }
+ }
+ else if ( flags & TRIG_FLAG_PLAYERONLY )
+ {
+ entities = GetPlayerArray()
+ }
+ else if ( flags & TRIG_FLAG_NPCONLY )
+ {
+ entities = GetNPCArray()
+ }
+ else
+ {
+ entities = GetPlayerArray()
+ entities.extend( GetNPCArray() )
+ entities.extend( GetPlayerDecoyArray() )
+ }
+
+ foreach ( ent in entities )
+ {
+ if ( !IsAlive( ent ) )
+ {
+ if ( ent in triggerEnt.e.scriptTriggerData.entities )
+ ScriptTriggerRemoveEntity( triggerEnt, ent )
+ continue
+ }
+
+ if ( ent.IsPlayer() && ent.IsPhaseShifted() && (flags & TRIG_FLAG_NO_PHASE_SHIFT) )
+ {
+ if ( ent in triggerEnt.e.scriptTriggerData.entities )
+ ScriptTriggerRemoveEntity( triggerEnt, ent )
+ continue
+ }
+
+ vector entityOrg = ent.GetOrigin()
+
+ if ( Distance2D( entityOrg, triggerEnt.GetOrigin() ) < triggerEnt.e.scriptTriggerData.radius )
+ {
+ if ( entityOrg.z > triggerEnt.e.scriptTriggerData.top )
+ continue
+
+ if ( entityOrg.z + 72.0 < triggerEnt.e.scriptTriggerData.bottom ) //72 is magic number for height of players. Should account for height of NPCs
+ continue
+
+ if ( (flags & TRIG_FLAG_NOCONTEXTBUSY) && !ent.IsPlayerDecoy() && ent.ContextAction_IsBusy() ) //This should probably be ContextAction_IsActive()
+ continue
+
+ if ( !(ent in triggerEnt.e.scriptTriggerData.entities) )
+ {
+ ScriptTriggerAddEntity( triggerEnt, ent )
+ if ( flags & TRIG_FLAG_ONCE )
+ {
+ WaitEndFrame()
+ triggerEnt.Kill_Deprecated_UseDestroyInstead()
+ return
+ }
+ }
+ }
+ else if ( ent in triggerEnt.e.scriptTriggerData.entities )
+ {
+ ScriptTriggerRemoveEntity( triggerEnt, ent )
+ }
+ }
+ }
+
+ wasEnabled = triggerEnt.e.scriptTriggerData.enabled
+ WaitFrame()
+ }
+}
+
+void function ScriptTriggerRemoveEntity( entity triggerEnt, entity ent )
+{
+ Assert( ent in triggerEnt.e.scriptTriggerData.entities )
+
+ foreach ( callbackFunc in triggerEnt.e.scriptTriggerData.leaveCallbacks )
+ {
+ callbackFunc( triggerEnt, ent )
+ }
+
+ delete triggerEnt.e.scriptTriggerData.entities[ent]
+}
+
+void function ScriptTriggerAddEntity( entity triggerEnt, entity ent )
+{
+ Assert( !(ent in triggerEnt.e.scriptTriggerData.entities) )
+
+ triggerEnt.e.scriptTriggerData.entities[ent] <- ent
+
+ foreach ( callbackFunc in triggerEnt.e.scriptTriggerData.enterCallbacks )
+ {
+ callbackFunc( triggerEnt, ent )
+ }
+
+ triggerEnt.Signal( TRIGGER_INTERNAL_SIGNAL )
+
+ thread ScriptTriggerPlayerDisconnectThink( triggerEnt, ent )
+}
+
+void function ScriptTriggerPlayerDisconnectThink( entity triggerEnt, entity ent )
+{
+ triggerEnt.EndSignal( "OnDestroy" )
+ ent.EndSignal( "OnDeath" )
+
+ OnThreadEnd(
+ function() : ( triggerEnt, ent )
+ {
+ if ( !IsValid( ent ) )
+ return
+
+ if ( ent in triggerEnt.e.scriptTriggerData.entities )
+ ScriptTriggerRemoveEntity( triggerEnt, ent )
+ }
+ )
+
+ ent.WaitSignal( "OnDestroy" )
+}
+
+array<entity> function GetAllEntitiesInTrigger( entity trigger )
+{
+ array<entity> ents
+ foreach ( ent in trigger.e.scriptTriggerData.entities )
+ {
+ ents.append( ent )
+ }
+
+ return ents
+}
+
+void function AddCallback_ScriptTriggerEnter( entity trigger, void functionref( entity, entity ) callbackFunc )
+{
+ trigger.e.scriptTriggerData.enterCallbacks.append( callbackFunc )
+}
+
+void function AddCallback_ScriptTriggerLeave( entity trigger, void functionref( entity, entity ) callbackFunc )
+{
+ trigger.e.scriptTriggerData.leaveCallbacks.append( callbackFunc )
+}
+
+/*
+void function thing()
+{
+ RegisterSignal( "TriggerGetOutThink" )
+
+ array<entity> targets = GetEntArrayByScriptName( "fling_target" )
+
+ foreach ( target in targets )
+ {
+ entity trigger = CreateEntity( "trigger_cylinder" )
+ trigger.SetRadius( 128 )
+ trigger.SetAboveHeight( 64 ) //Still not quite a sphere, will see if close enough
+ trigger.SetBelowHeight( 32 )
+ trigger.SetOrigin( target.GetOrigin() )
+ trigger.ConnectOutput( "OnStartTouch", TriggerGetOutStartTouch )
+ DispatchSpawn( trigger )
+ }
+}
+*/
+void function TriggerGetOutStartTouch( entity trigger, entity ent, entity caller, var value )
+{
+ if ( !ent.IsPlayer() )
+ return
+
+ if ( ent.IsTitan() )
+ return
+
+ if ( !ent.IsAlive() )
+ return
+
+ thread TriggerGetOutThink( trigger, ent )
+}
+
+void function TriggerGetOutThink( entity trigger, entity player )
+{
+ const float FALL_OFF_SPEED_MIN = 100
+ const float FALL_OFF_SPEED_MAX = 300
+ const float FALL_OFF_ACCEL = 300
+ const float FALL_OFF_INTERVAL = 0.1
+
+ while ( IsAlive( player ) && trigger.IsTouching( player ) )
+ {
+ if ( player.IsOnGround() )
+ {
+ vector vel = player.GetVelocity()
+
+ float len = vel.Length2D()
+ while ( len < 1.0 )
+ {
+ vel.x = RandomFloatRange( -100, 100 )
+ vel.y = RandomFloatRange( -100, 100 )
+ len = vel.Length2D()
+ }
+
+ if ( len < FALL_OFF_SPEED_MIN )
+ {
+ float scale = FALL_OFF_SPEED_MIN / len
+ vel.x *= scale
+ vel.y *= scale
+ }
+ else if ( len < FALL_OFF_SPEED_MAX )
+ {
+ float newlen = len + FALL_OFF_INTERVAL * FALL_OFF_ACCEL
+ newlen = min( newlen, FALL_OFF_SPEED_MAX )
+ float scale = newlen / len
+ vel.x *= scale
+ vel.y *= scale
+ }
+
+ player.SetVelocity( vel )
+ }
+
+ WaitFrame()
+ }
+}