add beehave
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
@tool
|
||||
@icon("../../icons/simple_parallel.svg")
|
||||
class_name SimpleParallelComposite extends Composite
|
||||
|
||||
## Simple Parallel nodes will attampt to execute all chidren at same time and
|
||||
## can only have exactly two children. First child as primary node, second
|
||||
## child as secondary node.
|
||||
## This node will always report primary node's state, and continue tick while
|
||||
## primary node return 'RUNNING'. The state of secondary node will be ignored
|
||||
## and executed like a subtree.
|
||||
## If primary node return 'SUCCESS' or 'FAILURE', this node will interrupt
|
||||
## secondary node and return primary node's result.
|
||||
## If this node is running under delay mode, it will wait seconday node
|
||||
## finish its action after primary node terminates.
|
||||
|
||||
#how many times should secondary node repeat, zero means loop forever
|
||||
@export var secondary_node_repeat_count: int = 0
|
||||
|
||||
#wether to wait secondary node finish its current action after primary node finished
|
||||
@export var delay_mode: bool = false
|
||||
|
||||
var delayed_result := SUCCESS
|
||||
var main_task_finished: bool = false
|
||||
var secondary_node_running: bool = false
|
||||
var secondary_node_repeat_left: int = 0
|
||||
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings: PackedStringArray = super._get_configuration_warnings()
|
||||
|
||||
if get_child_count() != 2:
|
||||
warnings.append("SimpleParallel should have exactly two child nodes.")
|
||||
|
||||
if not get_child(0) is ActionLeaf:
|
||||
warnings.append("SimpleParallel should have an action leaf node as first child node.")
|
||||
|
||||
return warnings
|
||||
|
||||
|
||||
func tick(actor, blackboard: Blackboard):
|
||||
for c in get_children():
|
||||
var node_index: int = c.get_index()
|
||||
if node_index == 0 and not main_task_finished:
|
||||
if c != running_child:
|
||||
c.before_run(actor, blackboard)
|
||||
|
||||
var response: int = c.tick(actor, blackboard)
|
||||
if can_send_message(blackboard):
|
||||
BeehaveDebuggerMessages.process_tick(c.get_instance_id(), response, blackboard.get_debug_data())
|
||||
|
||||
delayed_result = response
|
||||
match response:
|
||||
SUCCESS, FAILURE:
|
||||
_cleanup_running_task(c, actor, blackboard)
|
||||
c.after_run(actor, blackboard)
|
||||
main_task_finished = true
|
||||
if not delay_mode:
|
||||
if secondary_node_running:
|
||||
get_child(1).interrupt(actor, blackboard)
|
||||
_reset()
|
||||
return delayed_result
|
||||
RUNNING:
|
||||
running_child = c
|
||||
if c is ActionLeaf:
|
||||
blackboard.set_value("running_action", c, str(actor.get_instance_id()))
|
||||
|
||||
elif node_index == 1:
|
||||
if secondary_node_repeat_count == 0 or secondary_node_repeat_left > 0:
|
||||
if not secondary_node_running:
|
||||
c.before_run(actor, blackboard)
|
||||
var subtree_response = c.tick(actor, blackboard)
|
||||
if subtree_response != RUNNING:
|
||||
secondary_node_running = false
|
||||
c.after_run(actor, blackboard)
|
||||
if delay_mode and main_task_finished:
|
||||
_reset()
|
||||
return delayed_result
|
||||
elif secondary_node_repeat_left > 0:
|
||||
secondary_node_repeat_left -= 1
|
||||
else:
|
||||
secondary_node_running = true
|
||||
|
||||
return RUNNING
|
||||
|
||||
|
||||
func before_run(actor: Node, blackboard: Blackboard) -> void:
|
||||
secondary_node_repeat_left = secondary_node_repeat_count
|
||||
super(actor, blackboard)
|
||||
|
||||
|
||||
func interrupt(actor: Node, blackboard: Blackboard) -> void:
|
||||
if not main_task_finished:
|
||||
get_child(0).interrupt(actor, blackboard)
|
||||
if secondary_node_running:
|
||||
get_child(1).interrupt(actor, blackboard)
|
||||
_reset()
|
||||
super(actor, blackboard)
|
||||
|
||||
|
||||
func after_run(actor: Node, blackboard: Blackboard) -> void:
|
||||
_reset()
|
||||
super(actor, blackboard)
|
||||
|
||||
|
||||
func _reset() -> void:
|
||||
main_task_finished = false
|
||||
secondary_node_running = false
|
||||
|
||||
|
||||
## Changes `running_action` and `running_child` after the node finishes executing.
|
||||
func _cleanup_running_task(finished_action: Node, actor: Node, blackboard: Blackboard):
|
||||
var blackboard_name = str(actor.get_instance_id())
|
||||
if finished_action == running_child:
|
||||
running_child = null
|
||||
if finished_action == blackboard.get_value("running_action", null, blackboard_name):
|
||||
blackboard.set_value("running_action", null, blackboard_name)
|
||||
|
||||
|
||||
func get_class_name() -> Array[StringName]:
|
||||
var classes := super()
|
||||
classes.push_back(&"SimpleParallelComposite")
|
||||
return classes
|
||||
Reference in New Issue
Block a user