Skip to content

Commit c69c4e4

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 c69c4e4

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

korman/nodes/node_conditions.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,105 @@ 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 kMultiTrigger LogicMod with a plActivatorActivatorConditionalObject. LMs forward
473+
# all plNotifyMsgs to their conditions, and plAACO activates on any state==1.0 plNotifyMsg,
474+
# assuming that the LogicMod is not already marked as triggered and all of the other conditions
475+
# say that they're in a valid state. Once that LogicMod fires, anything we want can be fired
476+
# off, like other PFMs or Responders. A potential optimization here is to avoid creation
477+
# of the plAACO/plLM thunk if we only have responders attached.
478+
activator = self._find_create_object(plActivatorActivatorConditionalObject, exporter, so=so)
479+
logicmod = self._find_create_object(plLogicModifier, exporter, so=so)
480+
logicmod.addCondition(activator.key)
481+
logicmod.notify = self.generate_notify_msg(exporter, so, "satisfies")
482+
logicmod.setLogicFlag(plLogicModifier.kMultiTrigger, True)
483+
logicmod.setLogicFlag(plLogicModifier.kLocalElement, True)
484+
485+
pfm = self._find_create_object(plPythonFileMod, exporter, so=so)
486+
self._add_py_parameter(pfm, 1, plPythonParameter.kActivator, activator.key)
487+
self._add_py_parameter(pfm, 100, plPythonParameter.kString, f"{self.trigger_on} {self.trigger_direction}")
488+
self._add_py_parameter(pfm, 101, plPythonParameter.kString, self.trigger_for)
489+
self._add_py_parameter(pfm, 102, plPythonParameter.kString, self.trigger_at)
490+
pfm.filename = "xLinkEventTrigger"
491+
492+
@property
493+
def export_once(self):
494+
return True
495+
496+
398497
class PlasmaVolumeReportNode(PlasmaNodeBase, bpy.types.Node):
399498
bl_category = "CONDITIONS"
400499
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)