diff --git a/korman/nodes/node_avatar.py b/korman/nodes/node_avatar.py index 69a552b..7103fa7 100644 --- a/korman/nodes/node_avatar.py +++ b/korman/nodes/node_avatar.py @@ -45,11 +45,11 @@ class PlasmaSittingBehaviorNode(PlasmaNodeBase, bpy.types.Node): def draw_buttons_ext(self, context, layout): layout.prop_menu_enum(self, "approach") - def get_key(self, exporter, tree, so): - return exporter.mgr.find_create_key(plSittingModifier, name=self.create_key_name(tree), so=so) + def get_key(self, exporter, so): + return exporter.mgr.find_create_key(plSittingModifier, name=self.key_name, so=so) - def export(self, exporter, tree, bo, so): - sitmod = self.get_key(exporter, tree, so).object + def export(self, exporter, bo, so): + sitmod = self.get_key(exporter, so).object for flag in self.approach: sitmod.miscFlags |= getattr(plSittingModifier, flag) for key in self.find_outputs("satisfies"): diff --git a/korman/nodes/node_conditions.py b/korman/nodes/node_conditions.py index 6e2aaba..0ac2fe6 100644 --- a/korman/nodes/node_conditions.py +++ b/korman/nodes/node_conditions.py @@ -44,12 +44,12 @@ class PlasmaClickableNode(PlasmaNodeVariableInput, bpy.types.Node): layout.prop_search(self, "clickable", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "bounds") - def export(self, exporter, tree, parent_bo, parent_so): - clickable_bo, clickable_so = self._get_objects(exporter, tree, parent_so) + def export(self, exporter, parent_bo, parent_so): + clickable_bo, clickable_so = self._get_objects(exporter, parent_so) if clickable_bo is None: clickable_bo = parent_bo - name = self.create_key_name(tree) + name = self.key_name interface = exporter.mgr.find_create_key(plInterfaceInfoModifier, name=name, so=clickable_so).object logicmod = exporter.mgr.find_create_key(plLogicModifier, name=name, so=clickable_so) interface.addIntfKey(logicmod) @@ -84,31 +84,31 @@ class PlasmaClickableNode(PlasmaNodeVariableInput, bpy.types.Node): logicmod.addCondition(activator.key) logicmod.setLogicFlag(plLogicModifier.kLocalElement, True) logicmod.cursor = plCursorChangeMsg.kCursorPoised - logicmod.notify = self.generate_notify_msg(exporter, tree, parent_so, "satisfies") + logicmod.notify = self.generate_notify_msg(exporter, parent_so, "satisfies") # If we have a region attached, let it convert. region = self.find_input("region", "PlasmaClickableRegionNode") if region is not None: - region.convert_subcondition(exporter, tree, clickable_bo, clickable_so, logicmod) + region.convert_subcondition(exporter, clickable_bo, clickable_so, logicmod) # Hand things off to the FaceTarget socket which does things nicely for us face_target = self.find_input_socket("facing") - face_target.convert_subcondition(exporter, tree, clickable_bo, clickable_so, logicmod) + face_target.convert_subcondition(exporter, clickable_bo, clickable_so, logicmod) - def get_key(self, exporter, tree, parent_so): + def get_key(self, exporter, parent_so): # careful... we really make lots of keys... - clickable_bo, clickable_so = self._get_objects(exporter, tree, parent_so) - key = exporter.mgr.find_create_key(plLogicModifier, name=self.create_key_name(tree), so=clickable_so) + clickable_bo, clickable_so = self._get_objects(exporter, parent_so) + key = exporter.mgr.find_create_key(plLogicModifier, name=self.key_name, so=clickable_so) return key - def _get_objects(self, exporter, tree, parent_so): + def _get_objects(self, exporter, parent_so): # First: look up the clickable mesh. if it is not specified, then it's this BO. # We do this because we might be exporting from a BO that is not actually the clickable object. # Case: sitting modifier (exports from sit position empty) if self.clickable: clickable_bo = bpy.data.objects.get(self.clickable, None) if clickable_bo is None: - self.raise_error("invalid Clickable object: '{}'".format(self.clickable), tree) + self.raise_error("invalid Clickable object: '{}'".format(self.clickable)) clickable_so = exporter.mgr.find_create_object(plSceneObject, bl=clickable_bo) return (clickable_bo, clickable_so) else: @@ -141,11 +141,11 @@ class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node): layout.prop_search(self, "region", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "bounds") - def convert_subcondition(self, exporter, tree, parent_bo, parent_so, logicmod): + def convert_subcondition(self, exporter, parent_bo, parent_so, logicmod): # REMEMBER: parent_so doesn't have to be the actual region scene object... region_bo = bpy.data.objects.get(self.region, None) if region_bo is None: - self.raise_error("invalid Region object: '{}'".format(self.region), tree) + self.raise_error("invalid Region object: '{}'".format(self.region)) region_so = exporter.mgr.find_create_key(plSceneObject, bl=region_bo).object # Try to figure out the appropriate bounds type for the region.... @@ -163,7 +163,7 @@ class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node): # one detector for many unrelated logic mods. However, LogicMods and Conditions appear to # assume they pwn each other... so we need a unique detector. This detector must be attached # as a modifier to the region's SO however. - name = self.create_key_name(tree) + name = self.key_name detector_key = exporter.mgr.find_create_key(plObjectInVolumeDetector, name=name, so=region_so) detector = detector_key.object detector.addReceiver(logicmod.key) @@ -216,7 +216,7 @@ class PlasmaFacingTargetSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket): layout.prop(self, "allow_simple", text="") layout.label(text) - def convert_subcondition(self, exporter, tree, bo, so, logicmod): + def convert_subcondition(self, exporter, bo, so, logicmod): assert not self.is_output if not self.enable_condition: return @@ -225,12 +225,12 @@ class PlasmaFacingTargetSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket): if self.simple_mode: directional = True tolerance = 45 - name = "{}_SimpleFacing".format(self.node.create_key_name(tree)) + name = "{}_SimpleFacing".format(self.node.key_name) elif self.is_linked: node = self.links[0].from_node directional = node.directional tolerance = node.tolerance - name = node.create_key_name(tree) + name = node.key_name else: # This is a programmer failure, so we need a traceback. raise RuntimeError("Tried to export an unused PlasmaFacingTargetSocket") @@ -311,28 +311,28 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node): layout.prop_search(self, "region", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "bounds") - def export(self, exporter, tree, bo, so): - interface = exporter.mgr.add_object(plInterfaceInfoModifier, name=self.create_key_name(tree), so=so) + def export(self, exporter, bo, so): + interface = exporter.mgr.add_object(plInterfaceInfoModifier, name=self.key_name, so=so) # Region Enters enter_simple = self.find_input_socket("enter").allow enter_settings = self.find_input("enter", "PlasmaVolumeReportNode") if enter_simple or enter_settings is not None: - key = self._export_volume_event(exporter, tree, bo, so, plVolumeSensorConditionalObject.kTypeEnter, enter_settings) + key = self._export_volume_event(exporter, bo, so, plVolumeSensorConditionalObject.kTypeEnter, enter_settings) interface.addIntfKey(key) # Region Exits exit_simple = self.find_input_socket("exit").allow exit_settings = self.find_input("exit", "PlasmaVolumeReportNode") if exit_simple or exit_settings is not None: - key = self._export_volume_event(exporter, tree, bo, so, plVolumeSensorConditionalObject.kTypeExit, exit_settings) + key = self._export_volume_event(exporter, bo, so, plVolumeSensorConditionalObject.kTypeExit, exit_settings) interface.addIntfKey(key) # Don't forget to export the physical object itself! # [trollface.jpg] phys_bo = bpy.data.objects.get(self.region, None) if phys_bo is None: - self.raise_error("invalid Region object: '{}'".format(self.region), tree) + self.raise_error("invalid Region object: '{}'".format(self.region)) simIface, physical = exporter.physics.generate_physical(phys_bo, so, self.bounds, "{}_VolumeSensor".format(bo.name)) physical.memberGroup = plSimDefs.kGroupDetector @@ -341,18 +341,18 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node): if "dynamics" in self.report_on: physical.reportGroup |= 1 << plSimDefs.kGroupDynamic - def _export_volume_event(self, exporter, tree, bo, so, event, settings): + def _export_volume_event(self, exporter, bo, so, event, settings): if event == plVolumeSensorConditionalObject.kTypeEnter: suffix = "Enter" else: suffix = "Exit" - theName = "{}_{}_{}".format(tree.name, self.name, suffix) + theName = "{}_{}_{}".format(self.id_data.name, self.name, suffix) print(" [LogicModifier '{}']".format(theName)) logicKey = exporter.mgr.find_create_key(plLogicModifier, name=theName, so=so) logicmod = logicKey.object logicmod.setLogicFlag(plLogicModifier.kMultiTrigger, True) - logicmod.notify = self.generate_notify_msg(exporter, tree, so, "satisfies") + logicmod.notify = self.generate_notify_msg(exporter, so, "satisfies") # Now, the detector objects print(" [ObjectInVolumeDetector '{}']".format(theName)) diff --git a/korman/nodes/node_core.py b/korman/nodes/node_core.py index 81099aa..358cd75 100644 --- a/korman/nodes/node_core.py +++ b/korman/nodes/node_core.py @@ -20,24 +20,21 @@ from PyHSPlasma import plMessage, plNotifyMsg from ..exporter import ExportError class PlasmaNodeBase: - def create_key_name(self, tree): - return "{}_{}".format(tree.name, self.name) - - def generate_notify_msg(self, exporter, tree, so, socket_id, idname=None): + def generate_notify_msg(self, exporter, so, socket_id, idname=None): notify = plNotifyMsg() notify.BCastFlags = (plMessage.kNetPropagate | plMessage.kLocalPropagate) for i in self.find_outputs(socket_id, idname): - key = i.get_key(exporter, tree, so) + key = i.get_key(exporter, so) if key is None: exporter.report.warn(" '{}' Node '{}' doesn't expose a key. It won't be triggered by '{}'!".format(i.bl_idname, i.name, self.name), indent=3) else: notify.addReceiver(key) return notify - def get_key(self, exporter, tree, so): + def get_key(self, exporter, so): return None - def export(self, exporter, tree, bo, so): + def export(self, exporter, bo, so): pass def find_input(self, key, idname=None): @@ -98,7 +95,11 @@ class PlasmaNodeBase: def harvest_actors(self): return set() - def link_input(self, tree, node, out_key, in_key): + @property + def key_name(self): + return "{}_{}".format(self.id_data.name, self.name) + + def link_input(self, node, out_key, in_key): """Links a given Node's output socket to a given input socket on this Node""" if isinstance(in_key, str): in_socket = self.find_input_socket(in_key) @@ -108,9 +109,9 @@ class PlasmaNodeBase: out_socket = node.find_output_socket(out_key) else: out_socket = out_key - link = tree.links.new(in_socket, out_socket) + link = self.id_data.links.new(in_socket, out_socket) - def link_output(self, tree, node, out_key, in_key): + def link_output(self, node, out_key, in_key): """Links a given Node's input socket to a given output socket on this Node""" if isinstance(in_key, str): in_socket = node.find_input_socket(in_key) @@ -120,14 +121,14 @@ class PlasmaNodeBase: out_socket = self.find_output_socket(out_key) else: out_socket = out_key - link = tree.links.new(in_socket, out_socket) + link = self.id_data.links.new(in_socket, out_socket) @classmethod def poll(cls, context): return (context.bl_idname == "PlasmaNodeTree") - def raise_error(self, message, tree): - final = "Plasma Node Tree '{}' Node '{}': {}".format(tree.name, self.name, message) + def raise_error(self, message): + final = "Plasma Node Tree '{}' Node '{}': {}".format(self.id_data.name, self.name, message) raise ExportError(final) @property @@ -167,7 +168,7 @@ class PlasmaNodeTree(bpy.types.NodeTree): def export(self, exporter, bo, so): # just pass it off to each node for node in self.nodes: - node.export(exporter, self, bo, so) + node.export(exporter, bo, so) def harvest_actors(self): actors = set() diff --git a/korman/nodes/node_messages.py b/korman/nodes/node_messages.py index f109aa8..182c45a 100644 --- a/korman/nodes/node_messages.py +++ b/korman/nodes/node_messages.py @@ -150,24 +150,24 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): layout.prop(self, "event") - def convert_callback_message(self, exporter, tree, so, msg, target, wait): + def convert_callback_message(self, exporter, so, msg, target, wait): cb = plEventCallbackMsg() cb.addReceiver(target) cb.event = globals()[self.event] cb.user = wait msg.addCallback(cb) - def convert_message(self, exporter, tree, so): + def convert_message(self, exporter, so): msg = plAnimCmdMsg() # We're either sending this off to an AGMasterMod or a LayerAnim if self.anim_type == "OBJECT": obj = bpy.data.objects.get(self.object_name, None) if obj is None: - self.raise_error("invalid object: '{}'".format(self.object_name), tree) + self.raise_error("invalid object: '{}'".format(self.object_name)) anim = obj.plasma_modifiers.animation if not anim.enabled: - self.raise_error("invalid animation", tree) + self.raise_error("invalid animation") group = obj.plasma_modifiers.animation_group if group.enabled: # we might be controlling more than one animation. isn't that cute? @@ -181,10 +181,10 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): else: material = bpy.data.materials.get(self.material_name, None) if material is None: - self.raise_error("invalid material: '{}'".format(self.material_name), tree) + self.raise_error("invalid material: '{}'".format(self.material_name)) tex_slot = material.texture_slots.get(self.texture_name, None) if tex_slot is None: - self.raise_error("invalid texture: '{}'".format(self.texture_name), tree) + self.raise_error("invalid texture: '{}'".format(self.texture_name)) name = "{}_{}_LayerAnim".format(self.material_name, self.texture_name) target = exporter.mgr.find_create_key(plLayerAnimation, name=name, so=so) if target is None: @@ -240,7 +240,7 @@ class PlasmaEnableMsgNode(PlasmaMessageNode, bpy.types.Node): options={"ENUM_FLAG"}, default={"kAudible", "kDrawable", "kPhysical"}) - def convert_message(self, exporter, tree, so): + def convert_message(self, exporter, so): msg = plEnableMsg() target_bo = bpy.data.objects.get(self.object_name, None) if target_bo is None: @@ -291,12 +291,12 @@ class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): description="Player can reverse the OneShot", default=False) - def convert_callback_message(self, exporter, tree, so, msg, target, wait): + def convert_callback_message(self, exporter, so, msg, target, wait): msg.addCallback(self.marker, target, wait) - def convert_message(self, exporter, tree, so): + def convert_message(self, exporter, so): msg = plOneShotMsg() - msg.addReceiver(self.get_key(exporter, tree, so)) + msg.addReceiver(self.get_key(exporter, so)) return msg def draw_buttons(self, context, layout): @@ -308,8 +308,8 @@ class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): layout.prop_search(self, "pos", bpy.data, "objects", icon="EMPTY_DATA") layout.prop(self, "seek") - def export(self, exporter, tree, bo, so): - oneshotmod = self.get_key(exporter, tree, so).object + def export(self, exporter, bo, so): + oneshotmod = self.get_key(exporter, so).object oneshotmod.animName = self.animation oneshotmod.drivable = self.drivable oneshotmod.reversable = self.reversable @@ -317,12 +317,12 @@ class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): oneshotmod.noSeek = self.seek == "NONE" oneshotmod.seekDuration = 1.0 - def get_key(self, exporter, tree, so): - name = self.create_key_name(tree) + def get_key(self, exporter, so): + name = self.key_name if self.pos: bo = bpy.data.objects.get(self.pos, None) if bo is None: - raise ExportError("Node '{}' in '{}' specifies an invalid Position Empty".format(self.name, tree.name)) + raise ExportError("Node '{}' in '{}' specifies an invalid Position Empty".format(self.name, self.id_data.name)) pos_so = exporter.mgr.find_create_object(plSceneObject, bl=bo) return exporter.mgr.find_create_key(plOneShotMod, name=name, so=pos_so) else: @@ -357,11 +357,11 @@ class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node): def draw_buttons(self, context, layout): layout.prop(self, "delay") - def convert_callback_message(self, exporter, tree, so, msg, target, wait): + def convert_callback_message(self, exporter, so, msg, target, wait): msg.addReceiver(target) msg.ID = wait - def convert_message(self, exporter, tree, so): + def convert_message(self, exporter, so): msg = plTimerCallbackMsg() msg.time = self.delay return msg @@ -384,7 +384,7 @@ class PlasmaFootstepSoundMsgNode(PlasmaMessageNode, bpy.types.Node): def draw_buttons(self, context, layout): layout.prop(self, "surface") - def convert_message(self, exporter, tree, so): + def convert_message(self, exporter, so): msg = plArmatureEffectStateMsg() msg.BCastFlags |= (plMessage.kPropagateToModifiers | plMessage.kNetPropagate) msg.surface = footstep_surface_ids[self.surface] diff --git a/korman/nodes/node_responder.py b/korman/nodes/node_responder.py index 2b9989d..343b8da 100644 --- a/korman/nodes/node_responder.py +++ b/korman/nodes/node_responder.py @@ -45,11 +45,11 @@ class PlasmaResponderNode(PlasmaNodeVariableInput, bpy.types.Node): layout.prop(self, "detect_untrigger") layout.prop(self, "no_ff_sounds") - def get_key(self, exporter, tree, so): - return exporter.mgr.find_create_key(plResponderModifier, name=self.create_key_name(tree), so=so) + def get_key(self, exporter, so): + return exporter.mgr.find_create_key(plResponderModifier, name=self.key_name, so=so) - def export(self, exporter, tree, bo, so): - responder = self.get_key(exporter, tree, so).object + def export(self, exporter, bo, so): + responder = self.get_key(exporter, so).object if not bo.plasma_net.manual_sdl: responder.setExclude("Responder") @@ -83,7 +83,7 @@ class PlasmaResponderNode(PlasmaNodeVariableInput, bpy.types.Node): # Convert the Responder states stateMgr = ResponderStateMgr(self, responder) for stateNode in self.find_outputs("states", "PlasmaResponderStateNode"): - stateNode.convert_state(exporter, tree, so, stateMgr) + stateNode.convert_state(exporter, so, stateMgr) stateMgr.save() def update(self): @@ -107,7 +107,7 @@ class PlasmaResponderStateNode(PlasmaNodeVariableInput, bpy.types.Node): def draw_buttons(self, context, layout): layout.prop(self, "default_state") - def convert_state(self, exporter, tree, so, stateMgr): + def convert_state(self, exporter, so, stateMgr): idx, state, converted = stateMgr.get_state(self) # No sanity checking here. Hopefully nothing crazy has happened in the UI. @@ -122,7 +122,7 @@ class PlasmaResponderStateNode(PlasmaNodeVariableInput, bpy.types.Node): toIdx, toState, converted = stateMgr.get_state(toStateNode) state.switchToState = toIdx if not converted: - toStateNode.convert_state(exporter, tree, so, stateMgr) + toStateNode.convert_state(exporter, so, stateMgr) class CommandMgr: def __init__(self): @@ -152,7 +152,7 @@ class PlasmaResponderStateNode(PlasmaNodeVariableInput, bpy.types.Node): for i in self.find_outputs("cmds", "PlasmaResponderCommandNode"): # slight optimization--commands attached to states can't wait on other commands # namely because it's impossible to wait on a command that doesn't exist... - i.convert_command(exporter, tree, so, stateMgr.responder, commands) + i.convert_command(exporter, so, stateMgr.responder, commands) commands.save(state) def update(self): @@ -181,14 +181,14 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): self.outputs.new("PlasmaMessageSocket", "Message", "msg").link_limit = 1 self.outputs.new("PlasmaRespCommandSocket", "Trigger", "trigger") - def convert_command(self, exporter, tree, so, responder, commandMgr, waitOn=-1): + def convert_command(self, exporter, so, responder, commandMgr, waitOn=-1): # If this command has no message, there is no need to export it... msgNode = self.find_output("msg") if msgNode is not None: idx, command = commandMgr.add_command(self, waitOn) # Finally, convert our message... - msg = msgNode.convert_message(exporter, tree, so) + msg = msgNode.convert_message(exporter, so) if msg.sender is None: msg.sender = responder.key msg.BCastFlags |= plMessage.kLocalPropagate @@ -198,7 +198,7 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): haveChildren = self.find_output("trigger", "PlasmaResponderCommandNode") is not None if haveChildren and msgNode.has_callbacks: childWaitOn = commandMgr.add_wait(idx) - msgNode.convert_callback_message(exporter, tree, so, msg, responder.key, childWaitOn) + msgNode.convert_callback_message(exporter, so, msg, responder.key, childWaitOn) else: childWaitOn = waitOn command.msg = msg @@ -208,7 +208,7 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): # NOTE: would be incredibly stupid to do this if we're not waiting on anything to complete if childWaitOn != -1: for child in self.find_outputs("trigger"): - key = child.get_key(exporter, tree, so) + key = child.get_key(exporter, so) if key is None: continue logicmod = key.object @@ -229,7 +229,7 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): # Export any child commands for i in self.find_outputs("trigger", "PlasmaResponderCommandNode"): - i.convert_command(exporter, tree, so, responder, commandMgr, childWaitOn) + i.convert_command(exporter, so, responder, commandMgr, childWaitOn) class PlasmaRespCommandSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket): diff --git a/korman/properties/modifiers/avatar.py b/korman/properties/modifiers/avatar.py index cd9a7a3..65ed2a2 100644 --- a/korman/properties/modifiers/avatar.py +++ b/korman/properties/modifiers/avatar.py @@ -83,7 +83,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz): # Clickable clickable = nodes.new("PlasmaClickableNode") - clickable.link_output(tree, sittingmod, "satisfies", "condition") + clickable.link_output(sittingmod, "satisfies", "condition") clickable.clickable = self.clickable_obj clickable.bounds = find_modifier(self.clickable_obj, "collision").bounds @@ -91,7 +91,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz): region_phys = find_modifier(self.region_obj, "collision") if region_phys is not None: region = nodes.new("PlasmaClickableRegionNode") - region.link_output(tree, clickable, "satisfies", "region") + region.link_output(clickable, "satisfies", "region") region.name = "ClickableAvRegion" region.region = self.region_obj region.bounds = region_phys.bounds @@ -99,7 +99,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz): # Facing Target (optional) if self.facing_enabled: facing = nodes.new("PlasmaFacingTargetNode") - facing.link_output(tree, clickable, "satisfies", "facing") + facing.link_output(clickable, "satisfies", "facing") facing.name = "FacingClickable" facing.directional = True facing.tolerance = self.facing_degrees diff --git a/korman/properties/modifiers/region.py b/korman/properties/modifiers/region.py index aca77d9..297800c 100644 --- a/korman/properties/modifiers/region.py +++ b/korman/properties/modifiers/region.py @@ -97,16 +97,16 @@ class PlasmaFootstepRegion(PlasmaModifierProperties, PlasmaModifierLogicWiz): # Responder respmod = nodes.new("PlasmaResponderNode") respmod.name = "Resp" - respmod.link_input(tree, volsens, "satisfies", "condition") + respmod.link_input(volsens, "satisfies", "condition") respstate = nodes.new("PlasmaResponderStateNode") - respstate.link_input(tree, respmod, "states", "condition") + respstate.link_input(respmod, "states", "condition") respstate.default_state = True respcmd = nodes.new("PlasmaResponderCommandNode") - respcmd.link_input(tree, respstate, "cmds", "whodoneit") + respcmd.link_input(respstate, "cmds", "whodoneit") # ArmatureEffectStateMsg msg = nodes.new("PlasmaFootstepSoundMsgNode") - msg.link_input(tree, respcmd, "msg", "sender") + msg.link_input(respcmd, "msg", "sender") msg.surface = self.surface