Skip to content

Commit 0dc2b48

Browse files
committed
Add link event trigger node.
This is a helper node to abstract away the oddities of dealing with Python File Mods triggering logic. It's hopefully the first of many higher level logic nodes.
1 parent 8ca7c98 commit 0dc2b48

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

korman/nodes/node_conditions.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
398500
class PlasmaVolumeReportNode(PlasmaNodeBase, bpy.types.Node):
399501
bl_category = "CONDITIONS"
400502
bl_idname = "PlasmaVolumeReportNode"

korman/nodes/node_core.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
from ..exporter import Exporter
2929

3030
class PlasmaNodeBase:
31+
def _add_py_parameter(self, pfm: plPythonFileMod, id: int, param_type: int, value) -> None:
32+
param = plPythonParameter()
33+
param.id = id
34+
param.valueType = param_type
35+
param.value = value
36+
pfm.addParameter(param)
37+
3138
def generate_notify_msg(self, exporter: Exporter, so: plSceneObject, socket_id: str, idname: Optional[str] = None) -> plNotifyMsg:
3239
notify = plNotifyMsg()
3340
notify.BCastFlags = (plMessage.kNetPropagate | plMessage.kLocalPropagate)

0 commit comments

Comments
 (0)