mirror of
https://github.com/tonytins/citylimits
synced 2025-06-26 01:44:42 -04:00
Behavior Tree addon
This commit is contained in:
parent
5de5a0c315
commit
5fa863114a
50 changed files with 1762 additions and 3 deletions
8
addons/beehave/nodes/beehave_node.gd
Normal file
8
addons/beehave/nodes/beehave_node.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
extends BeehaveTree
|
||||
|
||||
class_name BeehaveNode, "../icons/action.svg"
|
||||
|
||||
enum { SUCCESS, FAILURE, RUNNING }
|
||||
|
||||
func tick(actor, blackboard):
|
||||
pass
|
84
addons/beehave/nodes/beehave_root.gd
Normal file
84
addons/beehave/nodes/beehave_root.gd
Normal file
|
@ -0,0 +1,84 @@
|
|||
extends BeehaveTree
|
||||
|
||||
class_name BeehaveRoot, "../icons/tree.svg"
|
||||
|
||||
const Blackboard = preload("../blackboard.gd")
|
||||
const SUCCESS = 0
|
||||
const FAILURE = 1
|
||||
const RUNNING = 2
|
||||
|
||||
enum ProcessMode {
|
||||
PHYSICS_PROCESS,
|
||||
IDLE,
|
||||
MANUAL
|
||||
}
|
||||
|
||||
export (ProcessMode) var process_mode = ProcessMode.PHYSICS_PROCESS setget set_process_mode
|
||||
export (bool) var enabled = true
|
||||
|
||||
export (NodePath) var actor_node_path
|
||||
|
||||
var actor : Node
|
||||
|
||||
onready var blackboard = Blackboard.new()
|
||||
|
||||
func _ready():
|
||||
if self.get_child_count() != 1:
|
||||
push_error("Beehave error: Root %s should have one child (NodePath: %s)" % [self.name, self.get_path()])
|
||||
disable()
|
||||
return
|
||||
|
||||
actor = get_parent()
|
||||
if actor_node_path:
|
||||
actor = get_node(actor_node_path)
|
||||
|
||||
set_process_mode(self.process_mode)
|
||||
|
||||
func _process(delta):
|
||||
tick(delta)
|
||||
|
||||
func _physics_process(delta):
|
||||
tick(delta)
|
||||
|
||||
func tick(delta):
|
||||
blackboard.set("delta", delta)
|
||||
|
||||
var status = self.get_child(0).tick(actor, blackboard)
|
||||
|
||||
if status != RUNNING:
|
||||
blackboard.set("running_action", null)
|
||||
|
||||
func get_running_action():
|
||||
if blackboard.has("running_action"):
|
||||
return blackboard.get("running_action")
|
||||
return null
|
||||
|
||||
func get_last_condition():
|
||||
if blackboard.has("last_condition"):
|
||||
return blackboard.get("last_condition")
|
||||
return null
|
||||
|
||||
func get_last_condition_status():
|
||||
if blackboard.has("last_condition_status"):
|
||||
var status = blackboard.get("last_condition_status")
|
||||
if status == SUCCESS:
|
||||
return "SUCCESS"
|
||||
elif status == FAILURE:
|
||||
return "FAILURE"
|
||||
else:
|
||||
return "RUNNING"
|
||||
return ""
|
||||
|
||||
func enable():
|
||||
self.enabled = true
|
||||
set_process_mode(self.process_mode)
|
||||
|
||||
func disable():
|
||||
self.enabled = false
|
||||
set_process(self.enabled)
|
||||
set_physics_process(self.enabled)
|
||||
|
||||
func set_process_mode(value):
|
||||
process_mode = value
|
||||
set_process(process_mode == ProcessMode.IDLE)
|
||||
set_physics_process(process_mode == ProcessMode.PHYSICS_PROCESS)
|
3
addons/beehave/nodes/beehave_tree.gd
Normal file
3
addons/beehave/nodes/beehave_tree.gd
Normal file
|
@ -0,0 +1,3 @@
|
|||
extends Node
|
||||
|
||||
class_name BeehaveTree
|
8
addons/beehave/nodes/composites/composite.gd
Normal file
8
addons/beehave/nodes/composites/composite.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
extends BeehaveNode
|
||||
|
||||
class_name Composite, "../../icons/category_composite.svg"
|
||||
|
||||
|
||||
func _ready():
|
||||
if self.get_child_count() < 1:
|
||||
push_error("BehaviorTree Error: Composite %s should have at least one child (NodePath: %s)" % [self.name, self.get_path()])
|
18
addons/beehave/nodes/composites/selector.gd
Normal file
18
addons/beehave/nodes/composites/selector.gd
Normal file
|
@ -0,0 +1,18 @@
|
|||
extends Composite
|
||||
|
||||
class_name SelectorComposite, "../../icons/selector.svg"
|
||||
|
||||
func tick(actor, blackboard):
|
||||
for c in get_children():
|
||||
var response = c.tick(actor, blackboard)
|
||||
|
||||
if c is ConditionLeaf:
|
||||
blackboard.set("last_condition", c)
|
||||
blackboard.set("last_condition_status", response)
|
||||
|
||||
if response != FAILURE:
|
||||
if c is ActionLeaf and response == RUNNING:
|
||||
blackboard.set("running_action", c)
|
||||
return response
|
||||
|
||||
return FAILURE
|
33
addons/beehave/nodes/composites/selector_star.gd
Normal file
33
addons/beehave/nodes/composites/selector_star.gd
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Special implementation of a selector that will
|
||||
# "wait" for running nodes and will not re-attempt
|
||||
# to execute previous nodes until that node is either
|
||||
# FAILED or SUCCEEDED
|
||||
extends Composite
|
||||
|
||||
class_name SelectorStarComposite, "../../icons/selector_star.svg"
|
||||
|
||||
|
||||
var last_execution_index = 0
|
||||
|
||||
func tick(actor, blackboard):
|
||||
for c in get_children():
|
||||
if c.get_index() < last_execution_index:
|
||||
continue
|
||||
|
||||
var response = c.tick(actor, blackboard)
|
||||
|
||||
if c is ConditionLeaf:
|
||||
blackboard.set("last_condition", c)
|
||||
blackboard.set("last_condition_status", response)
|
||||
|
||||
if response != FAILURE:
|
||||
if c is ActionLeaf and response == RUNNING:
|
||||
blackboard.set("running_action", c)
|
||||
if response == SUCCESS:
|
||||
last_execution_index = 0
|
||||
return response
|
||||
else:
|
||||
last_execution_index += 1
|
||||
|
||||
last_execution_index = 0
|
||||
return FAILURE
|
18
addons/beehave/nodes/composites/sequence.gd
Normal file
18
addons/beehave/nodes/composites/sequence.gd
Normal file
|
@ -0,0 +1,18 @@
|
|||
extends Composite
|
||||
|
||||
class_name SequenceComposite, "../../icons/sequencer.svg"
|
||||
|
||||
func tick(actor, blackboard):
|
||||
for c in get_children():
|
||||
var response = c.tick(actor, blackboard)
|
||||
|
||||
if c is ConditionLeaf:
|
||||
blackboard.set("last_condition", c)
|
||||
blackboard.set("last_condition_status", response)
|
||||
|
||||
if response != SUCCESS:
|
||||
if c is ActionLeaf and response == RUNNING:
|
||||
blackboard.set("running_action", c)
|
||||
return response
|
||||
|
||||
return SUCCESS
|
35
addons/beehave/nodes/composites/sequence_star.gd
Normal file
35
addons/beehave/nodes/composites/sequence_star.gd
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Special implementation of sequencer who will execute
|
||||
# successful nodes only once until all nodes were successful
|
||||
|
||||
extends Composite
|
||||
|
||||
class_name SequenceStarComposite, "../../icons/sequencer_star.svg"
|
||||
|
||||
var successful_index = 0
|
||||
|
||||
func tick(actor, blackboard):
|
||||
for c in get_children():
|
||||
if c.get_index() < successful_index:
|
||||
continue
|
||||
|
||||
var response = c.tick(actor, blackboard)
|
||||
|
||||
if c is ConditionLeaf:
|
||||
blackboard.set("last_condition", c)
|
||||
blackboard.set("last_condition_status", response)
|
||||
|
||||
if response != SUCCESS:
|
||||
if response == FAILURE:
|
||||
successful_index = 0
|
||||
if c is ActionLeaf and response == RUNNING:
|
||||
blackboard.set("running_action", c)
|
||||
return response
|
||||
else:
|
||||
successful_index += 1
|
||||
|
||||
if successful_index == get_child_count():
|
||||
successful_index = 0
|
||||
return SUCCESS
|
||||
else:
|
||||
successful_index = 0
|
||||
return FAILURE
|
8
addons/beehave/nodes/decorators/decorator.gd
Normal file
8
addons/beehave/nodes/decorators/decorator.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
extends BeehaveNode
|
||||
|
||||
class_name Decorator, "../../icons/category_decorator.svg"
|
||||
|
||||
|
||||
func _ready():
|
||||
if self.get_child_count() != 1:
|
||||
push_error("Beehave Error: Decorator %s should have only one child (NodePath: %s)" % [self.name, self.get_path()])
|
11
addons/beehave/nodes/decorators/failer.gd
Normal file
11
addons/beehave/nodes/decorators/failer.gd
Normal file
|
@ -0,0 +1,11 @@
|
|||
extends Decorator
|
||||
|
||||
class_name AlwaysFailDecorator, "../../icons/fail.svg"
|
||||
|
||||
|
||||
func tick(action, blackboard):
|
||||
for c in get_children():
|
||||
var response = c.tick(action, blackboard)
|
||||
if response == RUNNING:
|
||||
return RUNNING
|
||||
return FAILURE
|
17
addons/beehave/nodes/decorators/inverter.gd
Normal file
17
addons/beehave/nodes/decorators/inverter.gd
Normal file
|
@ -0,0 +1,17 @@
|
|||
extends Decorator
|
||||
|
||||
class_name InverterDecorator, "../../icons/inverter.svg"
|
||||
|
||||
|
||||
func tick(action, blackboard):
|
||||
for c in get_children():
|
||||
var response = c.tick(action, blackboard)
|
||||
|
||||
if response == SUCCESS:
|
||||
return FAILURE
|
||||
if response == FAILURE:
|
||||
return SUCCESS
|
||||
|
||||
if c is Leaf and response == RUNNING:
|
||||
blackboard.set("running_action", c)
|
||||
return RUNNING
|
19
addons/beehave/nodes/decorators/limiter.gd
Normal file
19
addons/beehave/nodes/decorators/limiter.gd
Normal file
|
@ -0,0 +1,19 @@
|
|||
extends Decorator
|
||||
|
||||
class_name LimiterDecorator, "../../icons/limiter.svg"
|
||||
|
||||
onready var cache_key = 'limiter_%s' % self.get_instance_id()
|
||||
|
||||
export (float) var max_count = 0
|
||||
|
||||
func tick(actor, blackboard):
|
||||
var current_count = blackboard.get(cache_key)
|
||||
|
||||
if current_count == null:
|
||||
current_count = 0
|
||||
|
||||
if current_count <= max_count:
|
||||
blackboard.set(cache_key, current_count + 1)
|
||||
return self.get_child(0).tick(actor, blackboard)
|
||||
else:
|
||||
return FAILED
|
11
addons/beehave/nodes/decorators/succeeder.gd
Normal file
11
addons/beehave/nodes/decorators/succeeder.gd
Normal file
|
@ -0,0 +1,11 @@
|
|||
extends Decorator
|
||||
|
||||
class_name AlwaysSucceedDecorator, "../../icons/succeed.svg"
|
||||
|
||||
|
||||
func tick(action, blackboard):
|
||||
for c in get_children():
|
||||
var response = c.tick(action, blackboard)
|
||||
if response == RUNNING:
|
||||
return RUNNING
|
||||
return SUCCESS
|
3
addons/beehave/nodes/leaves/action.gd
Normal file
3
addons/beehave/nodes/leaves/action.gd
Normal file
|
@ -0,0 +1,3 @@
|
|||
extends Leaf
|
||||
|
||||
class_name ActionLeaf, "../../icons/action.svg"
|
3
addons/beehave/nodes/leaves/condition.gd
Normal file
3
addons/beehave/nodes/leaves/condition.gd
Normal file
|
@ -0,0 +1,3 @@
|
|||
extends Leaf
|
||||
|
||||
class_name ConditionLeaf, "../../icons/condition.svg"
|
3
addons/beehave/nodes/leaves/leaf.gd
Normal file
3
addons/beehave/nodes/leaves/leaf.gd
Normal file
|
@ -0,0 +1,3 @@
|
|||
extends BeehaveNode
|
||||
|
||||
class_name Leaf, "../../icons/action.svg"
|
Loading…
Add table
Add a link
Reference in a new issue