@@ -395,6 +395,108 @@ def simple_mode(self):
395395 return (not self .is_linked and not self .is_output )
396396
397397
398+ class PlasmaLinkEventNode (PlasmaNodeBase , bpy .types .Node ):
399+ bl_category = "CONDITIONS"
400+ bl_idname = "PlasmaLinkEventNode"
401+ bl_label = "Link Event"
402+
403+ trigger_for = EnumProperty (
404+ name = "Trigger For" ,
405+ items = [
406+ ("Me" , "Local Player" , "Trigger only for the local player" ),
407+ ("NPCs" , "NPCs" , "Trigger for NPCs (eg quabs)" ),
408+ ("Player Avatars" , "Player Avatars" , "Trigger for player controlled avatars" ),
409+ ("Everyone" , "Everyone" , "Trigger for all avatars" ),
410+ ],
411+ default = "Me" ,
412+ options = set ()
413+ )
414+ trigger_on = EnumProperty (
415+ name = "Trigger On" ,
416+ items = [
417+ ("Spawn" , "Avatar Spawns" , "Trigger when an avatar spawns" ),
418+ ("Link" , "Avatar Links" , "Trigger when an avatar links" ),
419+ ],
420+ default = "Spawn" ,
421+ options = set ()
422+ )
423+ trigger_direction = EnumProperty (
424+ name = "Trigger Direction" ,
425+ items = [
426+ ("In" , "In" , "Trigger when the avatar links/spawns into the Age" ),
427+ ("Out" , "Out" , "Trigger when the avatar links/spawns out of the Age" ),
428+ ],
429+ default = "In" ,
430+ options = set ()
431+ )
432+ trigger_at = EnumProperty (
433+ name = "Trigger At" ,
434+ items = [
435+ ("Start" , "Event Start" , "Trigger when the interesting event begins" ),
436+ ("End" , "Event End" , "Trigger when the interesting event ends" ),
437+ ],
438+ default = "Start" ,
439+ options = set ()
440+ )
441+
442+ output_sockets : dict [str , dict [str , Any ]] = {
443+ "satisfies" : {
444+ "text" : "Satisfies" ,
445+ "type" : "PlasmaConditionSocket" ,
446+ "valid_link_sockets" : {"PlasmaConditionSocket" , "PlasmaPythonFileNodeSocket" },
447+ },
448+ }
449+
450+ def draw_buttons (self , context , layout ):
451+ combo = (self .trigger_for , self .trigger_on , self .trigger_direction )
452+
453+ layout .alert = combo == ("Me" , "Spawn" , "Out" )
454+ layout .prop (self , "trigger_for" )
455+ layout .alert = False
456+
457+ layout .prop (self , "trigger_on" )
458+ layout .prop (self , "trigger_direction" )
459+ layout .prop (self , "trigger_at" )
460+
461+ def get_key (self , exporter : Exporter , so ) -> plKey [plLogicModifier ]:
462+ return self ._find_create_key (plLogicModifier , exporter , so = so )
463+
464+ def export (self , exporter : Exporter , bo , so ) -> None :
465+ combo = (self .trigger_for , self .trigger_on , self .trigger_direction )
466+ if combo == ("Me" , "Spawn" , "Out" ):
467+ self .raise_error ("Cannot trigger when the local player spawns out" )
468+
469+ # There is no class in the engine that will fire when someone links in. There are messages,
470+ # though, and they all get to Python in one way or another. So, to fire an event on link
471+ # or spawn, we're going to use a helper script xLinkEventTrigger. It will send a notification
472+ # to a plActivatorActivatorConditionalObject, which can trigger a MultiTrigger LogicMod.
473+ # From there, any other node you could possibly want will be triggered, like responders
474+ # or other PFMs (eg to set SDL variables).
475+ #
476+ # The xLinkEventTrigger Python script does support firing responders directly, but that
477+ # would require extra book-keeping to set up - Responder nodes can hook directly to the
478+ # Responder attribute while other nodes need the activator. It's easier to just let the
479+ # activator/logicmod drive everything. If someone wants to fire a Responder directly, they
480+ # can just draw those nodes manually.
481+ activator = self ._find_create_object (plActivatorActivatorConditionalObject , exporter , so = so )
482+ logicmod = self ._find_create_object (plLogicModifier , exporter , so = so )
483+ logicmod .addCondition (activator .key )
484+ logicmod .notify = self .generate_notify_msg (exporter , so , "satisfies" )
485+ logicmod .setLogicFlag (plLogicModifier .kMultiTrigger , True )
486+ logicmod .setLogicFlag (plLogicModifier .kLocalElement , True )
487+
488+ pfm = self ._find_create_object (plPythonFileMod , exporter , so = so )
489+ self ._add_py_parameter (pfm , 1 , plPythonParameter .kActivator , activator .key )
490+ self ._add_py_parameter (pfm , 100 , plPythonParameter .kString , f"{ self .trigger_on } { self .trigger_direction } " )
491+ self ._add_py_parameter (pfm , 101 , plPythonParameter .kString , self .trigger_for )
492+ self ._add_py_parameter (pfm , 102 , plPythonParameter .kString , self .trigger_at )
493+ pfm .filename = "xLinkEventTrigger"
494+
495+ @property
496+ def export_once (self ):
497+ return True
498+
499+
398500class PlasmaVolumeReportNode (PlasmaNodeBase , bpy .types .Node ):
399501 bl_category = "CONDITIONS"
400502 bl_idname = "PlasmaVolumeReportNode"
0 commit comments