├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── addons └── behav_tree_for_groups │ ├── Reaction.gd │ ├── action.svg │ ├── action.svg.import │ ├── action_2d.svg │ ├── action_2d.svg.import │ ├── action_3d.svg │ ├── action_3d.svg.import │ ├── add_agent.gd │ ├── add_agent_at_pos_2d.gd │ ├── add_agent_at_pos_3d.gd │ ├── add_spring_on_contact.gd │ ├── behavior.gd │ ├── behavior.svg │ ├── behavior.svg.import │ ├── behavior_tree_for_groups.gd │ ├── behavior_tree_for_groups.svg │ ├── behavior_tree_for_groups.svg.import │ ├── behavior_tree_for_groups_plugin.gd │ ├── btfg_tools.gd │ ├── change_color.gd │ ├── change_color_random.gd │ ├── clone_agent.gd │ ├── clone_agent_at_pos_2d.gd │ ├── clone_agent_at_pos_3d.gd │ ├── condition.svg │ ├── condition.svg.import │ ├── condition_2d.svg │ ├── condition_2d.svg.import │ ├── condition_3d.svg │ ├── condition_3d.svg.import │ ├── data_plus.gd │ ├── data_set.gd │ ├── delete.gd │ ├── fallback.gd │ ├── fallback.svg │ ├── fallback.svg.import │ ├── field.gd │ ├── force_angular_z.gd │ ├── force_forward.gd │ ├── force_global.gd │ ├── force_radial.gd │ ├── force_random.gd │ ├── force_to_grid_value.gd │ ├── global_data_plus.gd │ ├── global_data_set.gd │ ├── grid2d.gd │ ├── icon.png │ ├── icon.png.import │ ├── if_age_between.gd │ ├── if_age_equals.gd │ ├── if_age_equals_periodic_values.gd │ ├── if_age_equals_values.gd │ ├── if_age_inf.gd │ ├── if_age_sup.gd │ ├── if_collision.gd │ ├── if_data_between.gd │ ├── if_data_equals.gd │ ├── if_data_equals_periodic_values.gd │ ├── if_data_equals_values.gd │ ├── if_data_inf.gd │ ├── if_data_sup.gd │ ├── if_global_data_between.gd │ ├── if_global_data_equals.gd │ ├── if_global_data_inf.gd │ ├── if_global_data_sup.gd │ ├── if_grid_2d_value_inf.gd │ ├── if_grid_2d_value_sup.gd │ ├── if_in_box.gd │ ├── if_mouse_click.gd │ ├── if_no_contact.gd │ ├── if_no_contact_with.gd │ ├── if_proba.gd │ ├── if_state_equals.gd │ ├── if_step_between.gd │ ├── if_time_between.gd │ ├── if_time_inf.gd │ ├── if_time_sup.gd │ ├── new_agent_2d.gd │ ├── new_agent_3d.gd │ ├── new_grid_2d.gd │ ├── parallel.gd │ ├── parallel.svg │ ├── parallel.svg.import │ ├── plugin.cfg │ ├── print_message.gd │ ├── prompt_dialog.gd │ ├── sequential.gd │ ├── sequential.svg │ ├── sequential.svg.import │ ├── set_age.gd │ ├── set_grid_value_2d.gd │ ├── set_state.gd │ ├── stay_in_box.gd │ ├── torque_global.gd │ ├── torque_random.gd │ └── translate_random.gd ├── doc └── behavior_tree_for_groups.pdf ├── examples ├── 2d_tutorial │ ├── agent_2d_0.tscn │ └── main.tscn ├── bacteria_colony │ ├── bact.tscn │ ├── gluc.tscn │ ├── ker.tscn │ ├── main.tscn │ ├── main2.tscn │ └── main3.tscn ├── coag │ ├── coag.tscn │ ├── fibro.tscn │ └── ma_grille.tscn ├── coagulation │ ├── CoaB82.tmp │ ├── CoaFB45.tmp │ ├── FA.tscn │ ├── Thumbs.db │ ├── factors.tscn │ ├── grid_2d_0.tscn │ ├── lesion.png │ ├── lesion.png.import │ ├── lesion.tscn │ ├── main.tscn │ ├── platelet.tscn │ ├── sphere_64x64.png │ └── sphere_64x64.png.import ├── flow_2d │ ├── cell.tscn │ └── main.tscn ├── flow_3d │ ├── .DS_Store │ ├── cell.tscn │ └── main.tscn ├── forest_fire │ ├── fire.tscn │ ├── main.tscn │ ├── tree.tscn │ ├── tree_burned.tscn │ └── tree_in_fire.tscn ├── grid2d │ ├── Agt.tscn │ ├── follower.tscn │ ├── my_ADF0.tmp │ ├── my_grid.tscn │ ├── reaction-diffusion.tscn │ └── reaction_diffusion.tscn └── various │ ├── agent_2d.tscn │ ├── agent_a.tscn │ ├── agent_b.tscn │ ├── agent_c.tscn │ ├── boilings.tscn │ ├── cell_tissue.tscn │ ├── cells_adhesion.tscn │ ├── cicatrisation.tscn │ ├── crowd_circular_mvt.tscn │ ├── crowd_opposite_mvt.tscn │ ├── curie_therapy.tscn │ ├── grid_2d.tscn │ ├── molecule_adhesion.tscn │ ├── mouse_click.tscn │ ├── prey_pred.tscn │ └── test_generic_6dof_joint_3d.tscn ├── project.godot └── screenshots ├── .gdignore ├── BTFG_documentation_front_page.png ├── BTFG_documentation_front_page.png.import ├── behav_tree_for_groups_flow.png ├── behav_tree_for_groups_flow_th.png ├── behav_tree_tor_groups_coag.png ├── behav_tree_tor_groups_coag_th.png ├── behavior_tree_for_groups_forest.png ├── behavior_tree_for_groups_forest_th.png └── icon_big.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | # Godot-specific ignores 5 | .import/ 6 | export.cfg 7 | export_presets.cfg 8 | 9 | # Imported translations (automatically generated from CSV files) 10 | *.translation 11 | 12 | # Mono-specific ignores 13 | .mono/ 14 | data_*/ 15 | mono_crash.*.json 16 | 17 | # Mac specific 18 | .DS_Store/ 19 | .DS_Store 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Pascal Ballet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BehaviorTreeForGroups 2 | ![logo](addons/behav_tree_for_groups/icon.png) 3 | 4 | **[Behavior Tree For Groups](doc/behavior_tree_for_groups.pdf) is an addon for Godot Engine that enables you to create swarms, flocks and multiagent systems using a single behavior tree.** 5 | 6 | **You can easily design collective behaviors without any code by adding groups to your nodes.** 7 | 8 | **Several examples, in 2D or 3D, are available: test them to understand how they work and what can be done** 9 | 10 | [![doc](screenshots/BTFG_documentation_front_page.png)](doc/behavior_tree_for_groups.pdf) 11 | 12 | ## Simple 2D tutorial 13 | ### First, create a new 2D scene 14 | * save it as *main* 15 | ### Second, create a new Agent2D 16 | * Click the + button in your scene tree and Select *NewAgent2D* (you can also create your own RigidBody2D) 17 | * Open the *Agent2D.tscn* automatically generated, and select the *RigidBody* at the root of this scene 18 | * In the inspector, go to the *Node Tab* then go to *Group* and add a new group called *test group* 19 | * Save the *Agent2D* scene 20 | * Go back to your *main* scene 21 | ### Third, create a simple behavior tree 22 | * Click the *plus button* in your *main* scene, then select the node *BehavTreeForGroups* 23 | * Then, add a new child node called *Behavior* 24 | * In the inspector of the newly created node *Behavior*, in the *Group* property, write *test_group*. That means all the nodes having the Group *test_group* will be treated. 25 | * Then, as child of the node *Behavior*, add a new node called *TranslateRandom* 26 | ### Finally, put about 10 *Agent2D* in your *main* scene 27 | * Drag & drop the file *Agent2D* inside your *main* scene 28 | * Execute your program: all the agents having the group *test_group* will move at random 29 | ### Many other nodes exists to create many different behaviors 30 | 31 | ## Simple 3D tutorial 32 | ### Very simple : replace 2D by 3D in the previous example! 33 | * And do not forget to put a camera and a light then execute your program 34 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/Reaction.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | class_name Reaction 3 | 4 | var coef_r1:int = 0 5 | @export var reactive_1:String = "" 6 | var coef_r2:int = 0 7 | @export var reactive_2:String = "" 8 | var coef_r3:int = 0 9 | @export var reactive_3:String = "" 10 | 11 | @export var speed:float = 0.01 12 | 13 | var coef_p1:int = 0 14 | @export var product_1:String = "" 15 | var coef_p2:int = 0 16 | @export var product_2:String = "" 17 | var coef_p3:int = 0 18 | @export var product_3:String = "" 19 | 20 | func extract_coef_field(): 21 | 22 | # reactives 23 | var lst_r1 = reactive_1.split(" ") 24 | if lst_r1.size() == 1: 25 | coef_r1 = 1 26 | reactive_1 = lst_r1[0] 27 | if lst_r1.size() == 2: 28 | coef_r1 = int(lst_r1[0]) 29 | reactive_1 = lst_r1[1] 30 | 31 | var lst_r2 = reactive_2.split(" ") 32 | if lst_r2.size() == 1: 33 | coef_r2 = 1 34 | reactive_2 = lst_r2[0] 35 | if lst_r2.size() == 2: 36 | coef_r2 = int(lst_r2[0]) 37 | reactive_2 = lst_r2[1] 38 | 39 | var lst_r3 = reactive_3.split(" ") 40 | if lst_r3.size() == 1: 41 | coef_r3 = 1 42 | reactive_3 = lst_r3[0] 43 | if lst_r3.size() == 2: 44 | coef_r3 = int(lst_r3[0]) 45 | reactive_3 = lst_r3[1] 46 | 47 | # products 48 | var lst_p1 = product_1.split(" ") 49 | if lst_p1.size() == 1: 50 | coef_p1 = 1 51 | product_1 = lst_p1[0] 52 | if lst_p1.size() == 2: 53 | coef_p1 = int(lst_p1[0]) 54 | product_1 = lst_p1[1] 55 | 56 | var lst_p2 = product_2.split(" ") 57 | if lst_p2.size() == 1: 58 | coef_p2 = 1 59 | product_2 = lst_p2[0] 60 | if lst_p2.size() == 2: 61 | coef_p2 = int(lst_p2[0]) 62 | product_2 = lst_p2[1] 63 | 64 | var lst_p3 = product_3.split(" ") 65 | if lst_p3.size() == 1: 66 | coef_p3 = 1 67 | product_3 = lst_p3[0] 68 | if lst_p3.size() == 2: 69 | coef_p3 = int(lst_p3[0]) 70 | product_3 = lst_p3[1] 71 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 20 | 24 | 25 | 28 | 32 | 33 | 34 | 54 | 56 | Created by potrace 1.15, written by Peter Selinger 2001-2017 57 | 58 | 65 | 66 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c0b5hrdrav62w" 6 | path="res://.godot/imported/action.svg-82397c85d2e85f7b3df5f9f676b99e24.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/action.svg" 14 | dest_files=["res://.godot/imported/action.svg-82397c85d2e85f7b3df5f9f676b99e24.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action_2d.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 20 | 24 | 25 | 28 | 32 | 33 | 34 | 54 | Created by potrace 1.15, written by Peter Selinger 2001-2017 56 | 63 | 64 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action_2d.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cxykedgwukq8c" 6 | path="res://.godot/imported/action_2d.svg-0b5cd9faeb36f82b227527f4596f388d.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/action_2d.svg" 14 | dest_files=["res://.godot/imported/action_2d.svg-0b5cd9faeb36f82b227527f4596f388d.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action_3d.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 20 | 24 | 25 | 28 | 32 | 33 | 34 | 54 | 56 | Created by potrace 1.15, written by Peter Selinger 2001-2017 57 | 58 | 65 | 66 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/action_3d.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dm6qvndrqaw2b" 6 | path="res://.godot/imported/action_3d.svg-eec895205d47be25d61382570512377b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/action_3d.svg" 14 | dest_files=["res://.godot/imported/action_3d.svg-eec895205d47be25d61382570512377b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/add_agent.gd: -------------------------------------------------------------------------------- 1 | ## Dynamically add a new node/agent in the scene 2 | ## at the location of the current node/agent 3 | 4 | @icon("action.svg") 5 | 6 | class_name AddAgent 7 | extends BehaviorTreeForGroups 8 | 9 | #@export var agent_path:String = "" 10 | @export_file("*.tscn") var agent_tscn: String 11 | 12 | var root:Node = null 13 | var new_agent_scene:Resource = null 14 | var new_agent_behaviors:Array = [] 15 | var new_agent_prototype:Node = null 16 | 17 | var btfg:BehaviorTreeForGroups = null 18 | 19 | func biodyn_process(agent) -> bool: 20 | #if agent_tscn.ends_with("_in_fire.tscn") == true: 21 | # print("TOUCH") 22 | 23 | if agent_tscn != "": 24 | # Initilize the Agent to clone 25 | if new_agent_scene == null: 26 | if root == null: 27 | root = get_tree().current_scene 28 | # Get the new Agent 29 | new_agent_scene = load(agent_tscn) 30 | new_agent_prototype = new_agent_scene.instantiate() 31 | # Find ALL its behaviors and put them in the new_agent_behaviors Array 32 | btfg = BTFG.btfg_root 33 | 34 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups 35 | if b is Behavior and b.applies_on_agent(new_agent_prototype): #new_agent_prototype.is_in_group(b.on_group): 36 | # Copy the current behavior to the new_agent_prototype 37 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively 38 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree 39 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent 40 | 41 | # Add of an Agent to the Scene 42 | var nb_agents:int = root.get_child_count() 43 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents: 44 | var spawn = new_agent_prototype.duplicate() 45 | # Put and translate the spawn in the scene 46 | root.add_child(spawn) 47 | if agent.get("transform"): 48 | spawn.translate ( agent.transform.origin ) 49 | else: 50 | spawn.translate ( agent.position ) 51 | return true 52 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/add_agent_at_pos_2d.gd: -------------------------------------------------------------------------------- 1 | ## Dynamically add a new node/agent in the scene 2 | ## at a location chosen 3 | 4 | @icon("action_2d.svg") 5 | 6 | class_name AddAgentAtPos2D 7 | extends BehaviorTreeForGroups 8 | 9 | # exports 10 | @export_file("*.tscn") var agent_tscn: String 11 | @export var relative:bool = true 12 | @export var x:float = 0 13 | @export var y:float = 0 14 | 15 | var root:Node = null 16 | var new_agent_scene:Resource = null 17 | var new_agent_behaviors:Array = [] 18 | var new_agent_prototype:Node = null 19 | 20 | var btfg:BehaviorTreeForGroups = null 21 | 22 | var newpos : Vector2 23 | var rx : float 24 | var ry : float 25 | 26 | func biodyn_process(agent) -> bool: 27 | if agent_tscn != "": 28 | # Initilize the Agent to clone 29 | if new_agent_scene == null: 30 | if root == null: 31 | root = get_tree().current_scene 32 | # Get the new Agent 33 | new_agent_scene = load(agent_tscn) 34 | new_agent_prototype = new_agent_scene.instantiate() 35 | # Find ALL its behaviors and put them in the new_agent_behaviors Array 36 | btfg = BTFG.btfg_root 37 | 38 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups 39 | if b is Behavior and new_agent_prototype.is_in_group(b.on_group): 40 | # Copy the current behavior to the new_agent_prototype 41 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively 42 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree 43 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent 44 | 45 | if relative == true: 46 | rx = x+agent.position.x 47 | ry = y+agent.position.y 48 | newpos = Vector2(rx, ry) 49 | else : 50 | newpos = Vector2(x, y) 51 | # Add of an Agent to the Scene 52 | var nb_agents:int = root.get_child_count() 53 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents: 54 | var spawn = new_agent_prototype.duplicate() 55 | spawn.position = newpos 56 | # Put and translate the spawn in the scene 57 | root.add_child(spawn) 58 | if agent.get("transform"): 59 | spawn.translate ( Vector2(0,0)) 60 | else: 61 | spawn.translate ( agent.position ) 62 | return true 63 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/add_agent_at_pos_3d.gd: -------------------------------------------------------------------------------- 1 | ## Dynamically add a new node/agent in the scene 2 | ## at a location chosen 3 | 4 | @icon("action_3d.svg") 5 | 6 | class_name AddAgentAtPos3D 7 | extends BehaviorTreeForGroups 8 | 9 | #exports 10 | @export_file("*.tscn") var agent_tscn: String 11 | @export var relative:bool = true 12 | @export var x :float = 1 13 | @export var y :float = 1 14 | @export var z :float = 1 15 | 16 | 17 | var root:Node = null 18 | var new_agent_scene:Resource = null 19 | var new_agent_behaviors:Array = [] 20 | var new_agent_prototype:Node = null 21 | 22 | var btfg:BehaviorTreeForGroups = null 23 | 24 | var newpos : Vector3 25 | var rx : float 26 | var ry : float 27 | var rz : float 28 | 29 | 30 | 31 | 32 | func biodyn_process(agent) -> bool: 33 | if agent is RigidBody3D : 34 | 35 | 36 | if agent_tscn != "": 37 | # Initilize the Agent to clone 38 | if new_agent_scene == null: 39 | if root == null: 40 | root = get_tree().current_scene 41 | # Get the new Agent 42 | new_agent_scene = load(agent_tscn) 43 | new_agent_prototype = new_agent_scene.instantiate() 44 | # Find ALL its behaviors and put them in the new_agent_behaviors Array 45 | btfg = BTFG.btfg_root 46 | 47 | for b in btfg.get_children(): # Get ALL the behaviors of BehaviorTreeForGroups 48 | if b is Behavior and new_agent_prototype.is_in_group(b.on_group): 49 | # Copy the current behavior to the new_agent_prototype 50 | var behav_clone:Behavior = b.duplicate(15) # Duplicate the Behavior recursively 51 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT # We can do it because its agent (proto) is NEVER in the scene tree 52 | new_agent_prototype.add_child(behav_clone) # Add the Behavior to the prototype agent 53 | 54 | if relative == true: 55 | rx = x+agent.position.x 56 | ry = y+agent.position.y 57 | rz = z+agent.position.z 58 | newpos = Vector3(rx, ry, rz) 59 | else : 60 | newpos = Vector3(x, y, z) 61 | # Add of an Agent to the Scene 62 | var nb_agents:int = root.get_child_count() 63 | if new_agent_scene != null and nb_agents < BehaviorTreeForGroups.max_agents: 64 | var spawn = new_agent_prototype.duplicate() 65 | spawn.position = newpos 66 | # Put and translate the spawn in the scene 67 | root.add_child(spawn) 68 | if agent.get("transform"): 69 | spawn.translate ( Vector3(0,0,0)) 70 | else: 71 | spawn.translate ( agent.position ) 72 | return true 73 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior.gd: -------------------------------------------------------------------------------- 1 | ## Behavior root node. 2 | ## MUST be a DIRECT child of the BehaviorTreeForGroups Node 3 | ## Works on one specific group 4 | ## Execute all its children, always 5 | ## like a Parallel Node 6 | 7 | @icon("behavior.svg") 8 | 9 | class_name Behavior 10 | extends BehaviorTreeForGroups 11 | 12 | @export var activated:bool = true 13 | #@export var on_group = "" 14 | 15 | func _process(delta): 16 | biodyn_process(get_parent()) 17 | 18 | func biodyn_process(agent:Node)->bool: 19 | # The Behavior Node is a Parallel Node 20 | # It executes all its children, stops after ALL children execution 21 | # Returns True when at least ONE child returns True 22 | if activated == false: 23 | return false 24 | var overall_success:bool = false 25 | for behav in get_children(): 26 | var success = behav.biodyn_process(agent) 27 | if success == true: 28 | overall_success = true 29 | 30 | return overall_success 31 | 32 | func applies_on_agent(n:Node) -> bool: 33 | for gp in self.get_groups(): 34 | if n.is_in_group(gp): 35 | return true 36 | return false 37 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | Created by potrace 1.15, written by Peter Selinger 2001-2017 39 | 44 | 47 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b8vs3hmibsimo" 6 | path="res://.godot/imported/behavior.svg-ac6cd31274dd65cc3e8e145a25b33e4b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/behavior.svg" 14 | dest_files=["res://.godot/imported/behavior.svg-ac6cd31274dd65cc3e8e145a25b33e4b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior_tree_for_groups.gd: -------------------------------------------------------------------------------- 1 | ## Root node of the BehavTreeForGroups plugin. 2 | ## Its DIRECT children MUST be Behavior nodes 3 | 4 | @icon("behavior_tree_for_groups.svg") 5 | 6 | class_name BehaviorTreeForGroups 7 | extends Node 8 | 9 | ## Max number of created agents 10 | static var max_agents:int = 3000 11 | ##Number of agents 12 | static var nb_agents:int = 0 13 | ## Current simulation step 14 | static var simulation_step:int = 0 15 | 16 | var init:bool = false 17 | 18 | func get_class() -> String: 19 | return "BehaviorTreeForGroups" 20 | 21 | func put_all_behaviors(): 22 | # The user will NOT execute BioDyn plugin 23 | if self.process_mode == Node.PROCESS_MODE_DISABLED: 24 | return 25 | 26 | # Put the behaviors INTO ALL agents according to their groups 27 | var root:Node = get_tree().current_scene 28 | for behav in get_children(): # Try to put the current behavior into the right agents 29 | if behav is Behavior and behav.process_mode != Node.PROCESS_MODE_DISABLED: 30 | for agt in root.get_children(): # Test the groups of ALL agents 31 | behav.process_mode = Node.PROCESS_MODE_DISABLED # It becomes Disabled in BioDyn behaviors (attached to no Agent) 32 | var apply_behav:bool = is_behavior_applicable(agt, behav) 33 | if apply_behav == true: #agt.is_in_group(behav.on_group): # the behav is for the agt 34 | var behav_clone:Behavior = behav.duplicate(15) 35 | behav_clone.process_mode = Node.PROCESS_MODE_INHERIT 36 | agt.add_child(behav_clone) #we add the behavior into the agent 37 | if agt.get("btfg_root"): 38 | agt.btfg_root = self 39 | 40 | func is_behavior_applicable(agt, behav)->bool: 41 | for b in behav.get_groups(): 42 | if agt.is_in_group(b): 43 | return true 44 | return false 45 | 46 | func _ready(): 47 | if BTFG.btfg_root == null: 48 | var the_script:Script = get_script() 49 | var script_name:String = "" 50 | if the_script != null: 51 | var script_path:NodePath = the_script.get_path() 52 | var sub:String = script_path.get_concatenated_subnames() 53 | script_name = sub.get_file() 54 | 55 | if script_name == "behavior_tree_for_groups.gd": 56 | BTFG.btfg_root = self 57 | 58 | func _process(delta): 59 | if init == true: # All behaviors have been put into Agents 60 | simulation_step += 1 61 | else: 62 | put_all_behaviors() 63 | init = true 64 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior_tree_for_groups.svg: -------------------------------------------------------------------------------- 1 | 2 | 21 | 40 | 41 | Untitled.svg 43 | 45 | 55 | 57 | 58 | 60 | Untitled.svg 61 | 62 | 63 | 64 | 71 | 78 | 79 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/behavior_tree_for_groups.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cor7dp8jswgqk" 6 | path="res://.godot/imported/behavior_tree_for_groups.svg-333b37a8e7effe0f4965d4e8e34b9393.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/behavior_tree_for_groups.svg" 14 | dest_files=["res://.godot/imported/behavior_tree_for_groups.svg-333b37a8e7effe0f4965d4e8e34b9393.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/btfg_tools.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | class_name BTFG 4 | ## BehavTreeForGroups main node 5 | static var btfg_root:BehaviorTreeForGroups = null 6 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/change_color.gd: -------------------------------------------------------------------------------- 1 | ## Change the color of a node/agent. 2 | 3 | @icon("action.svg") 4 | class_name ChangeColor 5 | extends BehaviorTreeForGroups 6 | 7 | @export var color:Color = Color.CHARTREUSE 8 | 9 | func biodyn_process(agent)->bool: 10 | if agent is RigidBody3D: 11 | # New material 12 | var mat:StandardMaterial3D = StandardMaterial3D.new() 13 | mat.albedo_color = color 14 | # Put the new material 15 | var msh:MeshInstance3D = agent.get_node("MeshInstance3D") 16 | msh.material_override = mat 17 | return true 18 | 19 | if agent is RigidBody2D: 20 | var poly:Polygon2D = agent.get_node("Polygon2D") 21 | poly.color = color 22 | return true 23 | 24 | return false 25 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/change_color_random.gd: -------------------------------------------------------------------------------- 1 | ## Change the color of a node/agent randomly. 2 | 3 | @icon("action.svg") 4 | class_name ChangeColorRandom 5 | extends BehaviorTreeForGroups 6 | 7 | 8 | func biodyn_process(agent)->bool: 9 | if agent is RigidBody3D: 10 | # New material 11 | var mat:StandardMaterial3D = StandardMaterial3D.new() 12 | mat.albedo_color = Color(randf_range(0,1),randf_range(0,1),randf_range(0,1)) 13 | # Put the new material 14 | var msh:MeshInstance3D = agent.get_node("MeshInstance3D") 15 | msh.material_override = mat 16 | return true 17 | 18 | if agent is RigidBody2D: 19 | var poly:Polygon2D = agent.get_node("Polygon2D") 20 | poly.color = Color(randf_range(0,1),randf_range(0,1),randf_range(0,1)) 21 | return true 22 | 23 | return false 24 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/clone_agent.gd: -------------------------------------------------------------------------------- 1 | ## Duplicate the current node/agent 2 | 3 | @icon("action.svg") 4 | 5 | class_name CloneAgent 6 | extends BehaviorTreeForGroups 7 | 8 | func biodyn_process(agent) -> bool: 9 | # Clone agent to the Scene 10 | var nb_agents:int = get_tree().current_scene.get_child_count() 11 | if nb_agents < BehaviorTreeForGroups.max_agents: 12 | var spawn = agent.duplicate(15) 13 | # Put and translate the spawn in the scene 14 | get_tree().current_scene.add_child(spawn) 15 | 16 | return true 17 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/clone_agent_at_pos_2d.gd: -------------------------------------------------------------------------------- 1 | ## Duplicate the current node/agent in a position chosen 2 | 3 | @icon("action_2d.svg") 4 | 5 | class_name CloneAgentAtPos2D 6 | extends BehaviorTreeForGroups 7 | 8 | @export var relative:bool = true 9 | @export var x:float = 0 10 | @export var y:float = 0 11 | 12 | #position 13 | var newpos : Vector2 14 | var rx : float 15 | var ry : float 16 | 17 | func biodyn_process(agent) -> bool: 18 | #create the position of the clone 19 | if agent is RigidBody2D : 20 | if relative == true: 21 | rx = x+agent.position.x 22 | ry = y+agent.position.y 23 | newpos = Vector2(rx, ry) 24 | else : 25 | newpos = Vector2(x, y) 26 | #print(newpos) 27 | # Clone agent to the Scene 28 | var nb_agents:int = get_tree().current_scene.get_child_count() 29 | if nb_agents < BehaviorTreeForGroups.max_agents: 30 | var spawn = agent.duplicate(15) 31 | #assign the position 32 | spawn.position = newpos 33 | # Put and translate the spawn in the scene 34 | get_tree().current_scene.add_child(spawn) 35 | return true 36 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/clone_agent_at_pos_3d.gd: -------------------------------------------------------------------------------- 1 | ## Duplicate the current node/agent in a position chosen 2 | 3 | @icon("action_3d.svg") 4 | 5 | class_name CloneAgentAtPos3D 6 | extends BehaviorTreeForGroups 7 | 8 | @export var relative:bool = true 9 | @export var x :float = 1 10 | @export var y :float = 1 11 | @export var z :float = 1 12 | 13 | #position 14 | var newpos : Vector3 15 | var rx : float 16 | var ry : float 17 | var rz : float 18 | 19 | func biodyn_process(agent) -> bool: 20 | #create the position of the clone 21 | if agent is RigidBody3D : 22 | if relative == true : 23 | rx = x+agent.position.x 24 | ry = y+agent.position.y 25 | rz = z+agent.position.z 26 | newpos = Vector3(rx, ry, rz) 27 | else : 28 | newpos = Vector3(x, y, z) 29 | var nb_agents:int = get_tree().current_scene.get_child_count() 30 | if nb_agents < BehaviorTreeForGroups.max_agents: 31 | var spawn = agent.duplicate(15) 32 | #assign the position 33 | spawn.position = newpos 34 | # Put and translate the spawn in the scene 35 | get_tree().current_scene.add_child(spawn) 36 | return true 37 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | Created by potrace 1.15, written by Peter Selinger 2001-2017 39 | 45 | 46 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://di6h3i6wutt1a" 6 | path="res://.godot/imported/condition.svg-be15db2fc4b79447b8f91834a6bcaf0b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/condition.svg" 14 | dest_files=["res://.godot/imported/condition.svg-be15db2fc4b79447b8f91834a6bcaf0b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition_2d.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | Created by potrace 1.15, written by Peter Selinger 2001-2017 39 | 45 | 46 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition_2d.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dbas35fjgsbwv" 6 | path="res://.godot/imported/condition_2d.svg-74b4e16627102cb24d295cbf3e6d313c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/condition_2d.svg" 14 | dest_files=["res://.godot/imported/condition_2d.svg-74b4e16627102cb24d295cbf3e6d313c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition_3d.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | Created by potrace 1.15, written by Peter Selinger 2001-2017 39 | 45 | 46 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/condition_3d.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://be71n6y4vjmpc" 6 | path="res://.godot/imported/condition_3d.svg-dfa75c275f007577f1438903b09d3242.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/condition_3d.svg" 14 | dest_files=["res://.godot/imported/condition_3d.svg-dfa75c275f007577f1438903b09d3242.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/data_plus.gd: -------------------------------------------------------------------------------- 1 | ## Add a float to a current agent's data 2 | 3 | @icon("action.svg") 4 | class_name DataPlus 5 | extends BehaviorTreeForGroups 6 | 7 | @export var data_name:String = "" 8 | @export var add_value:float = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | if data_name != "": 12 | if agent.has_meta(data_name): 13 | var val:float = 0 14 | val = agent.get_meta(data_name) 15 | val = val + add_value 16 | agent.set_meta(data_name, val) 17 | return true 18 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/data_set.gd: -------------------------------------------------------------------------------- 1 | ## Set a float to a current agent's data 2 | 3 | @icon("action.svg") 4 | class_name DataSet 5 | extends BehaviorTreeForGroups 6 | 7 | @export var data_name:String = "" 8 | @export var set_to_value:float = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | if data_name != "": 12 | agent.set_meta(data_name, set_to_value) 13 | return true 14 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/delete.gd: -------------------------------------------------------------------------------- 1 | ## Remove the current agent from the scene 2 | 3 | @icon("action.svg") 4 | class_name Delete 5 | extends BehaviorTreeForGroups 6 | 7 | func biodyn_process(agent)->bool: 8 | agent.queue_free() 9 | return true 10 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/fallback.gd: -------------------------------------------------------------------------------- 1 | ## Execute its children nodes 2 | ## upto one of them succeed 3 | 4 | @icon("fallback.svg") 5 | class_name Fallback 6 | extends BehaviorTreeForGroups 7 | 8 | @export var activated:bool = true 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func biodyn_process(agent)->bool: 12 | # Fallback Node 13 | # Execute its children, stops when : 14 | # a) one succeeded (=> return success) 15 | # b) or all failed (=> return failure) 16 | if activated == false: 17 | return false 18 | var overall_success:bool = false 19 | for behav in self.get_children(): 20 | var success = behav.biodyn_process(agent) 21 | if success == true: 22 | return true 23 | return false 24 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/fallback.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | 39 | Created by potrace 1.15, written by Peter Selinger 2001-2017 40 | 41 | 47 | 51 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/fallback.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://7swuq7wv1mja" 6 | path="res://.godot/imported/fallback.svg-70c42f61285363b7207b30c252a557ca.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/fallback.svg" 14 | dest_files=["res://.godot/imported/fallback.svg-70c42f61285363b7207b30c252a557ca.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/field.gd: -------------------------------------------------------------------------------- 1 | extends Resource 2 | 3 | class_name Field 4 | 5 | @export var name:String = "Field" 6 | @export var color:Color = Color.BLUE 7 | @export_range(0.0, 1.0) var diffusion_speed:float = 0.3 8 | @export var degradation_speed:float = 0.001 9 | @export_enum("0", "1", "Random") var initialisation: String = "0" 10 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_angular_z.gd: -------------------------------------------------------------------------------- 1 | ## Applies an angular force to the current agent 2 | ## relating to the center 3 | 4 | @icon("action.svg") 5 | class_name ForceAngularZ 6 | extends BehaviorTreeForGroups 7 | 8 | ## Center of the force field (vortex) 9 | @export var center:Vector3 10 | ##Intensity of the force field (vortex) 11 | @export var intensity:float = 1.0 12 | 13 | func biodyn_process(agent)->bool: 14 | if agent is RigidBody3D: 15 | var dv:Vector3 = center - agent.position.normalized() 16 | var du:Vector3 = Vector3(-dv.y, dv.x, 0) 17 | agent.apply_central_impulse ( intensity*du ) 18 | return true 19 | if agent is RigidBody2D: 20 | var dv:Vector2 = Vector2(center.x, center.y) - agent.position.normalized() 21 | var du:Vector2 = Vector2(-dv.y, dv.x) 22 | agent.apply_central_impulse ( intensity*du ) 23 | return true 24 | 25 | return false 26 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_forward.gd: -------------------------------------------------------------------------------- 1 | ## Applies a forward force to the current agent 2 | 3 | @icon("action.svg") 4 | class_name ForceForward 5 | extends BehaviorTreeForGroups 6 | 7 | @export var fx:float = 0.0 8 | 9 | func biodyn_process(agent)->bool: 10 | if agent is RigidBody3D: 11 | agent.apply_central_impulse(agent.transform.basis.x * fx) 12 | return true 13 | 14 | if agent is RigidBody2D: 15 | agent.apply_central_impulse(agent.transform.basis.x * fx) 16 | return true 17 | 18 | return false 19 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_global.gd: -------------------------------------------------------------------------------- 1 | ## Applies a force to the current agent 2 | ## relating to the absolute axis reference 3 | 4 | @icon("action.svg") 5 | class_name ForceGlobal 6 | extends BehaviorTreeForGroups 7 | 8 | @export var fx:float = 0.0 9 | @export var fy:float = 0.0 10 | @export var fz:float = 0.0 11 | 12 | func biodyn_process(agent)->bool: 13 | if agent is RigidBody3D: 14 | agent.apply_central_impulse ( Vector3 (fx, fy, fz) ) 15 | return true 16 | if agent is RigidBody2D: 17 | agent.apply_central_impulse ( Vector2 (fx, fy) ) 18 | return true 19 | return false 20 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_radial.gd: -------------------------------------------------------------------------------- 1 | ## Applies a centrifuge or centripet force to the current agent 2 | ## relating to the center 3 | 4 | @icon("action.svg") 5 | class_name ForceRadial 6 | extends BehaviorTreeForGroups 7 | 8 | ## Center of the force field 9 | @export var center:Vector3 10 | ## Intensity of the force field 11 | @export var intensity:float = 1.0 12 | 13 | func biodyn_process(agent)->bool: 14 | if agent is RigidBody3D: 15 | var dv:Vector3 = center - agent.position.normalized() 16 | agent.apply_central_impulse ( intensity*dv ) 17 | return true 18 | 19 | if agent is RigidBody2D: 20 | var dv:Vector2 = Vector2(center.x, center.y) - agent.position.normalized() 21 | agent.apply_central_impulse ( intensity*dv ) 22 | return true 23 | 24 | return false 25 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_random.gd: -------------------------------------------------------------------------------- 1 | ## Applies a random force to the current agent 2 | 3 | @icon("action.svg") 4 | class_name ForceRandom 5 | extends BehaviorTreeForGroups 6 | 7 | @export var F:Vector3 = Vector3(1,1,1) 8 | 9 | func biodyn_process(agent)->bool: 10 | if agent is RigidBody3D: 11 | var ffx:float = F.x * (randf() - 0.5) 12 | var ffy:float = F.y * (randf() - 0.5) 13 | var ffz:float = F.z * (randf() - 0.5) 14 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) ) 15 | agent.apply_central_impulse ( Vector3 (ffx, ffy, ffz) ) 16 | return true 17 | 18 | if agent is RigidBody2D: 19 | var ffx:float = F.x * (randf() - 0.5) 20 | var ffy:float = F.y * (randf() - 0.5) 21 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) ) 22 | agent.apply_central_impulse ( Vector2 (ffx, ffy) ) 23 | return true 24 | 25 | return false 26 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/force_to_grid_value.gd: -------------------------------------------------------------------------------- 1 | ## Applies a force to the current agent 2 | ## toward the value the agent has to reach 3 | ## inside a Grid of values 4 | 5 | @icon("action.svg") 6 | class_name ForceToGridValue 7 | extends BehaviorTreeForGroups 8 | 9 | @export var on_grid_group:String = "" 10 | @export var for_field:String = "" 11 | @export var target_value:float = 0 12 | @export var force:float = 0 13 | 14 | var grids:Array = Array() 15 | 16 | func _ready(): 17 | grids = get_tree().get_nodes_in_group(on_grid_group) 18 | pass 19 | 20 | func biodyn_process(agent)->bool: 21 | for grid in grids: 22 | # 2D 23 | var F:Vector2 = Vector2(0,0) 24 | if agent is RigidBody2D and "values_t0" in grid: 25 | var ax:float = agent.position.x 26 | var ay:float = agent.position.y 27 | var gx_min:float = grid.position.x 28 | var gx_max:float = gx_min+grid.size.x 29 | var gy_min:float = grid.position.y 30 | var gy_max:float = gy_min+grid.size.y 31 | if ax >= gx_min && ax < gx_max: 32 | if ay >= gy_min && ay < gy_max: 33 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX 34 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY 35 | var p:int = px+py*grid.SX 36 | var fx:float = 0 37 | var fy:float = 0 38 | if grid.fields_dico.has(for_field) == true: 39 | var p0:float = grid.values_t0[(p+1)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]] 40 | var p1:float = grid.values_t0[(p-grid.SX+grid.SX*grid.SY)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]] 41 | var p2:float = grid.values_t0[(p-1+grid.SX*grid.SY)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]] 42 | var p3:float = grid.values_t0[(p+grid.SX)%(grid.SX*grid.SY)].values[grid.fields_dico[for_field]] 43 | if grid.values_t0[p].values[grid.fields_dico[for_field]] >= target_value: 44 | # Go to the lowest value arround 45 | if p0 <= p1 && p0 <= p2 && p0 <= p3: 46 | fx = force 47 | elif p1 <= p2 && p1 <= p3: 48 | fy = -force 49 | elif p2 <= p3: 50 | fx = -force 51 | else: 52 | fy = force 53 | if grid.values_t0[p].values[grid.fields_dico[for_field]] < target_value: 54 | # Go to the highest value arround 55 | if p0 >= p1 && p0 >= p2 && p0 >= p3: 56 | fx = force 57 | elif p1 >= p2 && p1 >= p3: 58 | fy = -force 59 | elif p2 >= p3: 60 | fx = -force 61 | else: 62 | fy = force 63 | F = F + Vector2(fx,fy) 64 | agent.apply_impulse(F) 65 | return true 66 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/global_data_plus.gd: -------------------------------------------------------------------------------- 1 | ## Add a float to a current global's data 2 | 3 | @icon("action.svg") 4 | class_name GlobalDataPlus 5 | extends BehaviorTreeForGroups 6 | 7 | @export var global_data_name:String = "" 8 | @export var add_value:float = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | if global_data_name != "": 12 | if BTFG.btfg_root.has_meta(global_data_name): 13 | var val:float = 0 14 | val = BTFG.btfg_root.get_meta(global_data_name) 15 | val = val + add_value 16 | BTFG.btfg_root.set_meta(global_data_name, val) 17 | return true 18 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/global_data_set.gd: -------------------------------------------------------------------------------- 1 | ## Set a float to global scene's data 2 | 3 | @icon("action.svg") 4 | class_name GlobalDataSet 5 | extends BehaviorTreeForGroups 6 | 7 | @export var global_data_name:String = "" 8 | @export var set_to_value:float = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | if global_data_name != "": 12 | BTFG.btfg_root.set_meta(global_data_name, set_to_value) 13 | return true 14 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/grid2d.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends TextureRect 3 | 4 | @export var SX:int = 64 5 | @export var SY:int = 32 6 | @export var loop_x:bool = false 7 | @export var loop_y:bool = false 8 | 9 | @export var fields:Array[Field] = [] 10 | @export var reactions:Array[Reaction] = [] 11 | 12 | @export var opacity:float = 1.0 13 | #@export var show_iso:bool = false 14 | @export var print_values:bool = false 15 | 16 | @export var state:int = 0 17 | @export var age:int = 0 18 | 19 | var values_t0:Array[data] = [] 20 | var values_t1:Array[data] = [] 21 | 22 | var xmin:float; var xmax:float; var ymin:float;var ymax:float 23 | 24 | # Store the values of each field for ONE position in the matrix 25 | # Each data stores one qte of all the Fields 26 | class data: 27 | var values:Array[float] = [] 28 | func _init(fields:Array[Field], i:int, j:int, SX:int, SY:int, loop_x:bool, loop_y:bool): 29 | values.resize(fields.size()) 30 | for f in fields.size(): 31 | if fields[f] != null: 32 | if fields[f].initialisation == "0": 33 | values[f] = 0.0 34 | elif fields[f].initialisation == "1": 35 | values[f] = 1.0 36 | elif fields[f].initialisation == "Random": 37 | values[f] = randf() 38 | if loop_x == false and (i == 0 or i == SX-1) : # borders are exluded if non toric matrix 39 | values[f] = 0.0 40 | if loop_y == false and (j == 0 or j == SY-1): 41 | values[f] = 0.0 42 | var fields_dico:Dictionary 43 | 44 | func _ready(): 45 | # loop or not loop 46 | if loop_x == true: 47 | xmin = 0 48 | xmax = SX 49 | else: 50 | xmin = 1 51 | xmax = SX-1 52 | if loop_y == true: 53 | ymin = 0 54 | ymax = SY 55 | else: 56 | ymin = 1 57 | ymax = SY-1 58 | 59 | # Init matrix values 60 | values_t0.resize(SX*SY) 61 | values_t1.resize(SX*SY) 62 | for i in SX: 63 | for j in SY: 64 | values_t0[i+j*SX] = data.new(fields, i, j, SX, SY, loop_x, loop_y) # Call the constructor (_init) 65 | values_t1[i+j*SX] = data.new(fields, i, j, SX, SY, loop_x, loop_y) 66 | 67 | # fields names => id: allow a quick access of fields names during reactions 68 | var id:int = 0 69 | fields_dico["-"]=-1 70 | for f in fields: 71 | if f!= null: 72 | fields_dico[f.name]=id 73 | id += 1 74 | 75 | # reactions init 76 | for r in reactions: 77 | if r!=null: 78 | r.extract_coef_field() 79 | if fields_dico.has(r.reactive_1) == false: 80 | r.reactive_1 = "-" 81 | if fields_dico.has(r.reactive_2) == false: 82 | r.reactive_2 = "-" 83 | if fields_dico.has(r.reactive_3) == false: 84 | r.reactive_3 = "-" 85 | if fields_dico.has(r.product_1) == false: 86 | r.product_1 = "-" 87 | if fields_dico.has(r.product_2) == false: 88 | r.product_2 = "-" 89 | if fields_dico.has(r.product_3) == false: 90 | r.product_3 = "-" 91 | 92 | func _process(_delta): 93 | if not Engine.is_editor_hint(): 94 | reaction_diffusion() 95 | #if show_iso == false: 96 | display_values() 97 | #else: 98 | # display_iso() 99 | if print_values == true: 100 | print_all_values() 101 | age += 1 102 | 103 | func reaction_diffusion(): 104 | # Reaction 105 | var r1 : int 106 | var r2 : int 107 | var r3 : int 108 | var s : float 109 | var p1 : int 110 | var p2 : int 111 | var p3 : int 112 | 113 | for r in reactions: 114 | if r != null: 115 | for i in range(xmin,xmax): 116 | for j in range(ymin,ymax): 117 | var p:int = i+j*SX 118 | r1 = fields_dico[r.reactive_1] 119 | r2 = fields_dico[r.reactive_2] 120 | r3 = fields_dico[r.reactive_3] 121 | p1 = fields_dico[r.product_1] 122 | p2 = fields_dico[r.product_2] 123 | p3 = fields_dico[r.product_3] 124 | s = r.speed 125 | 126 | # NO reactive 127 | if r1 < 0 and r2 < 0 and r3 < 0: 128 | # if product 129 | if p1 >= 0: 130 | values_t0[p].values[p1] += s*r.coef_p1 131 | if p2 >= 0: 132 | values_t0[p].values[p2] += s*r.coef_p2 133 | if p3 >= 0: 134 | values_t0[p].values[p3] += s*r.coef_p3 135 | # Only ONE reactive (r1) 136 | if r1 >= 0 and r2 < 0 and r3 < 0: 137 | var d_qte:float = s * values_t0[p].values[r1] 138 | values_t0[p].values[r1] -= d_qte*r.coef_r1 139 | # if product 140 | if p1 >= 0: 141 | values_t0[p].values[p1] += d_qte*r.coef_p1 142 | if p2 >= 0: 143 | values_t0[p].values[p2] += d_qte*r.coef_p2 144 | if p3 >= 0: 145 | values_t0[p].values[p3] += d_qte*r.coef_p3 146 | # Only ONE reactive (r2) 147 | if r1 < 0 and r2 >= 0 and r3 < 0: 148 | var d_qte:float = s * values_t0[p].values[r2] 149 | values_t0[p].values[r2] -= d_qte*r.coef_r2 150 | # if product 151 | if p1 >= 0: 152 | values_t0[p].values[p1] += d_qte*r.coef_p1 153 | if p2 >= 0: 154 | values_t0[p].values[p2] += d_qte*r.coef_p2 155 | if p3 >= 0: 156 | values_t0[p].values[p3] += d_qte*r.coef_p3 157 | # Only ONE reactive (r3) 158 | if r1 < 0 and r2 < 0 and r3 >= 0: 159 | var d_qte:float = s * values_t0[p].values[r3] 160 | values_t0[p].values[r3] -= d_qte*r.coef_r3 161 | # if product 162 | if p1 >= 0: 163 | values_t0[p].values[p1] += d_qte*r.coef_p1 164 | if p2 >= 0: 165 | values_t0[p].values[p2] += d_qte*r.coef_p2 166 | if p3 >= 0: 167 | values_t0[p].values[p3] += d_qte*r.coef_p3 168 | # TWO reactives (r1+r2) 169 | if r1 >=0 and r2 >= 0 and r3 < 0: 170 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r2] 171 | values_t0[p].values[r1] -= d_qte*r.coef_r1 172 | values_t0[p].values[r2] -= d_qte*r.coef_r2 173 | # if product 174 | if p1 >= 0: 175 | values_t0[p].values[p1] += d_qte*r.coef_p1 176 | if p2 >= 0: 177 | values_t0[p].values[p2] += d_qte*r.coef_p2 178 | if p3 >= 0: 179 | values_t0[p].values[p3] += d_qte*r.coef_p3 180 | # TWO reactives (r1+r3) 181 | if r1 >=0 and r2 < 0 and r3 >= 0: 182 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r3] 183 | values_t0[p].values[r1] -= d_qte*r.coef_r1 184 | values_t0[p].values[r3] -= d_qte*r.coef_r3 185 | # if product 186 | if p1 >= 0: 187 | values_t0[p].values[p1] += d_qte*r.coef_p1 188 | if p2 >= 0: 189 | values_t0[p].values[p2] += d_qte*r.coef_p2 190 | if p3 >= 0: 191 | values_t0[p].values[p3] += d_qte*r.coef_p3 192 | # TWO reactives (r1+r3) 193 | if r1 < 0 and r2 >= 0 and r3 >= 0: 194 | var d_qte:float = s * values_t0[p].values[r2] * values_t0[p].values[r3] 195 | values_t0[p].values[r2] -= d_qte*r.coef_r2 196 | values_t0[p].values[r3] -= d_qte*r.coef_r3 197 | # if product 198 | if p1 >= 0: 199 | values_t0[p].values[p1] += d_qte*r.coef_p1 200 | if p2 >= 0: 201 | values_t0[p].values[p2] += d_qte*r.coef_p2 202 | if p3 >= 0: 203 | values_t0[p].values[p3] += d_qte*r.coef_p3 204 | # THREE reactives (r1+r2+r3) 205 | if r1 >= 0 and r2 >= 0 and r3 >= 0: 206 | var d_qte:float = s * values_t0[p].values[r1] * values_t0[p].values[r2] * values_t0[p].values[r3] 207 | values_t0[p].values[r1] -= d_qte*r.coef_r1 208 | values_t0[p].values[r2] -= d_qte*r.coef_r2 209 | values_t0[p].values[r3] -= d_qte*r.coef_r3 210 | # if product 211 | if p1 >= 0: 212 | values_t0[p].values[p1] += d_qte*r.coef_p1 213 | if p2 >= 0: 214 | values_t0[p].values[p2] += d_qte*r.coef_p2 215 | if p3 >= 0: 216 | values_t0[p].values[p3] += d_qte*r.coef_p3 217 | 218 | # Diffusion 219 | for f in fields.size(): 220 | if fields[f] != null: 221 | var degrad:float = fields[f].degradation_speed 222 | var diffus:float = fields[f].diffusion_speed 223 | for i in range(xmin,xmax): 224 | for j in range(ymin,ymax): 225 | var p:int = i+j*SX 226 | var v0:float = values_t0[ (i+1)%SX+j*SX].values[f] 227 | var v1:float = values_t0[ (i-1+SX)%SX+j*SX].values[f] 228 | var v2:float = values_t0[ i%SX+((j+1)%SY)*SX].values[f] 229 | var v3:float = values_t0[ i%SX+((j-1+SY)%SY)*SX].values[f] 230 | values_t1[p].values[f] = (1.0-degrad)*(1.0-diffus)*values_t0[p].values[f] + diffus*(v0+v1+v2+v3)*0.25 231 | 232 | for i in range(SX*SY): 233 | values_t0[i].values[f] = values_t1[i].values[f] 234 | 235 | 236 | func display_values(): 237 | var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8) 238 | for f in fields.size(): 239 | if fields[f] != null: 240 | for i in range(SX): 241 | for j in range(SY): 242 | var p:int = i+j*SX 243 | var v:float = values_t0[p].values[f] 244 | var col:Color = img.get_pixel(i,j) 245 | var baseColor:Color = fields[f].color 246 | var R = max(0.1, min(v*baseColor.r+col.r,0.9)) 247 | var G = max(0.1, min(v*baseColor.g+col.g,0.9)) 248 | var B = max(0.1, min(v*baseColor.b+col.b,0.9)) 249 | img.set_pixel(i,j,Color(R,G,B,opacity) ) 250 | set_texture(ImageTexture.create_from_image(img)) 251 | 252 | 253 | func print_all_values(): 254 | var i:int = randi_range(0, SX-1) 255 | var j:int = randi_range(0, SY-1) 256 | for f in fields.size(): 257 | var v:float = values_t0[i+j*SX].values[f] 258 | print("At (" + str(i) + "," + str(j) + ")=" + str(num_zeros(v)) + "<=" + str(v) ) 259 | 260 | func num_zeros(val:float) -> int: 261 | var n:int = 0 262 | if val != 0: 263 | n = -floor( log(abs(val)) / log(10) ) - 1 264 | return n 265 | 266 | func display_iso(): 267 | return 268 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8) 269 | #var r:float; var g:float; var b:float 270 | #for i in range(1,SX-2): 271 | #for j in range(1,SY-2): 272 | #var p:int = i+j*SX 273 | #var v0:float = num_zeros(values_t0[p]) 274 | #var vg:float = num_zeros(values_t0[p-1]) 275 | #var vd:float = num_zeros(values_t0[p+1]) 276 | #var vh:float = num_zeros(values_t0[p-SX]) 277 | #var vb:float = num_zeros(values_t0[p+SX]) 278 | #var e:float = 1.0 279 | #if vg>v0 || vd>v0 || vh>v0 || vb>v0: 280 | #e = 0.5 281 | #img.set_pixel(i,j,Color(e*baseColor.r,e*baseColor.g,e*baseColor.b,baseColor.a) ) 282 | #set_texture(ImageTexture.create_from_image(img)) 283 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/addons/behav_tree_for_groups/icon.png -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://y1248e31lb2p" 6 | path="res://.godot/imported/icon.png-73f6b8b1eff28052e2c7e3d863afda88.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/icon.png" 14 | dest_files=["res://.godot/imported/icon.png-73f6b8b1eff28052e2c7e3d863afda88.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_between.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's age 2 | ## is between 2 given integer numbers. 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeBetween 6 | extends BehaviorTreeForGroups 7 | 8 | ## Initial simulation/execution step 9 | @export var age_start:int = 0 10 | ## Final simulation/execution step 11 | @export var age_end:int = 100 12 | 13 | func _ready(): 14 | pass 15 | 16 | # Called every frame. 'delta' is the elapsed time since the previous frame. 17 | func biodyn_process(agent)->bool: 18 | var age:int = agent.age 19 | if age >= age_start and age <= age_end: 20 | return true 21 | else: 22 | return false 23 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_equals.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's age 2 | ## is equal to the given integer number. 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeEquals 6 | extends BehaviorTreeForGroups 7 | 8 | @export var age_equals:int = 0 9 | 10 | func _ready(): 11 | pass 12 | 13 | # Called every frame. 'delta' is the elapsed time since the previous frame. 14 | func biodyn_process(agent)->bool: 15 | var age:int = agent.age 16 | if age == age_equals : 17 | return true 18 | else: 19 | return false 20 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_equals_periodic_values.gd: -------------------------------------------------------------------------------- 1 | ## Return true when age reaches 2 | ## specified periodic values 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeEqualsPeriodicValues 6 | extends BehaviorTreeForGroups 7 | 8 | 9 | ## Size of each step 10 | @export var period: int =0 11 | @export var min_age: int =0 12 | ## Put -1 for infinite max age 13 | @export var max_age: int = -1 14 | 15 | func biodyn_process(agent)->bool: 16 | var age:int =agent.age 17 | if max_age == -1 : 18 | if age >= min_age : 19 | if (age-min_age)%period == 0 : 20 | return true 21 | else : 22 | return false 23 | else : 24 | return false 25 | elif age >= min_age and age <= max_age: 26 | if (age-min_age)%period == 0 : 27 | return true 28 | else : 29 | return false 30 | else : 31 | return false 32 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_equals_values.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the age equals 2 | ## one of the given values. 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeEqualsValues 6 | extends BehaviorTreeForGroups 7 | 8 | @export var values:Array[int] = [10,20,25] 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func biodyn_process(agent)->bool: 12 | var age:int = agent.age 13 | if values.find(age, 0) >= 0 : 14 | return true 15 | else: 16 | return false 17 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_inf.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's age 2 | ## is inf to the given integer number. 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeInf 6 | extends BehaviorTreeForGroups 7 | 8 | @export var age_inferior_to:int = 0 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func biodyn_process(agent)->bool: 12 | if agent.age <= age_inferior_to : 13 | return true 14 | else: 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_age_sup.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's age 2 | ## is equal to the given integer number. 3 | 4 | @icon("condition.svg") 5 | class_name IfAgeSup 6 | extends BehaviorTreeForGroups 7 | 8 | @export var age_superior_to:int = 0 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func biodyn_process(agent)->bool: 12 | if agent.age >= age_superior_to : 13 | return true 14 | else: 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_collision.gd: -------------------------------------------------------------------------------- 1 | ## Returns true if a collision occurs 2 | ## for the current agent 3 | 4 | @icon("condition.svg") 5 | class_name IfCollision 6 | extends BehaviorTreeForGroups 7 | 8 | ## Collider's group 9 | @export var with_group:String = "" 10 | ## Group's state (-1 = any state) 11 | @export var in_state:int = -1 12 | ## Collider's reference into the common blackboard 13 | var collider_reference:String = "collider" 14 | 15 | func biodyn_process(agent)->bool: 16 | var bodies = agent.get_colliding_bodies() 17 | if bodies.size() > 0: 18 | for b in bodies: 19 | if b.is_in_group(with_group): 20 | if "state" in b: 21 | if b.state == in_state || in_state == -1: 22 | if collider_reference != "": 23 | get_tree().current_scene.set_meta(collider_reference, b) 24 | return true 25 | else: # Not an agent from BehavTreeForGroups 26 | return true 27 | return false 28 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_between.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's data 2 | ## is between 2 given float values. 3 | 4 | @icon("condition.svg") 5 | class_name IfDataBetween 6 | extends BehaviorTreeForGroups 7 | 8 | @export var data_name:String = "" 9 | @export var data_min:float = 0 10 | @export var data_max:float = 0 11 | 12 | func biodyn_process(agent:Node)->bool: 13 | if data_name != "": 14 | if agent.has_meta(data_name): 15 | var val:float = 0 16 | val = agent.get_meta(data_name) 17 | if val >= data_min and val <= data_max: 18 | return true 19 | return false 20 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_equals.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent's data 2 | ## equals a specific float value 3 | 4 | @icon("condition.svg") 5 | class_name IfDataEquals 6 | extends BehaviorTreeForGroups 7 | 8 | @export var data_name:String = "" 9 | @export var is_equal_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if data_name != "": 13 | if agent.has_meta(data_name): 14 | var val:float = 0 15 | val = agent.get_meta(data_name) 16 | if val == is_equal_to: 17 | return true 18 | return false 19 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_equals_periodic_values.gd: -------------------------------------------------------------------------------- 1 | ## Return true when the data's value is 2 | ## inside the specified interval and 3 | ## periodically for each gap of the step size. 4 | 5 | @icon("condition.svg") 6 | class_name IfDataEqualsPeriodicValues 7 | extends BehaviorTreeForGroups 8 | 9 | 10 | 11 | @export var data_name:String = "" 12 | ## Size of each step 13 | @export var period: float = 0 14 | @export var min_data: float = 0 15 | ## Put -1 for infinite 16 | @export var max_data: float = -1 17 | 18 | # Called every frame. 'delta' is the elapsed time since the previous frame. 19 | func biodyn_process(agent)->bool: 20 | if data_name != "": 21 | if agent.has_meta(data_name): 22 | var data_value:float = agent.get_meta(data_name) 23 | if max_data == -1 : 24 | if data_value >= min_data : 25 | if modulo( (data_value-min_data), period) == true : 26 | return true 27 | else : 28 | return false 29 | else : 30 | return false 31 | elif data_value >= min_data and data_value <= max_data: 32 | if modulo( (data_value-min_data), period) == true : 33 | return true 34 | else : 35 | return false 36 | else: 37 | return false 38 | else : 39 | return false 40 | else : 41 | return false 42 | 43 | func modulo(val:float, period:float) -> bool: 44 | var rest:int = val / period 45 | if (val / period) == rest: 46 | return true 47 | else: 48 | return false 49 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_equals_values.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the data's value 2 | ## equals one of the given values. 3 | 4 | @icon("condition.svg") 5 | class_name IfDataEqualsValues 6 | extends BehaviorTreeForGroups 7 | @export var data_name:String = "" 8 | @export var values:Array[float] = [10,20,25] 9 | 10 | # Called every frame. 'delta' is the elapsed time since the previous frame. 11 | func biodyn_process(agent)->bool: 12 | if data_name != "": 13 | if agent.has_meta(data_name): 14 | var data_value:float = agent.get_meta(data_name) 15 | if values.find(data_value) >= 0 : 16 | return true 17 | else: 18 | return false 19 | else : 20 | return false 21 | else : 22 | return false 23 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_inf.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent's data 2 | ## is inferior to a float value 3 | 4 | @icon("condition.svg") 5 | class_name IfDataInf 6 | extends BehaviorTreeForGroups 7 | 8 | @export var data_name:String = "" 9 | @export var is_inf_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if data_name != "": 13 | if agent.has_meta(data_name): 14 | var val:float = 0 15 | val = agent.get_meta(data_name) 16 | if val < is_inf_to: 17 | return true 18 | return false 19 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_data_sup.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent's data 2 | ## is superior to a float value 3 | 4 | @icon("condition.svg") 5 | class_name IfDataSup 6 | extends BehaviorTreeForGroups 7 | 8 | @export var data_name:String = "" 9 | @export var is_sup_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if data_name != "": 13 | if agent.has_meta(data_name): 14 | var val:float = 0 15 | val = agent.get_meta(data_name) 16 | if val > is_sup_to: 17 | return true 18 | return false 19 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_global_data_between.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the global's data 2 | ## is between 2 given float values. 3 | 4 | @icon("condition.svg") 5 | class_name IfGlobalDataBetween 6 | extends BehaviorTreeForGroups 7 | 8 | @export var global_data_name:String = "" 9 | @export var min:float = 0 10 | @export var max:float = 0 11 | 12 | func biodyn_process(agent:Node)->bool: 13 | if global_data_name != "": 14 | if BTFG.btfg_root.has_meta(global_data_name): 15 | var val:float = BTFG.btfg_root.get_meta(global_data_name) 16 | if val >= min and val <= max: 17 | return true 18 | return false 19 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_global_data_equals.gd: -------------------------------------------------------------------------------- 1 | ## Return true if a global's data 2 | ## equals a specific float value 3 | 4 | @icon("condition.svg") 5 | class_name IfGlobalDataEquals 6 | extends BehaviorTreeForGroups 7 | 8 | @export var global_data_name:String = "" 9 | @export var is_equal_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if global_data_name != "": 13 | if BTFG.btfg_root.has_meta(global_data_name): 14 | var val:float = BTFG.btfg_root.get_meta(global_data_name) 15 | if val == is_equal_to: 16 | return true 17 | return false 18 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_global_data_inf.gd: -------------------------------------------------------------------------------- 1 | ## Return true if a global's data 2 | ## is inferior to a float value 3 | 4 | @icon("condition.svg") 5 | class_name IfGlobalDataInf 6 | extends BehaviorTreeForGroups 7 | 8 | @export var global_data_name:String = "" 9 | @export var is_inf_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if global_data_name != "": 13 | if BTFG.btfg_root.has_meta(global_data_name): 14 | var val:float = BTFG.btfg_root.get_meta(global_data_name) 15 | if val <= is_inf_to: 16 | return true 17 | return false 18 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_global_data_sup.gd: -------------------------------------------------------------------------------- 1 | ## Return true if a global's data 2 | ## is superior to a float value 3 | 4 | @icon("condition.svg") 5 | class_name IfGlobalDataSup 6 | extends BehaviorTreeForGroups 7 | 8 | @export var global_data_name:String = "" 9 | @export var is_sup_to:float = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if global_data_name != "": 13 | if BTFG.btfg_root.has_meta(global_data_name): 14 | var val:float = BTFG.btfg_root.get_meta(global_data_name) 15 | if val >= is_sup_to: 16 | return true 17 | return false 18 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_grid_2d_value_inf.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent 2 | ## is inside a grid having a value 3 | ## inferior to a float number 4 | 5 | @icon("condition_2d.svg") 6 | class_name IfGrid2DValueInf 7 | extends BehaviorTreeForGroups 8 | 9 | ## Name of the Grid's group 10 | ## Value to test (in Magnitude: 1=1/10, 2=1/100, 3=1/1000, etc) 11 | @export var is_inf_to:float = 0 12 | 13 | var grids:Array = Array() 14 | 15 | func _ready(): 16 | for gp in self.get_groups(): 17 | var sous_grids = get_tree().get_nodes_in_group(gp) 18 | for sg in sous_grids: 19 | grids.push_back(sg) 20 | 21 | func biodyn_process(agent)->bool: 22 | var cdt:bool = false 23 | for grid in grids: 24 | # 2D 25 | if agent is Node2D: 26 | var ax:float = agent.position.x 27 | var ay:float = agent.position.y 28 | var gx_min:float = grid.position.x 29 | var gx_max:float = gx_min+grid.size.x 30 | var gy_min:float = grid.position.y 31 | var gy_max:float = gy_min+grid.size.y 32 | if ax >= gx_min && ax < gx_max: 33 | if ay >= gy_min && ay < gy_max: 34 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX 35 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY 36 | var p:int = px+py*grid.SX 37 | var val:float = grid.values_t0[p] 38 | if val <= pow(10, -is_inf_to): 39 | cdt = true 40 | return cdt 41 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_grid_2d_value_sup.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent 2 | ## is inside a grid having a value 3 | ## superior to a float number 4 | 5 | @icon("condition_2d.svg") 6 | class_name IfGrid2DValueSup 7 | extends BehaviorTreeForGroups 8 | 9 | ## Name of the Grid's group 10 | ## Value to test (in Magnitude: 1=1/10, 2=1/100, 3=1/1000, etc) 11 | @export var is_sup_to:float = 0 12 | 13 | var grids:Array = Array() 14 | 15 | func _ready(): 16 | for gp in self.get_groups(): 17 | var sous_grids = get_tree().get_nodes_in_group(gp) 18 | for sg in sous_grids: 19 | grids.push_back(sg) 20 | 21 | func biodyn_process(agent)->bool: 22 | var cdt:bool = false 23 | for grid in grids: 24 | # 2D 25 | if agent is Node2D: 26 | var ax:float = agent.position.x 27 | var ay:float = agent.position.y 28 | var gx_min:float = grid.position.x 29 | var gx_max:float = gx_min+grid.size.x 30 | var gy_min:float = grid.position.y 31 | var gy_max:float = gy_min+grid.size.y 32 | if ax >= gx_min && ax < gx_max: 33 | if ay >= gy_min && ay < gy_max: 34 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX 35 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY 36 | var p:int = px+py*grid.SX 37 | var val:float = grid.values_t0[p] 38 | if val >= pow(10, -is_sup_to): 39 | cdt = true 40 | return cdt 41 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_in_box.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent 2 | ## is inside box 3 | 4 | @icon("condition.svg") 5 | class_name IfInBox 6 | extends BehaviorTreeForGroups 7 | 8 | @export var min:Vector3 = Vector3(-5,-5,-5) 9 | @export var max:Vector3 = Vector3(5,5,5) 10 | 11 | func biodyn_process(agent:Node) -> bool: 12 | if agent is Node3D: 13 | var x:float = agent.position.x 14 | var y:float = agent.position.y 15 | var z:float = agent.position.z 16 | 17 | # X Axis 18 | if x < min.x: 19 | return false 20 | if x > max.x: 21 | return false 22 | # Y Axis 23 | if y < min.y: 24 | return false 25 | if y > max.y: 26 | return false 27 | # Z Axis 28 | if z < min.z: 29 | return false 30 | if z > max.z: 31 | return false 32 | 33 | return true 34 | 35 | if agent is Node2D: 36 | var x:float = agent.position.x 37 | var y:float = agent.position.y 38 | 39 | # X Axis 40 | if x < min.x: 41 | return false 42 | if x > max.x: 43 | return false 44 | # Y Axis 45 | if y < min.y: 46 | return false 47 | if y > max.y: 48 | return false 49 | 50 | return true 51 | 52 | return false 53 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_mouse_click.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent 2 | ## is clicked by the mouse cursor. 3 | 4 | @icon("condition.svg") 5 | class_name IfMouseClick 6 | extends BehaviorTreeForGroups 7 | 8 | @export_enum("Left:1","Right:2","Middle:3") var mouse_button = 1 9 | @export var playerCamera:Camera3D 10 | var btn:int = MOUSE_BUTTON_LEFT 11 | 12 | func _ready(): 13 | if mouse_button == 1: 14 | btn = MOUSE_BUTTON_LEFT 15 | if mouse_button == 2: 16 | btn = MOUSE_BUTTON_RIGHT 17 | if mouse_button == 3: 18 | btn = MOUSE_BUTTON_MIDDLE 19 | 20 | # Called every frame. 'delta' is the elapsed time since the previous frame. 21 | func biodyn_process(agent)->bool: 22 | if agent is CollisionObject3D: 23 | if Input.is_mouse_button_pressed(btn): 24 | if playerCamera == null: 25 | playerCamera = get_tree().root.find_child("Camera3D", true, false) 26 | if playerCamera == null: 27 | print("Camera3D not found") 28 | return false 29 | var spaceState = agent.get_world_3d().direct_space_state 30 | var mousePosition = agent.get_viewport().get_mouse_position() 31 | var raycastOrigin = playerCamera.project_ray_origin(mousePosition) 32 | var rayLength = 1000 33 | var raycastTarget = raycastOrigin + playerCamera.project_ray_normal(mousePosition) * rayLength 34 | var physicsRaycastQuery = PhysicsRayQueryParameters3D.create(raycastOrigin, raycastTarget) 35 | var raycastResult = spaceState.intersect_ray(physicsRaycastQuery) 36 | if raycastResult: 37 | if raycastResult.collider == agent: 38 | return true 39 | 40 | return false 41 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_no_contact.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent 2 | ## has no collision during 3 | ## several execution steps 4 | 5 | @icon("condition.svg") 6 | class_name IfNoContact 7 | extends BehaviorTreeForGroups 8 | 9 | @export var steps_without_contact:int = 100 10 | var period_of_no_contact:int = 0 11 | 12 | func biodyn_process(agent)->bool: 13 | var bodies = agent.get_colliding_bodies() 14 | if bodies.size() == 0: 15 | period_of_no_contact = period_of_no_contact + 1 16 | else: 17 | period_of_no_contact = 0 # A contact occurs => reset 18 | 19 | if period_of_no_contact >= steps_without_contact: 20 | period_of_no_contact = steps_without_contact # avoid go back to MIN int if very very long period without contact 21 | return true 22 | else: 23 | return false 24 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_no_contact_with.gd: -------------------------------------------------------------------------------- 1 | ## Return true if an agent has no collision 2 | ## with a specific group in a designated 3 | ## state during several execution steps. 4 | 5 | @icon("condition.svg") 6 | class_name IfNoContactWith 7 | extends BehaviorTreeForGroups 8 | 9 | ## Contact's group 10 | @export var with_group:String = "" 11 | @export var steps_without_contact:int = 100 12 | var period_of_no_contact:int = 0 13 | ## Group's state (-1 = any state) 14 | @export var in_state:int = -1 15 | 16 | func biodyn_process(agent)->bool: 17 | var bodies = agent.get_colliding_bodies() 18 | var col:bool = false 19 | for b in bodies: 20 | if b.is_in_group(with_group): 21 | if "state" in b: 22 | if b.state == in_state || in_state == -1: 23 | col = true 24 | 25 | if col == false: 26 | period_of_no_contact = period_of_no_contact + 1 27 | else: 28 | period_of_no_contact = 0 # A contact occurs => reset 29 | 30 | if period_of_no_contact >= steps_without_contact: 31 | period_of_no_contact = steps_without_contact # avoid go back to MIN int if very very long period without contact 32 | return true 33 | else: 34 | return false 35 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_proba.gd: -------------------------------------------------------------------------------- 1 | ## Return true if a random float 2 | ## between 0 and 100 is inferior 3 | ## to a given float number 4 | 5 | @icon("condition.svg") 6 | class_name IfProba 7 | extends BehaviorTreeForGroups 8 | 9 | ## Probability of success 10 | @export var proba:float = 100 11 | 12 | func _ready(): 13 | pass 14 | 15 | # Called every frame. 'delta' is the elapsed time since the previous frame. 16 | func biodyn_process(agent)->bool: 17 | var rnd:float = randf() 18 | if rnd < proba/100.0: 19 | return true 20 | else: 21 | return false 22 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_state_equals.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the agent's state 2 | ## equals a given integer value 3 | 4 | @icon("condition.svg") 5 | class_name IfStateEquals 6 | extends BehaviorTreeForGroups 7 | 8 | ## Test the state value (-1 for any state) 9 | @export var state_equals:int = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | if agent.state == state_equals || state_equals == -1: 13 | return true 14 | else: 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_step_between.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the simulation/execution step 2 | ## is between 2 given integer numbers. 3 | 4 | @icon("condition.svg") 5 | class_name IfStepBetween 6 | extends BehaviorTreeForGroups 7 | 8 | ## Initial simulation/execution step 9 | @export var step_start:int = 0 10 | ## Final simulation/execution step 11 | @export var step_end:int = 100 12 | 13 | func _ready(): 14 | pass 15 | 16 | # Called every frame. 'delta' is the elapsed time since the previous frame. 17 | func biodyn_process(agent)->bool: 18 | var step:int = BehaviorTreeForGroups.simulation_step 19 | if step >= step_start and step <= step_end: 20 | return true 21 | else: 22 | return false 23 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_time_between.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the time's data 2 | ## is between 2 given float values. 3 | 4 | @icon("condition.svg") 5 | class_name IfTimeBetween 6 | extends BehaviorTreeForGroups 7 | 8 | @export var start_time_ms:int = 0 9 | @export var end_time_ms:int = 0 10 | 11 | func biodyn_process(agent:Node)->bool: 12 | var val:int = Time.get_ticks_msec() 13 | if val >= start_time_ms and val <= end_time_ms: 14 | return true 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_time_inf.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the time 2 | ## is inferior to a specific 3 | ## int value snapped by 20. 4 | 5 | @icon("condition.svg") 6 | class_name IfTimeInf 7 | extends BehaviorTreeForGroups 8 | @export var is_inferior_to_ms:int = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | var val:int = Time.get_ticks_msec() 12 | if val <= is_inferior_to_ms : 13 | return true 14 | else : 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/if_time_sup.gd: -------------------------------------------------------------------------------- 1 | ## Return true if the time 2 | ## is superior to a specific 3 | ## int value snapped by 20. 4 | 5 | @icon("condition.svg") 6 | class_name IfTimeSup 7 | extends BehaviorTreeForGroups 8 | @export var is_superior_to_ms:int = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | var val:int = Time.get_ticks_msec() 12 | if val >= is_superior_to_ms : 13 | return true 14 | else : 15 | return false 16 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/new_agent_2d.gd: -------------------------------------------------------------------------------- 1 | ## Create a new Type of 2D Agent 2 | ## into a Type Scene file (.tscn) 3 | ## This agent can be added manually 4 | ## using the Godot Editor 5 | ## or automaticaly (see AddAgent) 6 | ## into the main scene. 7 | 8 | @icon("action_2d.svg") 9 | @tool 10 | 11 | class_name NewAgent2D 12 | extends BehaviorTreeForGroups 13 | 14 | signal prompt_confirmed(input_text: String) 15 | signal prompt_canceled 16 | # Scène principale qui hérite de Node2D 17 | var prompt_instance: PromptDialog 18 | 19 | func _on_prompt_confirmed(input_text: String) -> void: 20 | print("L'utilisateur a validé la saisie : ", input_text) 21 | 22 | func _on_prompt_canceled(input_text: String) -> void: 23 | print("L'utilisateur a annulé la saisie : ", input_text) 24 | queue_free() 25 | 26 | func _enter_tree(): 27 | print("Agent2D : _enter_tree") 28 | 29 | # Creation of the PromptDialog 30 | prompt_instance = PromptDialog.new() 31 | 32 | print("Agent2D : prompt_instance created") 33 | 34 | # Ajout de la scène du prompt comme enfant 35 | #add_child(prompt_instance) 36 | #get_editor_interface().get_base_control().add_child(prompt_instance) 37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur 38 | editor_root.add_child(prompt_instance) 39 | 40 | prompt_instance.min_size = Vector2i(320, 80) 41 | prompt_instance.reset_size() 42 | prompt_instance.move_to_center() 43 | prompt_instance.title = "Name the new 2d agent" 44 | 45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale 46 | prompt_instance.set_transient(true) 47 | prompt_instance.set_exclusive(true) 48 | 49 | 50 | prompt_instance.close_requested.connect(func(): 51 | prompt_instance._on_cancel_button_pressed() 52 | ) 53 | 54 | # Connexion du signal de confirmation 55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed) 56 | # Connexion du signal d'annulation 57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled) 58 | 59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici) 60 | # Open the name window and apply the name to the new agent 2d 61 | var result = await prompt_instance.prompt_confirmed 62 | 63 | # The new agent is a .tscn file 64 | # It must have a valid filename 65 | var agent_name:String = result 66 | if agent_name.is_valid_filename() == false: 67 | print("Agent2D : invalid agent name => agent NOT created. Use a valid filename.") 68 | free_my_resources(null) 69 | return 70 | 71 | build_agent_2d(agent_name) 72 | 73 | func free_my_resources(rb:RigidBody2D): 74 | # Free memory resources 75 | if rb != null: 76 | rb.queue_free() # saved in the .tscn file 77 | self.queue_free() # this node is only made for creating rb 78 | print("Agent2D : Removed from Scene Tree") 79 | 80 | func build_agent_2d(agent_name:String): 81 | 82 | # Create the rigidBody2D 83 | print("Agent2D : creation of RigidBody2D") 84 | var rb:RigidBody2D = RigidBody2D.new() 85 | 86 | rb.name = agent_name 87 | rb.add_to_group(agent_name, true) 88 | 89 | # Add the collision shape 3D 90 | var col:CollisionShape2D = CollisionShape2D.new() 91 | col.name = "CollisionShape2D" 92 | var cs:CircleShape2D = CircleShape2D.new() 93 | cs.radius = 10 94 | col.set_shape(cs) 95 | rb.add_child(col) 96 | col.set_owner(rb) 97 | # Add the Polygon2D 98 | var poly:Polygon2D = Polygon2D.new() 99 | poly.name = "Polygon2D" 100 | var vertices:PackedVector2Array = PackedVector2Array(polygone2D_regular(10,6)) 101 | 102 | # Attribuer les sommets au Polygon2D 103 | poly.set_polygon(vertices) 104 | #msh.scale = Vector2(20,20) 105 | #msh.set_mesh(SphereMesh.new()) 106 | #msh.material = mat 107 | rb.add_child(poly) 108 | poly.set_owner(rb) 109 | 110 | # Set script to rb (if necessary, 111 | # change rb_script then uncomment below) 112 | var script = GDScript.new() 113 | script.set_source_code(rb_script()) 114 | script.reload() 115 | rb.set_script(script) 116 | 117 | # Set parameters 118 | rb.set_gravity_scale(0) 119 | rb.contact_monitor = true 120 | rb.max_contacts_reported = 2 121 | rb.linear_damp = 1 122 | rb.angular_damp = 1 123 | #rb.agent_color = Color(mat.albedo_color) 124 | 125 | # Export the new Agent as scene 126 | print("Agent2D : try to save TSCN") 127 | var scene = PackedScene.new() 128 | scene.pack(rb) 129 | var scene_path:String 130 | # Still a lot (it's .tscn files, NOT instances in scene tree!) 131 | scene_path = "res://"+agent_name+".tscn" #"res://"+agent_name+str(i)+".tscn" 132 | # Check if the file already exists 133 | if ResourceLoader.exists(scene_path)==true: 134 | print("new Agent2D:agent already exists. Try a new name or remove the agent") 135 | free_my_resources(rb) 136 | return 137 | # Save the Agent in the resource file .tscn 138 | ResourceSaver.save(scene, scene_path) 139 | free_my_resources(rb) 140 | 141 | 142 | 143 | func polygone2D_regular(radius:float, n:int) -> PackedVector2Array: 144 | var arr_poly:PackedVector2Array = PackedVector2Array() 145 | for a in range(0,n): 146 | var x:float = radius * cos(deg_to_rad(a*360.0 / n)) 147 | var y:float = radius * sin(deg_to_rad(a*360.0 / n)) 148 | arr_poly.append(Vector2(x,y)) 149 | return arr_poly 150 | 151 | func rb_script(): 152 | return """ 153 | @tool 154 | extends RigidBody2D 155 | 156 | @export var state:int = 0 157 | @export var age:int = 0 158 | 159 | func _process(_delta): 160 | if not Engine.is_editor_hint(): 161 | age += 1 162 | 163 | """ 164 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/new_agent_3d.gd: -------------------------------------------------------------------------------- 1 | ## Create a new Type of 3D Agent 2 | ## into a Type Scene file (.tscn) 3 | ## This agent can be added manually 4 | ## using the Godot Editor 5 | ## or automaticaly (see AddAgent) 6 | ## into the main scene. 7 | 8 | @icon("action_3d.svg") 9 | @tool 10 | 11 | class_name NewAgent3D 12 | extends BehaviorTreeForGroups 13 | 14 | signal prompt_confirmed(input_text: String) 15 | signal prompt_canceled 16 | # Scène principale qui hérite de Node2D 17 | var prompt_instance: PromptDialog 18 | 19 | func _on_prompt_confirmed(input_text: String) -> void: 20 | print("L'utilisateur a validé la saisie : ", input_text) 21 | 22 | func _on_prompt_canceled(input_text: String) -> void: 23 | print("L'utilisateur a annulé la saisie : ", input_text) 24 | queue_free() 25 | 26 | func _enter_tree(): 27 | print("Agent3D : _enter_tree") 28 | 29 | # Creation of the PromptDialog 30 | prompt_instance = PromptDialog.new() 31 | 32 | print("Agent3D : prompt_instance created") 33 | 34 | # Ajout de la scène du prompt comme enfant 35 | #add_child(prompt_instance) 36 | #get_editor_interface().get_base_control().add_child(prompt_instance) 37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur 38 | editor_root.add_child(prompt_instance) 39 | 40 | prompt_instance.min_size = Vector2i(320, 80) 41 | prompt_instance.reset_size() 42 | prompt_instance.move_to_center() 43 | prompt_instance.title = "Name the new 3d agent" 44 | 45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale 46 | prompt_instance.set_transient(true) 47 | prompt_instance.set_exclusive(true) 48 | 49 | 50 | prompt_instance.close_requested.connect(func(): 51 | prompt_instance._on_cancel_button_pressed() 52 | ) 53 | 54 | # Connexion du signal de confirmation 55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed) 56 | # Connexion du signal d'annulation 57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled) 58 | 59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici) 60 | # Open the name window and apply the name to the new agent 2d 61 | var result = await prompt_instance.prompt_confirmed 62 | 63 | # The new agent is a .tscn file 64 | # It must have a valid filename 65 | var agent_name:String = result 66 | if agent_name.is_valid_filename() == false: 67 | print("Agent3D : invalid agent name => agent NOT created. Use a valid filename.") 68 | free_my_resources(null) 69 | return 70 | 71 | build_agent_3d(agent_name) 72 | 73 | func free_my_resources(rb:RigidBody3D): 74 | # Free memory resources 75 | if rb != null: 76 | rb.queue_free() # saved in the .tscn file 77 | self.queue_free() # this node is only made for creating rb 78 | print("Agent3D : Removed from Scene Tree") 79 | 80 | func build_agent_3d(agent_name:String): 81 | # Create the rigidBody3D 82 | var rb:RigidBody3D = RigidBody3D.new() 83 | rb.name = agent_name 84 | rb.add_to_group(agent_name, true) 85 | 86 | # Add the collision shape 3D 87 | var col:CollisionShape3D = CollisionShape3D.new() 88 | col.name = "CollisionShape3D" 89 | col.set_shape(SphereShape3D.new()) 90 | rb.add_child(col) 91 | col.set_owner(rb) 92 | # New mat 93 | var mat:StandardMaterial3D = StandardMaterial3D.new() 94 | mat.albedo_color = Color(randf(),randf(),randf()) 95 | # Add the meshinstance 3D 96 | var msh:MeshInstance3D = MeshInstance3D.new() 97 | msh.name = "MeshInstance3D" 98 | msh.set_mesh(SphereMesh.new()) 99 | msh.material_override = mat 100 | rb.add_child(msh) 101 | msh.set_owner(rb) 102 | 103 | # Set script to rb (if necessary, 104 | # change rb_script then uncomment below) 105 | var script = GDScript.new() 106 | script.set_source_code(rb_script()) 107 | script.reload() 108 | rb.set_script(script) 109 | 110 | # Set parameters 111 | rb.set_gravity_scale(0) 112 | rb.contact_monitor = true 113 | rb.max_contacts_reported = 2 114 | rb.linear_damp = 5 115 | rb.angular_damp = 5 116 | #rb.agent_color = Color(mat.albedo_color) 117 | 118 | # Export the new Agent as scene 119 | print("Agent3D : try to save TSCN") 120 | var scene = PackedScene.new() 121 | scene.pack(rb) 122 | var scene_path:String 123 | # Still a lot (it's .tscn files, NOT instances in scene tree!) 124 | scene_path = "res://"+agent_name+".tscn" 125 | # Check if the file already exists 126 | if ResourceLoader.exists(scene_path)==true: 127 | print("new Agent2D:agent already exists. Try a new name or remove the agent") 128 | free_my_resources(rb) 129 | return 130 | # Save the Agent in the resource file .tscn 131 | ResourceSaver.save(scene, scene_path) 132 | free_my_resources(rb) 133 | 134 | print("Agent3D : END") 135 | 136 | 137 | func rb_script(): 138 | return """ 139 | @tool 140 | extends RigidBody3D 141 | 142 | @export var state:int = 0 143 | @export var age:int = 0 144 | 145 | func _process(_delta): 146 | if not Engine.is_editor_hint(): 147 | age += 1 148 | 149 | func emit_changed(): 150 | pass 151 | 152 | """ 153 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/new_grid_2d.gd: -------------------------------------------------------------------------------- 1 | ## Create a new Type of 2D Grid 2 | ## into a Type Scene file (.tscn) 3 | ## This grid can be added manually 4 | ## using the Godot Editor 5 | ## or automaticaly (see AddAgent) 6 | ## into the main scene. 7 | 8 | @icon("action_2d.svg") 9 | @tool 10 | 11 | class_name NewGrid2D 12 | extends BehaviorTreeForGroups 13 | 14 | signal prompt_confirmed(input_text: String) 15 | signal prompt_canceled 16 | # Scène principale qui hérite de Node2D 17 | var prompt_instance: PromptDialog 18 | 19 | func _on_prompt_confirmed(input_text: String) -> void: 20 | print("L'utilisateur a validé la saisie : ", input_text) 21 | 22 | func _on_prompt_canceled(input_text: String) -> void: 23 | print("L'utilisateur a annulé la saisie : ", input_text) 24 | queue_free() 25 | 26 | func _enter_tree(): 27 | print("Grid2D : _enter_tree") 28 | 29 | # Creation of the PromptDialog 30 | prompt_instance = PromptDialog.new() 31 | 32 | print("Grid2D : prompt_instance created") 33 | 34 | # Ajout de la scène du prompt comme enfant 35 | #add_child(prompt_instance) 36 | #get_editor_interface().get_base_control().add_child(prompt_instance) 37 | var editor_root = get_tree().root.get_child(0) # Accède à la fenêtre principale de l'éditeur 38 | editor_root.add_child(prompt_instance) 39 | 40 | prompt_instance.min_size = Vector2i(320, 80) 41 | prompt_instance.reset_size() 42 | prompt_instance.move_to_center() 43 | prompt_instance.title = "Name the new 2d grid" 44 | 45 | # Rendre la fenêtre modale pour bloquer les interactions avec l'interface principale 46 | prompt_instance.set_transient(true) 47 | prompt_instance.set_exclusive(true) 48 | 49 | 50 | prompt_instance.close_requested.connect(func(): 51 | prompt_instance._on_cancel_button_pressed() 52 | ) 53 | 54 | # Connexion du signal de confirmation 55 | prompt_instance.prompt_confirmed.connect(_on_prompt_confirmed) 56 | # Connexion du signal d'annulation 57 | prompt_instance.prompt_canceled.connect(_on_prompt_canceled) 58 | 59 | # Attendre que l'utilisateur confirme la fenêtre (bloque l'exécution ici) 60 | # Open the name window and apply the name to the new agent 2d 61 | var result = await prompt_instance.prompt_confirmed 62 | 63 | # The new agent is a .tscn file 64 | # It must have a valid filename 65 | var agent_name:String = result 66 | if agent_name.is_valid_filename() == false: 67 | print("Grid2D : invalid agent name => agent NOT created. Use a valid filename.") 68 | free_my_resources(null) 69 | return 70 | 71 | build_grid_2d(agent_name) 72 | 73 | func free_my_resources(tr:TextureRect): 74 | # Free memory resources 75 | if tr != null: 76 | tr.queue_free() # saved in the .tscn file 77 | self.queue_free() # this node is only made for creating rb 78 | print("Grid2D : Removed from Scene Tree") 79 | 80 | func build_grid_2d(agent_name:String): 81 | # Create the rigidBody3D 82 | var tr:TextureRect = TextureRect.new() 83 | tr.name = agent_name 84 | tr.add_to_group(agent_name, true) 85 | 86 | # Add the Image 87 | var SX:int = 64 88 | var SY:int = 32 89 | var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8) 90 | for x in range(SX): 91 | for y in range(SY): 92 | var rnd:float = 0#randf() 93 | if x == 0 || x == SX-1 || y == 0 || y == SY-1: 94 | img.set_pixel(x,y, Color(rnd,rnd,rnd,1)) 95 | # Put the image into a texture for rendering 96 | tr.set_texture(ImageTexture.create_from_image(img)) 97 | 98 | # Set script to tr 99 | var script = GDScript.new() 100 | script.set_source_code(tr_script()) 101 | script.reload() 102 | tr.set_script(script) 103 | 104 | # Export the new Agent as scene 105 | print("Grid2D : try to save TSCN") 106 | var scene = PackedScene.new() 107 | scene.pack(tr) 108 | var scene_path:String 109 | # Still a lot (it's .tscn files, NOT instances in scene tree!) 110 | scene_path = "res://"+agent_name+".tscn" 111 | # Check if the file already exists 112 | if ResourceLoader.exists(scene_path)==true: 113 | print("new Grid2D:agent already exists. Try a new name or remove the agent") 114 | free_my_resources(tr) 115 | return 116 | # Save the Agent in the resource file .tscn 117 | ResourceSaver.save(scene, scene_path) 118 | free_my_resources(tr) 119 | 120 | print("Grid2D : END") 121 | 122 | func tr_script() -> String: 123 | var scp:Script = load("res://addons/behav_tree_for_groups/grid2d.gd") 124 | return scp.source_code 125 | #return """ 126 | #@tool 127 | #extends TextureRect 128 | #class_name Grid2D 129 | # 130 | #@export var baseColor:Color = Color(0.5,0.5,0.5,0.5) 131 | #@export var diffusionRate = 0.3 132 | #@export var degradationRate = 0.001 133 | #@export var display_value:bool = false 134 | #@export var show_iso:bool = false 135 | # 136 | #@export var SX:int = 64 137 | #@export var SY:int = 32 138 | #@export var loop_x:bool = false 139 | #@export var loop_y:bool = false 140 | # 141 | #@export var state:int = 0 142 | #@export var age:int = 0 143 | # 144 | #var values_t0:PackedFloat32Array = PackedFloat32Array() 145 | #var values_t1:PackedFloat32Array = PackedFloat32Array() 146 | # 147 | #var xmin:float; var xmax:float; var ymin:float;var ymax:float 148 | # 149 | #func _ready(): 150 | #values_t0.resize(SX*SY) 151 | #values_t1.resize(SX*SY) 152 | #for i in range(SX*SY): 153 | #values_t0[i] = 0 154 | # 155 | #if loop_x == true: 156 | #xmin = 0 157 | #xmax = SX 158 | #else: 159 | #xmin = 1 160 | #xmax = SX-1 161 | # 162 | #if loop_y == true: 163 | #ymin = 0 164 | #ymax = SY 165 | #else: 166 | #ymin = 1 167 | #ymax = SY-1 168 | # 169 | # 170 | #func _process(_delta): 171 | #if not Engine.is_editor_hint(): 172 | #diffusion() 173 | #if show_iso == false: 174 | #display_values() 175 | #else: 176 | #display_iso() 177 | #if display_value == true: 178 | #print_value() 179 | #age += 1 180 | # 181 | #func diffusion(): 182 | #for i in range(xmin,xmax): 183 | #for j in range(ymin,ymax): 184 | #var p:int = i+j*SX 185 | #var v0:float = values_t0[ (i+1)%SX+j*SX] 186 | #var v1:float = values_t0[ (i-1+SX)%SX+j*SX] 187 | #var v2:float = values_t0[ i%SX+((j+1)%SY)*SX] 188 | #var v3:float = values_t0[ i%SX+((j-1+SY)%SY)*SX] 189 | #values_t1[p] = (1.0-degradationRate)*(1.0-diffusionRate)*values_t0[p] + diffusionRate*(v0+v1+v2+v3)*0.25 190 | # 191 | #for i in range(SX*SY): 192 | #values_t0[i] = values_t1[i] 193 | # 194 | #func display_values(): 195 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8) 196 | #for i in range(SX): 197 | #for j in range(SY): 198 | #var p:int = i+j*SX 199 | #var v:float = values_t0[p] 200 | #img.set_pixel(i,j,Color(v*baseColor.r,v*baseColor.g,v*baseColor.b,baseColor.a) ) 201 | #set_texture(ImageTexture.create_from_image(img)) 202 | # 203 | #func print_value(): 204 | #var i:int = randi_range(0, SX-1) 205 | #var j:int = randi_range(0, SY-1) 206 | #var v:float = values_t0[i+j*SX] 207 | #print("At (" + str(i) + "," + str(j) + ")=" + str(num_zeros(v)) + "<=" + str(v) ) 208 | # 209 | #func num_zeros(val:float) -> int: 210 | #var n:int = 0 211 | #if val != 0: 212 | #n = -floor( log(abs(val)) / log(10) ) - 1 213 | #return n 214 | # 215 | #func display_iso(): 216 | #var img:Image = Image.create(SX,SY,false, Image.FORMAT_RGBA8) 217 | #var r:float; var g:float; var b:float 218 | #for i in range(1,SX-2): 219 | #for j in range(1,SY-2): 220 | #var p:int = i+j*SX 221 | #var v0:float = num_zeros(values_t0[p]) 222 | #var vg:float = num_zeros(values_t0[p-1]) 223 | #var vd:float = num_zeros(values_t0[p+1]) 224 | #var vh:float = num_zeros(values_t0[p-SX]) 225 | #var vb:float = num_zeros(values_t0[p+SX]) 226 | #var e:float = 1.0 227 | #if vg>v0 || vd>v0 || vh>v0 || vb>v0: 228 | #e = 0.5 229 | #img.set_pixel(i,j,Color(e*baseColor.r,e*baseColor.g,e*baseColor.b,baseColor.a) ) 230 | #set_texture(ImageTexture.create_from_image(img)) 231 | # 232 | #""" 233 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/parallel.gd: -------------------------------------------------------------------------------- 1 | ## Execute all its children 2 | 3 | @icon("parallel.svg") 4 | class_name Parallel 5 | extends BehaviorTreeForGroups 6 | 7 | @export var activated:bool = true 8 | 9 | # Called every frame. 'delta' is the elapsed time since the previous frame. 10 | func biodyn_process(agent)->bool: 11 | # Parallel Node 12 | # Execute all its children, stops after ALL children execution 13 | # Return True when at leat ONE child returns True 14 | if activated == false: 15 | return false 16 | var overall_success:bool = false 17 | for behav in self.get_children(): 18 | var success = behav.biodyn_process(agent) 19 | if success == true: 20 | overall_success = true 21 | return overall_success 22 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/parallel.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | 39 | Created by potrace 1.15, written by Peter Selinger 2001-2017 40 | 41 | 47 | 51 | 52 | 58 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/parallel.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c5i55nkua68w6" 6 | path="res://.godot/imported/parallel.svg-bb539307c1dace5e872ffa4400740c3d.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/parallel.svg" 14 | dest_files=["res://.godot/imported/parallel.svg-bb539307c1dace5e872ffa4400740c3d.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Behavior Tree for Groups" 4 | description="Add a behavior tree to node's groups and create swarms, flocks and multiagent systems." 5 | author="Pascal Ballet" 6 | version="2.0" 7 | script="behavior_tree_for_groups_plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/print_message.gd: -------------------------------------------------------------------------------- 1 | ## Print a message into 2 | ## the Godot Output Window. 3 | 4 | @icon("action.svg") 5 | class_name PrintMessage 6 | extends BehaviorTreeForGroups 7 | 8 | ## Message to print 9 | @export var message:String = "" 10 | ## Data to print 11 | @export var data:String = "" 12 | ## Blackboard reference to print 13 | @export var reference:String = "" 14 | 15 | func biodyn_process(agent)->bool: 16 | var msg:String = message 17 | if agent.has_meta(data): 18 | msg += ":"+data+" = " + agent.get_meta(data) 19 | var root:Node = get_tree().current_scene 20 | if root.has_meta(reference): 21 | msg += ":"+reference+" = " + root.get_meta(reference) 22 | 23 | print(msg) 24 | return true 25 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/prompt_dialog.gd: -------------------------------------------------------------------------------- 1 | ## PromptDialog class asking for the name of a new agent 2 | 3 | extends Window 4 | 5 | class_name PromptDialog 6 | 7 | var input_field: LineEdit 8 | 9 | signal prompt_confirmed(input_text: String) 10 | signal prompt_canceled 11 | 12 | func _init(): 13 | pass 14 | 15 | func _ready() -> void: 16 | # Vertical Box Container to put the Line Edit 17 | # and the OK and CANCEL buttons 18 | var vbox:VBoxContainer = VBoxContainer.new() 19 | vbox.set_anchors_preset(Control.PRESET_FULL_RECT) 20 | # Set light grey background color 21 | var style = StyleBoxFlat.new() 22 | style.bg_color = Color(0.9, 0.0, 0.9, 1.0) # Light grey color 23 | vbox.add_theme_stylebox_override("panel", style) 24 | # Add a MarginContainer for better spacing 25 | var margin = MarginContainer.new() 26 | margin.add_theme_constant_override("margin_left", 16) 27 | margin.add_theme_constant_override("margin_right", 16) 28 | vbox.add_child(margin) 29 | 30 | # LineEdit creation to enter the 2d agent name 31 | input_field = LineEdit.new() 32 | input_field.alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER 33 | input_field.expand_to_text_length = true 34 | input_field.placeholder_text = "agent_name" 35 | vbox.add_child(input_field) 36 | 37 | # HBox creation to put Buttons OK and CANCEL 38 | var hbox:HBoxContainer = HBoxContainer.new() 39 | hbox.set_anchors_preset(Control.PRESET_FULL_RECT) 40 | hbox.size_flags_horizontal = Control.SIZE_SHRINK_CENTER 41 | hbox.add_theme_constant_override("separation", 10) # Space between buttons 42 | vbox.add_child(hbox) 43 | 44 | # OK button creation 45 | var ok_button = Button.new() 46 | ok_button.text = "OK" 47 | ok_button.pressed.connect(self._on_ok_button_pressed) 48 | ok_button.size_flags_horizontal = Control.SIZE_FILL 49 | set_button_style(ok_button, Color(0.0, 0.6, 0.0, 1.0)) 50 | hbox.add_child(ok_button) 51 | 52 | # CANCEL button creation 53 | var cancel_button = Button.new() 54 | cancel_button.text = "CANCEL" 55 | cancel_button.pressed.connect(self._on_cancel_button_pressed) 56 | set_button_style(cancel_button, Color(0.6, 0.0, 0.0, 1.0)) 57 | hbox.add_child(cancel_button) 58 | 59 | # Add the VBox to the modal prompt Window 60 | add_child(vbox) 61 | 62 | # Set the style of a given button 63 | func set_button_style(button:Button, text_color:Color): 64 | # Create button styles 65 | var normal_style = StyleBoxFlat.new() 66 | normal_style.bg_color = Color(0.6, 0.6, 0.6, 1.0) 67 | normal_style.corner_radius_top_left = 4 68 | normal_style.corner_radius_top_right = 4 69 | normal_style.corner_radius_bottom_left = 4 70 | normal_style.corner_radius_bottom_right = 4 71 | 72 | var hover_style = StyleBoxFlat.new() 73 | hover_style.bg_color = Color(0.8, 0.8, 0.8, 1.0) 74 | hover_style.corner_radius_top_left = 4 75 | hover_style.corner_radius_top_right = 4 76 | hover_style.corner_radius_bottom_left = 4 77 | hover_style.corner_radius_bottom_right = 4 78 | 79 | var pressed_style = StyleBoxFlat.new() 80 | pressed_style.bg_color = Color(0.85, 0.85, 0.85, 1.0) 81 | pressed_style.corner_radius_top_left = 4 82 | pressed_style.corner_radius_top_right = 4 83 | pressed_style.corner_radius_bottom_left = 4 84 | pressed_style.corner_radius_bottom_right = 4 85 | 86 | # Apply styles to button 87 | button.add_theme_stylebox_override("normal", normal_style) 88 | button.add_theme_stylebox_override("hover", hover_style) 89 | button.add_theme_stylebox_override("pressed", pressed_style) 90 | 91 | # Add padding to button 92 | button.custom_minimum_size.x = 100 93 | button.custom_minimum_size.y = 30 94 | 95 | # Set button text color 96 | button.add_theme_color_override("font_color", Color.WHITE) 97 | button.add_theme_color_override("font_hover_color", text_color) 98 | 99 | # Events from the buttons 100 | func _on_ok_button_pressed() -> void: 101 | emit_signal("prompt_confirmed", input_field.text) 102 | hide() 103 | print("PromptDialog : _on_ok_button_pressed") 104 | 105 | func _on_cancel_button_pressed() -> void: 106 | emit_signal("prompt_canceled", "") 107 | hide() 108 | print("PromptDialog : _on_cancel_button_pressed") 109 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/sequential.gd: -------------------------------------------------------------------------------- 1 | ## Execute its children 2 | ## upto one of them fails 3 | ## (return false) 4 | 5 | @icon("sequential.svg") 6 | class_name Sequential 7 | extends BehaviorTreeForGroups 8 | 9 | ## Activate / unactivate this sequence 10 | @export var activated:bool = true 11 | 12 | func biodyn_process(agent)->bool: 13 | # Sequential Node 14 | # Execute all its children, stops 15 | # a) after the 1st Failed 16 | # b) or after ALL children execution succeded 17 | # Return False if ONE of its children fail. 18 | # Returns True if all succeeded 19 | if activated == false: 20 | return false 21 | for behav in self.get_children(): 22 | var success = behav.biodyn_process(agent) 23 | if success == false: 24 | return false 25 | return true 26 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/sequential.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 37 | 39 | Created by potrace 1.15, written by Peter Selinger 2001-2017 40 | 41 | 47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/sequential.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b1djd0cc1vk3h" 6 | path="res://.godot/imported/sequential.svg-44b8b3071cabbf19b9116d22a23d7582.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/behav_tree_for_groups/sequential.svg" 14 | dest_files=["res://.godot/imported/sequential.svg-44b8b3071cabbf19b9116d22a23d7582.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/set_age.gd: -------------------------------------------------------------------------------- 1 | ## Set an int to a current agent's age 2 | 3 | @icon("action.svg") 4 | class_name SetAge 5 | extends BehaviorTreeForGroups 6 | 7 | ## New agent's age value 8 | @export var age:int = 0 9 | 10 | func biodyn_process(agent:Node)->bool: 11 | agent.age = age 12 | return true 13 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/set_grid_value_2d.gd: -------------------------------------------------------------------------------- 1 | ## Set a float value inside a Grid2D 2 | ## at the location of the current agent 3 | 4 | @icon("action_2d.svg") 5 | class_name SetGridValue2D 6 | extends BehaviorTreeForGroups 7 | 8 | @export var field:String = "" 9 | @export var set_value:float = 0.5 10 | 11 | var grids:Array = Array() 12 | 13 | func _ready(): 14 | for gp in self.get_groups(): 15 | var sous_grids = get_tree().get_nodes_in_group(gp) 16 | for sg in sous_grids: 17 | if "fields" in sg: 18 | grids.push_back(sg) 19 | 20 | func biodyn_process(agent)->bool: 21 | for grid in grids: 22 | # 2D 23 | if agent is Node2D and "values_t0" in grid: 24 | var ax:float = agent.position.x 25 | var ay:float = agent.position.y 26 | var gx_min:float = grid.position.x 27 | var gx_max:float = gx_min+grid.size.x 28 | var gy_min:float = grid.position.y 29 | var gy_max:float = gy_min+grid.size.y 30 | if ax >= gx_min && ax < gx_max: 31 | if ay >= gy_min && ay < gy_max: 32 | var px:int = ((ax - gx_min) / grid.size.x) * grid.SX 33 | var py:int = ((ay - gy_min) / grid.size.y) * grid.SY 34 | var p:int = px+py*grid.SX 35 | if grid.fields_dico.has(field) == true: 36 | grid.values_t0[p].values[grid.fields_dico[field]] = set_value 37 | return true 38 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/set_state.gd: -------------------------------------------------------------------------------- 1 | ## Set the state of the current agent 2 | 3 | @icon("action.svg") 4 | class_name SetState 5 | extends BehaviorTreeForGroups 6 | 7 | ## New agent's state value 8 | @export var set_to_value:int = 0 9 | var update_state_at_age:int = -1 10 | var agt:Node = null 11 | 12 | func biodyn_process(agent:Node)->bool: 13 | try_update_state() 14 | if agent.state != set_to_value: 15 | update_state_at_age = agent.age+1 16 | agt = agent 17 | 18 | return true 19 | 20 | func _process(_delta): 21 | try_update_state() 22 | 23 | func try_update_state(): 24 | if update_state_at_age != -1: 25 | if is_instance_valid(agt): 26 | if update_state_at_age <= agt.age: 27 | agt.state = set_to_value 28 | update_state_at_age = -1 29 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/stay_in_box.gd: -------------------------------------------------------------------------------- 1 | ## Force the current agent 2 | ## to stay inside a 2D or 3D box 3 | 4 | @tool 5 | @icon("action.svg") 6 | 7 | class_name StayInBox 8 | extends BehaviorTreeForGroups 9 | 10 | @export var min:Vector3 = Vector3(-5,-5,-5) 11 | @export var max:Vector3 = Vector3( 5, 5, 5) 12 | @export var loop_x:bool = false 13 | @export var loop_y:bool = false 14 | @export var loop_z:bool = false 15 | 16 | func biodyn_process(agent:Node) -> bool: 17 | if agent is Node3D: 18 | var x:float = agent.position.x 19 | var y:float = agent.position.y 20 | var z:float = agent.position.z 21 | 22 | var new_x:float = x 23 | var new_y:float = y 24 | var new_z:float = z 25 | 26 | var out_of_box = false 27 | 28 | # X Axis 29 | if x < min.x: 30 | out_of_box = true 31 | if loop_x == true: 32 | new_x = max.x 33 | else: 34 | new_x = min.x 35 | if agent is RigidBody3D: 36 | (agent as RigidBody3D).linear_velocity.x = - (agent as RigidBody3D).linear_velocity.x 37 | 38 | if x > max.x: 39 | out_of_box = true 40 | if loop_x == true: 41 | new_x = min.x 42 | else: 43 | new_x = max.x 44 | if agent is RigidBody3D: 45 | (agent as RigidBody3D).linear_velocity.x = - (agent as RigidBody3D).linear_velocity.x 46 | 47 | # Y Axis 48 | if y < min.y: 49 | out_of_box = true 50 | if loop_y == true: 51 | new_y = max.y 52 | else: 53 | new_y = min.y 54 | if agent is RigidBody3D: 55 | (agent as RigidBody3D).linear_velocity.y = - (agent as RigidBody3D).linear_velocity.y 56 | 57 | if y > max.y: 58 | out_of_box = true 59 | if loop_y == true: 60 | new_y = min.y 61 | else: 62 | new_y = max.y 63 | if agent is RigidBody3D: 64 | (agent as RigidBody3D).linear_velocity.y = - (agent as RigidBody3D).linear_velocity.y 65 | 66 | # Z Axis 67 | if z < min.z: 68 | out_of_box = true 69 | if loop_z == true: 70 | new_z = max.z 71 | else: 72 | new_z = min.z 73 | if agent is RigidBody3D: 74 | (agent as RigidBody3D).linear_velocity.z = - (agent as RigidBody3D).linear_velocity.z 75 | 76 | if z > max.z: 77 | out_of_box = true 78 | if loop_z == true: 79 | new_z = min.z 80 | else: 81 | new_z = max.z 82 | if agent is RigidBody3D: 83 | (agent as RigidBody3D).linear_velocity.z = - (agent as RigidBody3D).linear_velocity.z 84 | 85 | if out_of_box == true: 86 | #agent.position = Vector3(new_x,new_y,new_z) 87 | agent.global_transform.origin = Vector3(new_x,new_y,new_z) 88 | return true 89 | 90 | if agent is Node2D: 91 | var x:float = agent.position.x 92 | var y:float = agent.position.y 93 | 94 | var new_x:float = x 95 | var new_y:float = y 96 | 97 | var out_of_box = false 98 | 99 | # X Axis 100 | if x < min.x: 101 | out_of_box = true 102 | if loop_x == true: 103 | new_x = max.x 104 | else: 105 | new_x = min.x 106 | if agent is RigidBody2D: 107 | (agent as RigidBody2D).linear_velocity.x = - (agent as RigidBody2D).linear_velocity.x 108 | 109 | if x > max.x: 110 | out_of_box = true 111 | if loop_x == true: 112 | new_x = min.x 113 | else: 114 | new_x = max.x 115 | if agent is RigidBody2D: 116 | (agent as RigidBody2D).linear_velocity.x = - (agent as RigidBody2D).linear_velocity.x 117 | 118 | # Y Axis 119 | if y < min.y: 120 | out_of_box = true 121 | if loop_y == true: 122 | new_y = max.y 123 | else: 124 | new_y = min.y 125 | if agent is RigidBody2D: 126 | (agent as RigidBody2D).linear_velocity.y = - (agent as RigidBody2D).linear_velocity.y 127 | 128 | if y > max.y: 129 | out_of_box = true 130 | if loop_y == true: 131 | new_y = min.y 132 | else: 133 | new_y = max.y 134 | if agent is RigidBody2D: 135 | (agent as RigidBody2D).linear_velocity.y = - (agent as RigidBody2D).linear_velocity.y 136 | 137 | if out_of_box == true: 138 | agent.global_transform.origin = Vector2(new_x,new_y) 139 | # agent.position.x = new_x 140 | # agent.position.y = new_y 141 | return true 142 | 143 | return false 144 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/torque_global.gd: -------------------------------------------------------------------------------- 1 | ## Apply a torque on the current agent 2 | ## according to the absolute axis reference 3 | 4 | @icon("action.svg") 5 | class_name TorqueGlobal 6 | extends BehaviorTreeForGroups 7 | 8 | @export var rx:float = 0.0 9 | @export var ry:float = 0.0 10 | @export var rz:float = 0.0 11 | 12 | func biodyn_process(agent)->bool: 13 | if agent is RigidBody3D: 14 | agent.apply_torque_impulse ( Vector3 (rx, ry, rz) ) 15 | return true 16 | 17 | if agent is RigidBody2D: 18 | agent.apply_torque_impulse ( rz ) 19 | return true 20 | 21 | return false 22 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/torque_random.gd: -------------------------------------------------------------------------------- 1 | ## Apply a random torque on the current agent. 2 | 3 | @icon("action.svg") 4 | class_name TorqueRandom 5 | extends BehaviorTreeForGroups 6 | 7 | @export var rx:float = 1.0 8 | @export var ry:float = 1.0 9 | @export var rz:float = 1.0 10 | 11 | func biodyn_process(agent)->bool: 12 | if agent is Node3D: 13 | var rrx:float = rx * (randf() - 0.5) 14 | var rry:float = ry * (randf() - 0.5) 15 | var rrz:float = rz * (randf() - 0.5) 16 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) ) 17 | agent.apply_torque_impulse ( Vector3 (rrx, rry, rrz) ) 18 | return true 19 | 20 | if agent is Node2D: 21 | var rrz:float = rz * (randf() - 0.5) 22 | #call_deferred("agent.apply_central_force", Vector3 (ffx, ffy, ffz) ) 23 | agent.apply_torque_impulse ( rrz ) 24 | return true 25 | 26 | return false 27 | -------------------------------------------------------------------------------- /addons/behav_tree_for_groups/translate_random.gd: -------------------------------------------------------------------------------- 1 | ## Apply a random translation 2 | ## on the current agent. 3 | 4 | @icon("action.svg") 5 | class_name TranslateRandom 6 | extends BehaviorTreeForGroups 7 | 8 | ## Maximum sizes of the random vector 9 | @export var delta:Vector3 = Vector3(1,1,1) 10 | 11 | func biodyn_process(agent)->bool: 12 | if agent is Node3D: 13 | var ddx:float = randf()*delta.x - delta.x / 2.0 14 | var ddy:float = randf()*delta.y - delta.y / 2.0 15 | var ddz:float = randf()*delta.z - delta.z / 2.0 16 | agent.translate ( Vector3 (ddx, ddy, ddz) ) 17 | return true 18 | 19 | if agent is Node2D: 20 | var ddx:float = randf()*delta.x - delta.x / 2.0 21 | var ddy:float = randf()*delta.y - delta.y / 2.0 22 | agent.translate ( Vector2 (ddx, ddy) ) 23 | return true 24 | 25 | return false 26 | -------------------------------------------------------------------------------- /doc/behavior_tree_for_groups.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/doc/behavior_tree_for_groups.pdf -------------------------------------------------------------------------------- /examples/2d_tutorial/agent_2d_0.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://dsdilworfnl1q"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_3rvo1"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | 15 | func _enter_tree(): 16 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 17 | set_name.call_deferred(new_name) 18 | " 19 | 20 | [sub_resource type="CircleShape2D" id="CircleShape2D_qmo1i"] 21 | 22 | [node name="agent_2d_0" type="RigidBody2D" groups=["test_group"]] 23 | gravity_scale = 0.0 24 | contact_monitor = true 25 | max_contacts_reported = 2 26 | linear_damp = 1.0 27 | angular_damp = 1.0 28 | script = SubResource("GDScript_3rvo1") 29 | 30 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 31 | shape = SubResource("CircleShape2D_qmo1i") 32 | 33 | [node name="Polygon2D" type="Polygon2D" parent="."] 34 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 35 | -------------------------------------------------------------------------------- /examples/2d_tutorial/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://b43rx2enqvlnj"] 2 | 3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_8qv0k"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_vp25h"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/translate_random.gd" id="3_pbt64"] 6 | [ext_resource type="PackedScene" uid="uid://dsdilworfnl1q" path="res://examples/2d_tutorial/agent_2d_0.tscn" id="4_7458n"] 7 | 8 | [node name="main" type="Node2D"] 9 | 10 | [node name="BehaviorTreeForGroups" type="Node" parent="."] 11 | script = ExtResource("1_8qv0k") 12 | 13 | [node name="Behavior" type="Node" parent="BehaviorTreeForGroups" groups=["test_group"]] 14 | script = ExtResource("2_vp25h") 15 | 16 | [node name="TranslateRandom" type="Node" parent="BehaviorTreeForGroups/Behavior"] 17 | script = ExtResource("3_pbt64") 18 | delta = Vector3(3, 3, 3) 19 | 20 | [node name="agent_2d_0" parent="." instance=ExtResource("4_7458n")] 21 | position = Vector2(146, 276) 22 | 23 | [node name="agent_2d_1" parent="." instance=ExtResource("4_7458n")] 24 | position = Vector2(160, 225) 25 | 26 | [node name="agent_2d_2" parent="." instance=ExtResource("4_7458n")] 27 | position = Vector2(107, 246) 28 | 29 | [node name="agent_2d_3" parent="." instance=ExtResource("4_7458n")] 30 | position = Vector2(249, 253) 31 | 32 | [node name="agent_2d_4" parent="." instance=ExtResource("4_7458n")] 33 | position = Vector2(207, 212) 34 | 35 | [node name="agent_2d_5" parent="." instance=ExtResource("4_7458n")] 36 | position = Vector2(196, 250) 37 | 38 | [node name="agent_2d_6" parent="." instance=ExtResource("4_7458n")] 39 | position = Vector2(214, 282) 40 | 41 | [node name="agent_2d_7" parent="." instance=ExtResource("4_7458n")] 42 | position = Vector2(129, 202) 43 | -------------------------------------------------------------------------------- /examples/bacteria_colony/bact.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bh4ftosmek2wy"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_oxsuj"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"] 17 | 18 | [node name="Bact" type="RigidBody2D" groups=["bact"]] 19 | mass = 100.0 20 | gravity_scale = 0.0 21 | contact_monitor = true 22 | max_contacts_reported = 2 23 | linear_damp = 1.0 24 | angular_damp = 1.0 25 | script = SubResource("GDScript_oxsuj") 26 | 27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 28 | shape = SubResource("CircleShape2D_deou3") 29 | 30 | [node name="Polygon2D" type="Polygon2D" parent="."] 31 | color = Color(1, 0, 0.0431373, 1) 32 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 33 | -------------------------------------------------------------------------------- /examples/bacteria_colony/gluc.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bx4xylu7e1eag"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_oxsuj"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"] 17 | 18 | [node name="Gluc" type="RigidBody2D" groups=["gluc"]] 19 | gravity_scale = 0.0 20 | contact_monitor = true 21 | max_contacts_reported = 2 22 | linear_damp = 1.0 23 | angular_damp = 1.0 24 | script = SubResource("GDScript_oxsuj") 25 | 26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 27 | shape = SubResource("CircleShape2D_deou3") 28 | 29 | [node name="Polygon2D" type="Polygon2D" parent="."] 30 | color = Color(0, 1, 0.0666667, 1) 31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 32 | -------------------------------------------------------------------------------- /examples/bacteria_colony/ker.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://3evit7hlnoq3"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_oxsuj"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_deou3"] 17 | 18 | [node name="Ker" type="RigidBody2D"] 19 | mass = 1000.0 20 | gravity_scale = 0.0 21 | contact_monitor = true 22 | max_contacts_reported = 2 23 | linear_damp = 1.0 24 | angular_damp = 1.0 25 | script = SubResource("GDScript_oxsuj") 26 | 27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 28 | scale = Vector2(10, 10) 29 | shape = SubResource("CircleShape2D_deou3") 30 | 31 | [node name="Polygon2D" type="Polygon2D" parent="."] 32 | scale = Vector2(10, 10) 33 | color = Color(1, 0.482353, 0, 1) 34 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 35 | -------------------------------------------------------------------------------- /examples/coag/coag.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=17 format=3 uid="uid://dfu0f4ml38di0"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://dl1mi18kqpcki" path="res://examples/coag/ma_grille.tscn" id="1_2thtx"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_q4mpb"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/field.gd" id="2_2xt6c"] 6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_mfvur"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/reaction.gd" id="3_4oj5n"] 8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/set_grid_value_2d.gd" id="3_k5ybw"] 9 | [ext_resource type="PackedScene" uid="uid://m6hkrylkreko" path="res://examples/coag/fibro.tscn" id="4_a54p3"] 10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="4_kqs1l"] 11 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="5_n2l44"] 12 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_grid_2d_value_sup.gd" id="6_pl66x"] 13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_agent.gd" id="7_n45if"] 14 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="8_duvfc"] 15 | 16 | [sub_resource type="Resource" id="Resource_q6ab2"] 17 | script = ExtResource("2_2xt6c") 18 | name = "A" 19 | color = Color(0, 0, 1, 1) 20 | diffusion_speed = 0.001 21 | degradation_speed = 0.01 22 | initialisation = "Random" 23 | 24 | [sub_resource type="Resource" id="Resource_dhys0"] 25 | script = ExtResource("2_2xt6c") 26 | name = "Field" 27 | color = Color(0, 1, 0, 1) 28 | diffusion_speed = 0.001 29 | degradation_speed = 0.01 30 | initialisation = "Random" 31 | 32 | [sub_resource type="Resource" id="Resource_lb84g"] 33 | script = ExtResource("2_2xt6c") 34 | name = "C" 35 | color = Color(1, 0.205149, 0.393126, 1) 36 | diffusion_speed = 0.3 37 | degradation_speed = 0.001 38 | initialisation = "0" 39 | 40 | [sub_resource type="Resource" id="Resource_p1nvq"] 41 | script = ExtResource("3_4oj5n") 42 | reactive_1 = "A" 43 | reactive_2 = "B" 44 | reactive_3 = "" 45 | speed = 0.01 46 | product_1 = "C" 47 | product_2 = "" 48 | product_3 = "" 49 | 50 | [node name="coag" type="Node2D"] 51 | 52 | [node name="BehaviorTreeForGroups" type="Node" parent="."] 53 | script = ExtResource("1_q4mpb") 54 | 55 | [node name="Secretion" type="Node" parent="BehaviorTreeForGroups" groups=["Fibro"]] 56 | script = ExtResource("2_mfvur") 57 | 58 | [node name="SetGridValue2D" type="Node" parent="BehaviorTreeForGroups/Secretion"] 59 | script = ExtResource("3_k5ybw") 60 | on_grid_group = "ma_grille" 61 | for_field = "A" 62 | set_value = 1.0 63 | 64 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Secretion"] 65 | script = ExtResource("4_kqs1l") 66 | F = Vector3(10, 10, 0) 67 | 68 | [node name="ActivationMacrophage" type="Node" parent="BehaviorTreeForGroups"] 69 | script = ExtResource("2_mfvur") 70 | 71 | [node name="Sequential" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage"] 72 | script = ExtResource("5_n2l44") 73 | 74 | [node name="IfGrid2DValueSup" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"] 75 | script = ExtResource("6_pl66x") 76 | 77 | [node name="AddAgent" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"] 78 | script = ExtResource("7_n45if") 79 | 80 | [node name="Delete" type="Node" parent="BehaviorTreeForGroups/ActivationMacrophage/Sequential"] 81 | script = ExtResource("8_duvfc") 82 | 83 | [node name="ma_grille" parent="." instance=ExtResource("1_2thtx")] 84 | offset_left = 110.0 85 | offset_top = 80.0 86 | offset_right = 1060.0 87 | offset_bottom = 596.0 88 | fields = Array[ExtResource("2_2xt6c")]([SubResource("Resource_q6ab2"), SubResource("Resource_dhys0"), SubResource("Resource_lb84g")]) 89 | reactions = Array[ExtResource("3_4oj5n")]([SubResource("Resource_p1nvq")]) 90 | 91 | [node name="Fibro" parent="." instance=ExtResource("4_a54p3")] 92 | position = Vector2(383, 361) 93 | -------------------------------------------------------------------------------- /examples/coag/fibro.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://m6hkrylkreko"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_80yq4"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | 15 | " 16 | 17 | [sub_resource type="CircleShape2D" id="CircleShape2D_up5f6"] 18 | 19 | [node name="Fibro" type="RigidBody2D" groups=["Fibro"]] 20 | gravity_scale = 0.0 21 | contact_monitor = true 22 | max_contacts_reported = 2 23 | linear_damp = 1.0 24 | angular_damp = 1.0 25 | script = SubResource("GDScript_80yq4") 26 | 27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 28 | shape = SubResource("CircleShape2D_up5f6") 29 | 30 | [node name="Polygon2D" type="Polygon2D" parent="."] 31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 32 | -------------------------------------------------------------------------------- /examples/coagulation/FA.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bw71fvacgc6sk"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_6aa4s"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_whlnq"] 17 | 18 | [node name="FA" type="RigidBody2D" groups=["FA", "circulating"]] 19 | gravity_scale = 0.0 20 | contact_monitor = true 21 | max_contacts_reported = 2 22 | linear_damp = 1.0 23 | angular_damp = 1.0 24 | script = SubResource("GDScript_6aa4s") 25 | 26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 27 | scale = Vector2(0.5, 0.5) 28 | shape = SubResource("CircleShape2D_whlnq") 29 | 30 | [node name="Polygon2D" type="Polygon2D" parent="."] 31 | scale = Vector2(0.5, 0.5) 32 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 33 | -------------------------------------------------------------------------------- /examples/coagulation/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/Thumbs.db -------------------------------------------------------------------------------- /examples/coagulation/factors.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://weluiq846o2x"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_g40xn"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _enter_tree(): 12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 13 | set_name.call_deferred(new_name) 14 | 15 | " 16 | 17 | [sub_resource type="CircleShape2D" id="CircleShape2D_xyohc"] 18 | radius = 4.0 19 | 20 | [node name="Factors" type="RigidBody2D" groups=["factors"]] 21 | collision_layer = 2 22 | collision_mask = 2 23 | mass = 0.1 24 | gravity_scale = 0.0 25 | max_contacts_reported = 2 26 | contact_monitor = true 27 | linear_damp = 1.0 28 | angular_damp = 1.0 29 | script = SubResource("GDScript_g40xn") 30 | 31 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 32 | shape = SubResource("CircleShape2D_xyohc") 33 | 34 | [node name="Polygon2D" type="Polygon2D" parent="."] 35 | scale = Vector2(0.4, 0.404145) 36 | color = Color(1, 0.290196, 0, 1) 37 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 38 | -------------------------------------------------------------------------------- /examples/coagulation/lesion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/lesion.png -------------------------------------------------------------------------------- /examples/coagulation/lesion.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dsnumjw110fjy" 6 | path="res://.godot/imported/lesion.png-a04a2f0deb9866341dcc73d994083952.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://examples/coagulation/lesion.png" 14 | dest_files=["res://.godot/imported/lesion.png-a04a2f0deb9866341dcc73d994083952.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /examples/coagulation/lesion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://8d1mmxxnxnxy"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_nyy48"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _enter_tree(): 12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 13 | set_name.call_deferred(new_name) 14 | 15 | 16 | func _process(_delta): 17 | if not Engine.is_editor_hint(): 18 | age += 1 19 | 20 | " 21 | 22 | [sub_resource type="CircleShape2D" id="CircleShape2D_ikg3t"] 23 | 24 | [node name="lesion" type="RigidBody2D" groups=["fibro"]] 25 | gravity_scale = 0.0 26 | freeze = true 27 | freeze_mode = 1 28 | max_contacts_reported = 5 29 | contact_monitor = true 30 | linear_damp = 1.0 31 | angular_damp = 1.0 32 | script = SubResource("GDScript_nyy48") 33 | state = 1 34 | age = 3678 35 | 36 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 37 | shape = SubResource("CircleShape2D_ikg3t") 38 | 39 | [node name="Polygon2D" type="Polygon2D" parent="."] 40 | color = Color(1, 0.368627, 0.690196, 1) 41 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 42 | -------------------------------------------------------------------------------- /examples/coagulation/platelet.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://c7hylydq3sl81"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_oq8p4"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _enter_tree(): 12 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 13 | set_name.call_deferred(new_name) 14 | 15 | 16 | func _process(_delta): 17 | if not Engine.is_editor_hint(): 18 | age += 1 19 | 20 | " 21 | 22 | [sub_resource type="CircleShape2D" id="CircleShape2D_rgg7l"] 23 | 24 | [node name="platelet" type="RigidBody2D" groups=["circulating", "platelet"]] 25 | collision_mask = 3 26 | gravity_scale = 0.0 27 | max_contacts_reported = 4 28 | contact_monitor = true 29 | linear_damp = 1.0 30 | angular_damp = 1.0 31 | script = SubResource("GDScript_oq8p4") 32 | age = 15724 33 | 34 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 35 | shape = SubResource("CircleShape2D_rgg7l") 36 | 37 | [node name="Polygon2D" type="Polygon2D" parent="."] 38 | color = Color(0.564706, 0.603922, 1, 1) 39 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 40 | -------------------------------------------------------------------------------- /examples/coagulation/sphere_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/coagulation/sphere_64x64.png -------------------------------------------------------------------------------- /examples/coagulation/sphere_64x64.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b7wtmuys4ctgj" 6 | path="res://.godot/imported/sphere_64x64.png-7405549ae7fa038ee7fb77f228b2c7a3.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://examples/coagulation/sphere_64x64.png" 14 | dest_files=["res://.godot/imported/sphere_64x64.png-7405549ae7fa038ee7fb77f228b2c7a3.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /examples/flow_2d/cell.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://i28u32im7gm4"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_kww5j"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | func _enter_tree(): 9 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 10 | set_name.call_deferred(new_name) 11 | 12 | " 13 | 14 | [sub_resource type="CircleShape2D" id="CircleShape2D_n3lcf"] 15 | 16 | [node name="Cell" type="RigidBody2D" groups=["cell"]] 17 | gravity_scale = 0.0 18 | max_contacts_reported = 2 19 | contact_monitor = true 20 | linear_damp = 1.0 21 | angular_damp = 1.0 22 | script = SubResource("GDScript_kww5j") 23 | 24 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 25 | shape = SubResource("CircleShape2D_n3lcf") 26 | 27 | [node name="Polygon2D" type="Polygon2D" parent="."] 28 | color = Color(1, 0.0509804, 0.45098, 1) 29 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 30 | -------------------------------------------------------------------------------- /examples/flow_2d/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://dpaaye4b1ct5e"] 2 | 3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_qevbp"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_21fqr"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_rck85"] 6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="4_q10aq"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="5_hquvo"] 8 | [ext_resource type="PackedScene" uid="uid://i28u32im7gm4" path="res://examples/flow_2d/cell.tscn" id="6_ko71e"] 9 | 10 | [node name="Flow2D" type="Node2D"] 11 | 12 | [node name="BehavTreeForGroups" type="Node" parent="."] 13 | script = ExtResource("1_qevbp") 14 | 15 | [node name="Behavior" type="Node" parent="BehavTreeForGroups" groups=["cell"]] 16 | script = ExtResource("2_21fqr") 17 | 18 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Behavior"] 19 | script = ExtResource("3_rck85") 20 | 21 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Behavior"] 22 | script = ExtResource("5_hquvo") 23 | fx = 2.0 24 | 25 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Behavior"] 26 | script = ExtResource("4_q10aq") 27 | min = Vector3(200, 100, 0) 28 | max = Vector3(600, 200, 0) 29 | loop_x = true 30 | 31 | [node name="ColorRect" type="ColorRect" parent="."] 32 | offset_left = 200.0 33 | offset_top = 100.0 34 | offset_right = 600.0 35 | offset_bottom = 200.0 36 | color = Color(0.313726, 0.258824, 1, 0.290196) 37 | 38 | [node name="cell" parent="." instance=ExtResource("6_ko71e")] 39 | position = Vector2(259, 161) 40 | 41 | [node name="cell2" parent="." instance=ExtResource("6_ko71e")] 42 | position = Vector2(281, 146) 43 | 44 | [node name="cell3" parent="." instance=ExtResource("6_ko71e")] 45 | position = Vector2(236, 137) 46 | 47 | [node name="cell4" parent="." instance=ExtResource("6_ko71e")] 48 | position = Vector2(258, 122) 49 | 50 | [node name="cell5" parent="." instance=ExtResource("6_ko71e")] 51 | position = Vector2(328, 187) 52 | 53 | [node name="cell6" parent="." instance=ExtResource("6_ko71e")] 54 | position = Vector2(350, 172) 55 | 56 | [node name="cell7" parent="." instance=ExtResource("6_ko71e")] 57 | position = Vector2(305, 163) 58 | 59 | [node name="cell8" parent="." instance=ExtResource("6_ko71e")] 60 | position = Vector2(327, 148) 61 | 62 | [node name="cell9" parent="." instance=ExtResource("6_ko71e")] 63 | position = Vector2(391, 151) 64 | 65 | [node name="cell10" parent="." instance=ExtResource("6_ko71e")] 66 | position = Vector2(413, 136) 67 | 68 | [node name="cell11" parent="." instance=ExtResource("6_ko71e")] 69 | position = Vector2(368, 127) 70 | 71 | [node name="cell12" parent="." instance=ExtResource("6_ko71e")] 72 | position = Vector2(390, 112) 73 | 74 | [node name="cell13" parent="." instance=ExtResource("6_ko71e")] 75 | position = Vector2(460, 177) 76 | 77 | [node name="cell14" parent="." instance=ExtResource("6_ko71e")] 78 | position = Vector2(482, 162) 79 | 80 | [node name="cell15" parent="." instance=ExtResource("6_ko71e")] 81 | position = Vector2(437, 153) 82 | 83 | [node name="cell16" parent="." instance=ExtResource("6_ko71e")] 84 | position = Vector2(459, 138) 85 | 86 | [node name="cell17" parent="." instance=ExtResource("6_ko71e")] 87 | position = Vector2(497, 147) 88 | 89 | [node name="cell18" parent="." instance=ExtResource("6_ko71e")] 90 | position = Vector2(519, 132) 91 | 92 | [node name="cell19" parent="." instance=ExtResource("6_ko71e")] 93 | position = Vector2(474, 123) 94 | 95 | [node name="cell20" parent="." instance=ExtResource("6_ko71e")] 96 | position = Vector2(496, 108) 97 | 98 | [node name="cell21" parent="." instance=ExtResource("6_ko71e")] 99 | position = Vector2(566, 173) 100 | 101 | [node name="cell22" parent="." instance=ExtResource("6_ko71e")] 102 | position = Vector2(588, 158) 103 | 104 | [node name="cell23" parent="." instance=ExtResource("6_ko71e")] 105 | position = Vector2(543, 149) 106 | 107 | [node name="cell24" parent="." instance=ExtResource("6_ko71e")] 108 | position = Vector2(565, 134) 109 | -------------------------------------------------------------------------------- /examples/flow_3d/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/examples/flow_3d/.DS_Store -------------------------------------------------------------------------------- /examples/flow_3d/cell.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://doydn5x6x37xu"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_yh41y"] 4 | script/source = " 5 | @tool 6 | extends RigidBody3D 7 | 8 | #@export var agent_color:Color : 9 | # get: 10 | # return agent_color 11 | # set(value): 12 | # agent_color = value 13 | # if get_child(1) != null: 14 | # get_child(1).material_override.albedo_color = agent_color 15 | 16 | func _ready(): 17 | pass 18 | 19 | func _process(delta): 20 | pass 21 | 22 | func _enter_tree(): 23 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 24 | set_name.call_deferred(new_name) 25 | 26 | func emit_changed(): 27 | pass 28 | 29 | " 30 | 31 | [sub_resource type="SphereShape3D" id="SphereShape3D_tjc2m"] 32 | 33 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o7kob"] 34 | albedo_color = Color(0.443137, 0.321569, 0.780392, 1) 35 | 36 | [sub_resource type="SphereMesh" id="SphereMesh_sw65u"] 37 | 38 | [node name="Cell" type="RigidBody3D" groups=["cell"]] 39 | gravity_scale = 0.0 40 | max_contacts_reported = 2 41 | contact_monitor = true 42 | linear_damp = 5.0 43 | angular_damp = 5.0 44 | script = SubResource("GDScript_yh41y") 45 | 46 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 47 | shape = SubResource("SphereShape3D_tjc2m") 48 | 49 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 50 | material_override = SubResource("StandardMaterial3D_o7kob") 51 | mesh = SubResource("SphereMesh_sw65u") 52 | -------------------------------------------------------------------------------- /examples/flow_3d/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://dxyigr7s87t04"] 2 | 3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_4jb5r"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_3ieej"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_f64oc"] 6 | [ext_resource type="PackedScene" uid="uid://doydn5x6x37xu" path="res://examples/flow_3d/cell.tscn" id="4_x2xy5"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="4_yuj62"] 8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="5_4avop"] 9 | 10 | [node name="Flow" type="Node3D"] 11 | 12 | [node name="BehavTreeForGroups" type="Node" parent="."] 13 | script = ExtResource("1_4jb5r") 14 | 15 | [node name="Behavior" type="Node" parent="BehavTreeForGroups" groups=["cell"]] 16 | script = ExtResource("2_3ieej") 17 | 18 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Behavior"] 19 | script = ExtResource("3_f64oc") 20 | 21 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Behavior"] 22 | script = ExtResource("4_yuj62") 23 | fx = 0.3 24 | 25 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Behavior"] 26 | script = ExtResource("5_4avop") 27 | loop_x = true 28 | 29 | [node name="Camera3D" type="Camera3D" parent="."] 30 | transform = Transform3D(1, 0, 0, 0, 0.858978, 0.512013, 0, -0.512013, 0.858978, 0, 2.59212, 5.00598) 31 | 32 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 33 | transform = Transform3D(1, 0, 0, 0, 0.867245, 0.497882, 0, -0.497882, 0.867245, 0, 3.77915, 4.85166) 34 | 35 | [node name="cell" parent="." instance=ExtResource("4_x2xy5")] 36 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -0.0886159) 37 | 38 | [node name="cell2" parent="." instance=ExtResource("4_x2xy5")] 39 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -0.0886159) 40 | 41 | [node name="cell3" parent="." instance=ExtResource("4_x2xy5")] 42 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -0.0886159) 43 | 44 | [node name="cell4" parent="." instance=ExtResource("4_x2xy5")] 45 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -0.0886159) 46 | 47 | [node name="cell5" parent="." instance=ExtResource("4_x2xy5")] 48 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -1.23198) 49 | 50 | [node name="cell6" parent="." instance=ExtResource("4_x2xy5")] 51 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -1.23198) 52 | 53 | [node name="cell7" parent="." instance=ExtResource("4_x2xy5")] 54 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -1.23198) 55 | 56 | [node name="cell8" parent="." instance=ExtResource("4_x2xy5")] 57 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -1.23198) 58 | 59 | [node name="cell9" parent="." instance=ExtResource("4_x2xy5")] 60 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 0, -2.37579) 61 | 62 | [node name="cell10" parent="." instance=ExtResource("4_x2xy5")] 63 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 0, -2.37579) 64 | 65 | [node name="cell11" parent="." instance=ExtResource("4_x2xy5")] 66 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 0, -2.37579) 67 | 68 | [node name="cell12" parent="." instance=ExtResource("4_x2xy5")] 69 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 0, -2.37579) 70 | 71 | [node name="cell13" parent="." instance=ExtResource("4_x2xy5")] 72 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, 1.09299, -1.24824) 73 | 74 | [node name="cell14" parent="." instance=ExtResource("4_x2xy5")] 75 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, 1.09299, -1.24824) 76 | 77 | [node name="cell15" parent="." instance=ExtResource("4_x2xy5")] 78 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, 1.09299, -1.24824) 79 | 80 | [node name="cell16" parent="." instance=ExtResource("4_x2xy5")] 81 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, 1.09299, -1.24824) 82 | 83 | [node name="cell17" parent="." instance=ExtResource("4_x2xy5")] 84 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.593141, -1.07794, -1.24824) 85 | 86 | [node name="cell18" parent="." instance=ExtResource("4_x2xy5")] 87 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.81141, -1.07794, -1.24824) 88 | 89 | [node name="cell19" parent="." instance=ExtResource("4_x2xy5")] 90 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.81094, -1.07794, -1.24824) 91 | 92 | [node name="cell20" parent="." instance=ExtResource("4_x2xy5")] 93 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.592675, -1.07794, -1.24824) 94 | -------------------------------------------------------------------------------- /examples/forest_fire/fire.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://cnvya7fqx07ur"] 2 | 3 | [sub_resource type="PlaneMesh" id="PlaneMesh_2od7k"] 4 | 5 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vcjnx"] 6 | albedo_color = Color(1, 0, 0.0509804, 1) 7 | 8 | [sub_resource type="SphereShape3D" id="SphereShape3D_q8vu0"] 9 | 10 | [node name="Fire" type="RigidBody3D" groups=["Fire"]] 11 | gravity_scale = 0.0 12 | linear_damp = 2.0 13 | 14 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 15 | transform = Transform3D(0.16, 0, 0, 0, 0.16, 0, 0, 0, 0.16, 0, 0, 0) 16 | mesh = SubResource("PlaneMesh_2od7k") 17 | surface_material_override/0 = SubResource("StandardMaterial3D_vcjnx") 18 | 19 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 20 | transform = Transform3D(0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0) 21 | shape = SubResource("SphereShape3D_q8vu0") 22 | -------------------------------------------------------------------------------- /examples/forest_fire/tree.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://cis6ivx1riuic"] 2 | 3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"] 4 | 5 | [sub_resource type="PrismMesh" id="PrismMesh_ieixx"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_rxxig"] 8 | albedo_color = Color(0, 0.45098, 0.0352941, 1) 9 | 10 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"] 11 | 12 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i5c1d"] 13 | albedo_color = Color(1, 0.498039, 0.0235294, 1) 14 | 15 | [node name="Tree" type="RigidBody3D" groups=["Tree"]] 16 | axis_lock_linear_x = true 17 | axis_lock_linear_y = true 18 | axis_lock_linear_z = true 19 | axis_lock_angular_x = true 20 | axis_lock_angular_y = true 21 | axis_lock_angular_z = true 22 | max_contacts_reported = 1 23 | contact_monitor = true 24 | 25 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 26 | transform = Transform3D(1.46, 0, 0, 0, 1.46, 0, 0, 0, 1.46, 0, -0.228769, 0) 27 | shape = SubResource("BoxShape3D_7nlum") 28 | 29 | [node name="MeshInstance3D2" type="MeshInstance3D" parent="."] 30 | transform = Transform3D(1, 0, 0, 0, 0.351, 0, 0, 0, 1, 0, 0.233011, 0) 31 | mesh = SubResource("PrismMesh_ieixx") 32 | surface_material_override/0 = SubResource("StandardMaterial3D_rxxig") 33 | 34 | [node name="MeshInstance3D3" type="MeshInstance3D" parent="."] 35 | transform = Transform3D(1.46, 0, 0, 0, 0.511543, 0, 0, 0, 1.46, 0, -0.198279, 0) 36 | mesh = SubResource("PrismMesh_ieixx") 37 | surface_material_override/0 = SubResource("StandardMaterial3D_rxxig") 38 | 39 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 40 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.17152, 0) 41 | mesh = SubResource("CylinderMesh_4d0ge") 42 | surface_material_override/0 = SubResource("StandardMaterial3D_i5c1d") 43 | -------------------------------------------------------------------------------- /examples/forest_fire/tree_burned.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://co4y4j2jfmhr1"] 2 | 3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"] 4 | 5 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0da6n"] 8 | albedo_color = Color(0.152941, 0.0705882, 0, 1) 9 | 10 | [node name="TreeBurned" type="RigidBody3D" groups=["TreeBurned"]] 11 | axis_lock_linear_x = true 12 | axis_lock_linear_y = true 13 | axis_lock_linear_z = true 14 | axis_lock_angular_x = true 15 | axis_lock_angular_y = true 16 | axis_lock_angular_z = true 17 | 18 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 19 | transform = Transform3D(0.6, 0, 0, 0, 0.6, 0, 0, 0, 0.6, 0, -1.02591, 0) 20 | shape = SubResource("BoxShape3D_7nlum") 21 | 22 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 23 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.09886, 0) 24 | mesh = SubResource("CylinderMesh_4d0ge") 25 | surface_material_override/0 = SubResource("StandardMaterial3D_0da6n") 26 | -------------------------------------------------------------------------------- /examples/forest_fire/tree_in_fire.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://dsdphcvcaxhpx"] 2 | 3 | [sub_resource type="BoxShape3D" id="BoxShape3D_7nlum"] 4 | 5 | [sub_resource type="PrismMesh" id="PrismMesh_ieixx"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m3v45"] 8 | albedo_color = Color(1, 0, 0.14902, 1) 9 | 10 | [sub_resource type="CylinderMesh" id="CylinderMesh_4d0ge"] 11 | 12 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0da6n"] 13 | albedo_color = Color(0.152941, 0.0705882, 0, 1) 14 | 15 | [node name="TreeInFire" type="RigidBody3D" groups=["TreeInFire"]] 16 | axis_lock_linear_x = true 17 | axis_lock_linear_y = true 18 | axis_lock_linear_z = true 19 | axis_lock_angular_x = true 20 | axis_lock_angular_y = true 21 | axis_lock_angular_z = true 22 | 23 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 24 | transform = Transform3D(1.46, 0, 0, 0, 1.46, 0, 0, 0, 1.46, 0, -0.227753, 0) 25 | shape = SubResource("BoxShape3D_7nlum") 26 | 27 | [node name="MeshInstance3D2" type="MeshInstance3D" parent="."] 28 | transform = Transform3D(1, 0, 0, 0, 0.351, 0, 0, 0, 1, 0, 0.234027, 0) 29 | mesh = SubResource("PrismMesh_ieixx") 30 | surface_material_override/0 = SubResource("StandardMaterial3D_m3v45") 31 | 32 | [node name="MeshInstance3D3" type="MeshInstance3D" parent="."] 33 | transform = Transform3D(1.46, 0, 0, 0, 0.511543, 0, 0, 0, 1.46, 0, -0.197263, 0) 34 | mesh = SubResource("PrismMesh_ieixx") 35 | surface_material_override/0 = SubResource("StandardMaterial3D_m3v45") 36 | 37 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 38 | transform = Transform3D(0.45, 0, 0, 0, 0.757859, 0, 0, 0, 0.45, 0, -1.17051, 0) 39 | mesh = SubResource("CylinderMesh_4d0ge") 40 | surface_material_override/0 = SubResource("StandardMaterial3D_0da6n") 41 | -------------------------------------------------------------------------------- /examples/grid2d/Agt.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://ccaq3hxvxvpla"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_sbo1b"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_88vdm"] 17 | 18 | [node name="Agt" type="RigidBody2D" groups=["Agt"]] 19 | gravity_scale = 0.0 20 | contact_monitor = true 21 | max_contacts_reported = 2 22 | linear_damp = 1.0 23 | angular_damp = 1.0 24 | script = SubResource("GDScript_sbo1b") 25 | 26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 27 | shape = SubResource("CircleShape2D_88vdm") 28 | 29 | [node name="Polygon2D" type="Polygon2D" parent="."] 30 | color = Color(1, 0, 0, 1) 31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 32 | -------------------------------------------------------------------------------- /examples/grid2d/follower.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://d3ie2qkjhjg3d"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_8ycgr"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | " 15 | 16 | [sub_resource type="CircleShape2D" id="CircleShape2D_g4qje"] 17 | 18 | [node name="follower" type="RigidBody2D" groups=["follower"]] 19 | gravity_scale = 0.0 20 | contact_monitor = true 21 | max_contacts_reported = 2 22 | linear_damp = 1.0 23 | angular_damp = 1.0 24 | script = SubResource("GDScript_8ycgr") 25 | 26 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 27 | shape = SubResource("CircleShape2D_g4qje") 28 | 29 | [node name="Polygon2D" type="Polygon2D" parent="."] 30 | color = Color(0.521569, 1, 0, 1) 31 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22465e-15, -5, -8.66025, 5, -8.66025) 32 | -------------------------------------------------------------------------------- /examples/grid2d/reaction-diffusion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://uxy5nviyl5pl"] 2 | 3 | [node name="Reaction-diffusion" type="Node2D"] 4 | -------------------------------------------------------------------------------- /examples/grid2d/reaction_diffusion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=27 format=3 uid="uid://ba0usgva601dg"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://cpe7fdfuxa1bj" path="res://examples/grid2d/my_grid.tscn" id="1_qumfy"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_xt3m6"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/field.gd" id="2_a7pa0"] 6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_aq2ef"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_w5h35"] 8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/set_grid_value_2d.gd" id="4_8b4h6"] 9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="5_4atmj"] 10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_to_grid_value.gd" id="6_3wt0p"] 11 | [ext_resource type="PackedScene" uid="uid://d3ie2qkjhjg3d" path="res://examples/grid2d/follower.tscn" id="7_uleci"] 12 | [ext_resource type="PackedScene" uid="uid://ccaq3hxvxvpla" path="res://examples/grid2d/Agt.tscn" id="8_a4qvu"] 13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/reaction.gd" id="9_051ld"] 14 | 15 | [sub_resource type="Resource" id="Resource_knat1"] 16 | script = ExtResource("2_a7pa0") 17 | name = "A" 18 | color = Color(0, 0.988235, 0, 1) 19 | diffusion_speed = 0.1 20 | degradation_speed = 0.001 21 | initialisation = "Random" 22 | 23 | [sub_resource type="Resource" id="Resource_4fn7p"] 24 | script = ExtResource("2_a7pa0") 25 | name = "B" 26 | color = Color(1, 0.568627, 0.733333, 1) 27 | diffusion_speed = 0.005 28 | degradation_speed = 0.001 29 | initialisation = "0" 30 | 31 | [sub_resource type="Resource" id="Resource_57mwe"] 32 | script = ExtResource("2_a7pa0") 33 | name = "B" 34 | color = Color(1, 0, 0.0588235, 1) 35 | diffusion_speed = 0.1 36 | degradation_speed = 0.001 37 | initialisation = "Random" 38 | 39 | [sub_resource type="Resource" id="Resource_r0hg5"] 40 | script = ExtResource("9_051ld") 41 | reactive_1 = "A" 42 | reactive_2 = "A" 43 | reactive_3 = "" 44 | speed = 0.01 45 | product_1 = "3 A" 46 | product_2 = "" 47 | product_3 = "" 48 | 49 | [sub_resource type="Resource" id="Resource_3pbwn"] 50 | script = ExtResource("9_051ld") 51 | reactive_1 = "B" 52 | reactive_2 = "B" 53 | reactive_3 = "" 54 | speed = 0.01 55 | product_1 = "3 B" 56 | product_2 = "" 57 | product_3 = "" 58 | 59 | [sub_resource type="Resource" id="Resource_uqhw3"] 60 | script = ExtResource("9_051ld") 61 | reactive_1 = "A" 62 | reactive_2 = "B" 63 | reactive_3 = "" 64 | speed = 0.01 65 | product_1 = "0 A" 66 | product_2 = "0 B" 67 | product_3 = "" 68 | 69 | [sub_resource type="Resource" id="Resource_5x48p"] 70 | script = ExtResource("2_a7pa0") 71 | name = "B" 72 | color = Color(0, 0, 1, 1) 73 | diffusion_speed = 0.3 74 | degradation_speed = 0.001 75 | initialisation = "Random" 76 | 77 | [sub_resource type="Resource" id="Resource_00wib"] 78 | script = ExtResource("2_a7pa0") 79 | name = "Mol2" 80 | color = Color(0.8012, 0.555211, 0.460583, 1) 81 | diffusion_speed = 0.1 82 | degradation_speed = 0.0 83 | initialisation = "Random" 84 | 85 | [sub_resource type="Resource" id="Resource_uhnse"] 86 | script = ExtResource("2_a7pa0") 87 | name = "A" 88 | color = Color(1, 0, 1, 1) 89 | diffusion_speed = 0.3 90 | degradation_speed = 0.01 91 | initialisation = "0" 92 | 93 | [sub_resource type="Resource" id="Resource_g16xq"] 94 | script = ExtResource("2_a7pa0") 95 | name = "A" 96 | color = Color(0.926313, 0.000197721, 0.794224, 1) 97 | diffusion_speed = 0.05 98 | degradation_speed = 0.001 99 | initialisation = "Random" 100 | 101 | [sub_resource type="Resource" id="Resource_qxp5o"] 102 | script = ExtResource("2_a7pa0") 103 | name = "B" 104 | color = Color(2.55093e-06, 0.69572, 0.487671, 1) 105 | diffusion_speed = 0.05 106 | degradation_speed = 0.001 107 | initialisation = "Random" 108 | 109 | [sub_resource type="Resource" id="Resource_grxcc"] 110 | script = ExtResource("2_a7pa0") 111 | name = "C" 112 | color = Color(0, 0, 1, 1) 113 | diffusion_speed = 0.05 114 | degradation_speed = 0.001 115 | initialisation = "Random" 116 | 117 | [sub_resource type="Resource" id="Resource_oe8bw"] 118 | script = ExtResource("9_051ld") 119 | reactive_1 = "A" 120 | reactive_2 = "B" 121 | reactive_3 = "" 122 | speed = 0.3 123 | product_1 = "2 B" 124 | product_2 = "" 125 | product_3 = "" 126 | 127 | [sub_resource type="Resource" id="Resource_1dlc7"] 128 | script = ExtResource("9_051ld") 129 | reactive_1 = "B" 130 | reactive_2 = "C" 131 | reactive_3 = "" 132 | speed = 0.3 133 | product_1 = "2 C" 134 | product_2 = "" 135 | product_3 = "" 136 | 137 | [sub_resource type="Resource" id="Resource_5hr6g"] 138 | script = ExtResource("9_051ld") 139 | reactive_1 = "C" 140 | reactive_2 = "A" 141 | reactive_3 = "" 142 | speed = 0.3 143 | product_1 = "2 A" 144 | product_2 = "" 145 | product_3 = "" 146 | 147 | [node name="ReactionDiffusion" type="Node2D"] 148 | 149 | [node name="BehaviorTreeForGroups" type="Node" parent="."] 150 | script = ExtResource("1_xt3m6") 151 | 152 | [node name="Agt" type="Node" parent="BehaviorTreeForGroups" groups=["Agt"]] 153 | script = ExtResource("2_aq2ef") 154 | 155 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Agt"] 156 | script = ExtResource("3_w5h35") 157 | F = Vector3(50, 50, 50) 158 | 159 | [node name="SetGridValue2D" type="Node" parent="BehaviorTreeForGroups/Agt" groups=["my_grid"]] 160 | script = ExtResource("4_8b4h6") 161 | field = "A" 162 | set_value = 1.0 163 | 164 | [node name="StayInBox" type="Node" parent="BehaviorTreeForGroups/Agt"] 165 | script = ExtResource("5_4atmj") 166 | min = Vector3(0, 0, 0) 167 | max = Vector3(1000, 500, 0) 168 | 169 | [node name="Follow" type="Node" parent="BehaviorTreeForGroups" groups=["follower"]] 170 | script = ExtResource("2_aq2ef") 171 | 172 | [node name="ForceToGridValue" type="Node" parent="BehaviorTreeForGroups/Follow"] 173 | script = ExtResource("6_3wt0p") 174 | on_grid_group = "my_grid" 175 | for_field = "A" 176 | target_value = 1.0 177 | force = 10.0 178 | 179 | [node name="ForceRandom" type="Node" parent="BehaviorTreeForGroups/Follow"] 180 | script = ExtResource("3_w5h35") 181 | F = Vector3(20, 20, 20) 182 | 183 | [node name="SetGridValue2D2" type="Node" parent="BehaviorTreeForGroups/Follow" groups=["my_grid"]] 184 | script = ExtResource("4_8b4h6") 185 | field = "A" 186 | set_value = 1.0 187 | 188 | [node name="StayInBox2" type="Node" parent="BehaviorTreeForGroups/Follow"] 189 | script = ExtResource("5_4atmj") 190 | min = Vector3(0, 0, 0) 191 | max = Vector3(1000, 500, 0) 192 | 193 | [node name="my_grid" parent="." instance=ExtResource("1_qumfy")] 194 | offset_left = 24.0 195 | offset_top = 16.0 196 | offset_right = 536.0 197 | offset_bottom = 291.0 198 | SX = 128 199 | SY = 64 200 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_knat1"), SubResource("Resource_4fn7p")]) 201 | 202 | [node name="my_grid2" parent="." instance=ExtResource("1_qumfy")] 203 | offset_left = 595.0 204 | offset_top = 14.0 205 | offset_right = 1107.0 206 | offset_bottom = 292.0 207 | SX = 128 208 | SY = 64 209 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_knat1"), SubResource("Resource_57mwe")]) 210 | reactions = Array[ExtResource("9_051ld")]([SubResource("Resource_r0hg5"), SubResource("Resource_3pbwn"), SubResource("Resource_uqhw3")]) 211 | 212 | [node name="my_grid3" parent="." instance=ExtResource("1_qumfy")] 213 | offset_left = 30.0 214 | offset_top = 343.0 215 | offset_right = 539.0 216 | offset_bottom = 614.0 217 | loop_x = true 218 | loop_y = true 219 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_5x48p"), SubResource("Resource_00wib"), SubResource("Resource_uhnse")]) 220 | 221 | [node name="my_grid_Belousov_Zhabotinsky" parent="." instance=ExtResource("1_qumfy")] 222 | offset_left = 599.0 223 | offset_top = 347.0 224 | offset_right = 1108.0 225 | offset_bottom = 612.0 226 | loop_x = true 227 | loop_y = true 228 | fields = Array[ExtResource("2_a7pa0")]([SubResource("Resource_g16xq"), SubResource("Resource_qxp5o"), SubResource("Resource_grxcc")]) 229 | reactions = Array[ExtResource("9_051ld")]([SubResource("Resource_oe8bw"), SubResource("Resource_1dlc7"), SubResource("Resource_5hr6g")]) 230 | 231 | [node name="Agt" parent="." instance=ExtResource("8_a4qvu")] 232 | position = Vector2(334, 182) 233 | 234 | [node name="Agt2" parent="." instance=ExtResource("8_a4qvu")] 235 | position = Vector2(333, 458) 236 | 237 | [node name="Agt3" parent="." instance=ExtResource("8_a4qvu")] 238 | position = Vector2(862, 308) 239 | 240 | [node name="Agt4" parent="." instance=ExtResource("8_a4qvu")] 241 | position = Vector2(799, 357) 242 | 243 | [node name="Agt5" parent="." instance=ExtResource("8_a4qvu")] 244 | position = Vector2(334, 182) 245 | 246 | [node name="Agt6" parent="." instance=ExtResource("8_a4qvu")] 247 | position = Vector2(333, 458) 248 | 249 | [node name="Agt7" parent="." instance=ExtResource("8_a4qvu")] 250 | position = Vector2(862, 308) 251 | 252 | [node name="Agt8" parent="." instance=ExtResource("8_a4qvu")] 253 | position = Vector2(799, 357) 254 | 255 | [node name="Agt9" parent="." instance=ExtResource("8_a4qvu")] 256 | position = Vector2(334, 182) 257 | 258 | [node name="Agt10" parent="." instance=ExtResource("8_a4qvu")] 259 | position = Vector2(333, 458) 260 | 261 | [node name="Agt11" parent="." instance=ExtResource("8_a4qvu")] 262 | position = Vector2(862, 308) 263 | 264 | [node name="Agt12" parent="." instance=ExtResource("8_a4qvu")] 265 | position = Vector2(799, 357) 266 | 267 | [node name="follower" parent="." instance=ExtResource("7_uleci")] 268 | position = Vector2(165, 100) 269 | 270 | [node name="follower2" parent="." instance=ExtResource("7_uleci")] 271 | position = Vector2(200, 100) 272 | 273 | [node name="follower3" parent="." instance=ExtResource("7_uleci")] 274 | position = Vector2(700, 400) 275 | 276 | [node name="follower4" parent="." instance=ExtResource("7_uleci")] 277 | position = Vector2(800, 400) 278 | 279 | [node name="follower5" parent="." instance=ExtResource("7_uleci")] 280 | position = Vector2(165, 100) 281 | 282 | [node name="follower6" parent="." instance=ExtResource("7_uleci")] 283 | position = Vector2(200, 100) 284 | 285 | [node name="follower7" parent="." instance=ExtResource("7_uleci")] 286 | position = Vector2(700, 400) 287 | 288 | [node name="follower8" parent="." instance=ExtResource("7_uleci")] 289 | position = Vector2(800, 400) 290 | 291 | [node name="follower9" parent="." instance=ExtResource("7_uleci")] 292 | position = Vector2(165, 100) 293 | 294 | [node name="follower10" parent="." instance=ExtResource("7_uleci")] 295 | position = Vector2(200, 100) 296 | 297 | [node name="follower11" parent="." instance=ExtResource("7_uleci")] 298 | position = Vector2(700, 400) 299 | 300 | [node name="follower12" parent="." instance=ExtResource("7_uleci")] 301 | position = Vector2(800, 400) 302 | -------------------------------------------------------------------------------- /examples/various/agent_2d.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://btaurfj6abv1j"] 2 | 3 | [sub_resource type="GDScript" id="GDScript_5seel"] 4 | script/source = " 5 | @tool 6 | extends RigidBody2D 7 | 8 | @export var state:int = 0 9 | @export var age:int = 0 10 | 11 | func _process(_delta): 12 | if not Engine.is_editor_hint(): 13 | age += 1 14 | 15 | func _enter_tree(): 16 | var new_name:String = get_scene_file_path().get_file().trim_suffix(\".tscn\") 17 | set_name.call_deferred(new_name) 18 | " 19 | 20 | [sub_resource type="CircleShape2D" id="CircleShape2D_3k7d8"] 21 | 22 | [node name="agent_2d" type="RigidBody2D" groups=["agt"]] 23 | gravity_scale = 0.0 24 | contact_monitor = true 25 | max_contacts_reported = 2 26 | linear_damp = 1.0 27 | angular_damp = 1.0 28 | script = SubResource("GDScript_5seel") 29 | 30 | [node name="CollisionShape2D" type="CollisionShape2D" parent="."] 31 | shape = SubResource("CircleShape2D_3k7d8") 32 | 33 | [node name="Polygon2D" type="Polygon2D" parent="."] 34 | color = Color(1, 0.294118, 0.533333, 1) 35 | polygon = PackedVector2Array(10, 0, 5, 8.66025, -5, 8.66025, -10, 1.22461e-15, -5, -8.66025, 5, -8.66025) 36 | -------------------------------------------------------------------------------- /examples/various/agent_a.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://c0socp63xfqt7"] 2 | 3 | [sub_resource type="BoxShape3D" id="BoxShape3D_obgbv"] 4 | size = Vector3(1, 0.3, 0.3) 5 | 6 | [sub_resource type="BoxMesh" id="BoxMesh_q4tn4"] 7 | 8 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_6w1qo"] 9 | albedo_color = Color(1, 0.745098, 0, 1) 10 | 11 | [node name="Agent-A" type="RigidBody3D" groups=["Agent-A"]] 12 | contact_monitor = true 13 | max_contacts_reported = 1 14 | metadata/Age = 0 15 | 16 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 17 | shape = SubResource("BoxShape3D_obgbv") 18 | 19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 20 | transform = Transform3D(1, 0, 0, 0, 0.3, 0, 0, 0, 0.3, 0, 0, 0) 21 | mesh = SubResource("BoxMesh_q4tn4") 22 | surface_material_override/0 = SubResource("StandardMaterial3D_6w1qo") 23 | -------------------------------------------------------------------------------- /examples/various/agent_b.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://cmh2j5wto6rrp"] 2 | 3 | [sub_resource type="SphereShape3D" id="SphereShape3D_f7ebv"] 4 | 5 | [sub_resource type="SphereMesh" id="SphereMesh_owuwi"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_t20g3"] 8 | albedo_color = Color(1, 0.666667, 0.984314, 1) 9 | 10 | [node name="Agent-B" type="RigidBody3D" groups=["Agent-B"]] 11 | contact_monitor = true 12 | max_contacts_reported = 1 13 | metadata/Age = 0 14 | 15 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 16 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) 17 | shape = SubResource("SphereShape3D_f7ebv") 18 | 19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 20 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) 21 | mesh = SubResource("SphereMesh_owuwi") 22 | surface_material_override/0 = SubResource("StandardMaterial3D_t20g3") 23 | -------------------------------------------------------------------------------- /examples/various/agent_c.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://cnp1sb4hijc2o"] 2 | 3 | [sub_resource type="SphereShape3D" id="SphereShape3D_f7ebv"] 4 | 5 | [sub_resource type="SphereMesh" id="SphereMesh_owuwi"] 6 | 7 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8mr6m"] 8 | albedo_color = Color(0.972549, 1, 0, 1) 9 | 10 | [node name="Agent-C" type="RigidBody3D" groups=["Agent-C"]] 11 | contact_monitor = true 12 | max_contacts_reported = 1 13 | metadata/Age = 0 14 | 15 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."] 16 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) 17 | shape = SubResource("SphereShape3D_f7ebv") 18 | 19 | [node name="MeshInstance3D" type="MeshInstance3D" parent="." groups=["Agent-C"]] 20 | transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) 21 | mesh = SubResource("SphereMesh_owuwi") 22 | surface_material_override/0 = SubResource("StandardMaterial3D_8mr6m") 23 | -------------------------------------------------------------------------------- /examples/various/curie_therapy.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://bxd6dtmcpy2h4"] 2 | 3 | [node name="CurieTherapy" type="Node2D"] 4 | 5 | [node name="Label" type="Label" parent="."] 6 | offset_right = 40.0 7 | offset_bottom = 23.0 8 | text = "Work in progress..." 9 | -------------------------------------------------------------------------------- /examples/various/molecule_adhesion.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=13 format=3 uid="uid://gbfhv38mowje"] 2 | 3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_ty85y"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_r87fs"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="3_1a2m6"] 6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_step_between.gd" id="4_t67sr"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_spring_on_contact.gd" id="4_u81ky"] 8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="4_wcjs1"] 9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="4_xxsde"] 10 | [ext_resource type="PackedScene" uid="uid://cmh2j5wto6rrp" path="res://examples/various/agent_b.tscn" id="5_di58j"] 11 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_proba.gd" id="6_q137f"] 12 | [ext_resource type="PackedScene" uid="uid://cnp1sb4hijc2o" path="res://examples/various/agent_c.tscn" id="6_qqbgm"] 13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="7_3e5lb"] 14 | 15 | [sub_resource type="BoxMesh" id="BoxMesh_ccvj4"] 16 | flip_faces = true 17 | 18 | [node name="ExampleAdhesion" type="Node3D"] 19 | 20 | [node name="BehavTreeForGroups" type="Node" parent="."] 21 | script = ExtResource("1_ty85y") 22 | 23 | [node name="Agent-B" type="Node" parent="BehavTreeForGroups" groups=["Agent-B"]] 24 | script = ExtResource("2_r87fs") 25 | 26 | [node name="MvtRandom" type="Node" parent="BehavTreeForGroups/Agent-B"] 27 | script = ExtResource("3_1a2m6") 28 | 29 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-B/MvtRandom"] 30 | script = ExtResource("4_t67sr") 31 | step_end = 100000 32 | 33 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Agent-B/MvtRandom"] 34 | script = ExtResource("4_xxsde") 35 | 36 | [node name="DeathRandom" type="Node" parent="BehavTreeForGroups/Agent-B"] 37 | script = ExtResource("3_1a2m6") 38 | 39 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"] 40 | script = ExtResource("4_t67sr") 41 | step_start = 100000 42 | step_end = 100000000 43 | 44 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"] 45 | script = ExtResource("6_q137f") 46 | proba = 0.001 47 | 48 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Agent-B/DeathRandom"] 49 | script = ExtResource("7_3e5lb") 50 | 51 | [node name="AddSpringOnContact" type="Node" parent="BehavTreeForGroups/Agent-B"] 52 | script = ExtResource("4_u81ky") 53 | with_group = "Agent-C" 54 | 55 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Agent-B"] 56 | script = ExtResource("4_wcjs1") 57 | min = Vector3(-1, -1, -1) 58 | max = Vector3(1, 1, 1) 59 | 60 | [node name="Agent-C" type="Node" parent="BehavTreeForGroups" groups=["Agent-C"]] 61 | script = ExtResource("2_r87fs") 62 | 63 | [node name="Sequential" type="Node" parent="BehavTreeForGroups/Agent-C"] 64 | script = ExtResource("3_1a2m6") 65 | 66 | [node name="IfStepBetween" type="Node" parent="BehavTreeForGroups/Agent-C/Sequential"] 67 | script = ExtResource("4_t67sr") 68 | step_end = 100000 69 | 70 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Agent-C/Sequential"] 71 | script = ExtResource("4_xxsde") 72 | 73 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Agent-C"] 74 | script = ExtResource("4_wcjs1") 75 | min = Vector3(-1, -1, -1) 76 | max = Vector3(1, 1, 1) 77 | 78 | [node name="Agent-B" parent="." instance=ExtResource("5_di58j")] 79 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 80 | gravity_scale = 0.0 81 | 82 | [node name="Agent-B2" parent="." instance=ExtResource("5_di58j")] 83 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 84 | gravity_scale = 0.0 85 | 86 | [node name="Agent-B3" parent="." instance=ExtResource("5_di58j")] 87 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 88 | gravity_scale = 0.0 89 | 90 | [node name="Agent-B4" parent="." instance=ExtResource("5_di58j")] 91 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 92 | gravity_scale = 0.0 93 | 94 | [node name="Agent-B5" parent="." instance=ExtResource("5_di58j")] 95 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 96 | gravity_scale = 0.0 97 | 98 | [node name="Agent-B6" parent="." instance=ExtResource("5_di58j")] 99 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 100 | gravity_scale = 0.0 101 | 102 | [node name="Agent-B7" parent="." instance=ExtResource("5_di58j")] 103 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 104 | gravity_scale = 0.0 105 | 106 | [node name="Agent-B8" parent="." instance=ExtResource("5_di58j")] 107 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.369118, -0.0464584, 0) 108 | gravity_scale = 0.0 109 | 110 | [node name="Agent-C" parent="." instance=ExtResource("6_qqbgm")] 111 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 112 | gravity_scale = 0.0 113 | 114 | [node name="Agent-C2" parent="." instance=ExtResource("6_qqbgm")] 115 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 116 | gravity_scale = 0.0 117 | 118 | [node name="Agent-C3" parent="." instance=ExtResource("6_qqbgm")] 119 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 120 | gravity_scale = 0.0 121 | 122 | [node name="Agent-C4" parent="." instance=ExtResource("6_qqbgm")] 123 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 124 | gravity_scale = 0.0 125 | 126 | [node name="Agent-C5" parent="." instance=ExtResource("6_qqbgm")] 127 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 128 | gravity_scale = 0.0 129 | 130 | [node name="Agent-C6" parent="." instance=ExtResource("6_qqbgm")] 131 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 132 | gravity_scale = 0.0 133 | 134 | [node name="Agent-C7" parent="." instance=ExtResource("6_qqbgm")] 135 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 136 | gravity_scale = 0.0 137 | 138 | [node name="Agent-C8" parent="." instance=ExtResource("6_qqbgm")] 139 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.412403, 0.0459936, 0) 140 | gravity_scale = 0.0 141 | 142 | [node name="Camera3D" type="Camera3D" parent="."] 143 | transform = Transform3D(1, 0, 0, 0, 0.890372, 0.455234, 0, -0.455234, 0.890372, 0, 1.04184, 2.29168) 144 | 145 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 146 | transform = Transform3D(1, 0, 0, 0, 0.180794, 0.983521, 0, -0.983521, 0.180794, 0, 0, 10.7686) 147 | 148 | [node name="MeshInstance3D" type="MeshInstance3D" parent="."] 149 | transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0) 150 | mesh = SubResource("BoxMesh_ccvj4") 151 | -------------------------------------------------------------------------------- /examples/various/prey_pred.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=14 format=3 uid="uid://cjttehav3absk"] 2 | 3 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior_tree_for_groups.gd" id="1_bbgsd"] 4 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/behavior.gd" id="2_ydp6m"] 5 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_random.gd" id="3_n8pv4"] 6 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/sequential.gd" id="4_52da3"] 7 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_proba.gd" id="5_jmidm"] 8 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/add_agent.gd" id="6_6wxfy"] 9 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/if_collision.gd" id="7_3pti1"] 10 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/delete.gd" id="8_bqvrh"] 11 | [ext_resource type="PackedScene" uid="uid://cmh2j5wto6rrp" path="res://examples/various/agent_b.tscn" id="9_1gvab"] 12 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/stay_in_box.gd" id="9_maaon"] 13 | [ext_resource type="Script" path="res://addons/behav_tree_for_groups/force_global.gd" id="10_ahpm3"] 14 | [ext_resource type="PackedScene" uid="uid://cnp1sb4hijc2o" path="res://examples/various/agent_c.tscn" id="10_sbjrl"] 15 | 16 | [sub_resource type="BoxMesh" id="BoxMesh_h8i4e"] 17 | flip_faces = true 18 | 19 | [node name="ExamplePreyPred" type="Node3D"] 20 | 21 | [node name="BehavTreeForGroups" type="Node" parent="."] 22 | script = ExtResource("1_bbgsd") 23 | 24 | [node name="Preys" type="Node" parent="BehavTreeForGroups" groups=["Agent-B"]] 25 | script = ExtResource("2_ydp6m") 26 | 27 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Preys"] 28 | script = ExtResource("3_n8pv4") 29 | 30 | [node name="Reproduce" type="Node" parent="BehavTreeForGroups/Preys"] 31 | script = ExtResource("4_52da3") 32 | 33 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Preys/Reproduce"] 34 | script = ExtResource("5_jmidm") 35 | proba = 1.0 36 | 37 | [node name="AddAgent" type="Node" parent="BehavTreeForGroups/Preys/Reproduce"] 38 | script = ExtResource("6_6wxfy") 39 | agent_tscn = "res://examples/various/agent_b.tscn" 40 | 41 | [node name="Eaten" type="Node" parent="BehavTreeForGroups/Preys"] 42 | script = ExtResource("4_52da3") 43 | 44 | [node name="IfContact" type="Node" parent="BehavTreeForGroups/Preys/Eaten"] 45 | script = ExtResource("7_3pti1") 46 | with_group = "Agent-C" 47 | 48 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Preys/Eaten"] 49 | script = ExtResource("8_bqvrh") 50 | 51 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Preys"] 52 | script = ExtResource("9_maaon") 53 | 54 | [node name="Jump" type="Node" parent="BehavTreeForGroups/Preys"] 55 | script = ExtResource("4_52da3") 56 | 57 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Preys/Jump"] 58 | script = ExtResource("5_jmidm") 59 | proba = 0.1 60 | 61 | [node name="ForceGlobal" type="Node" parent="BehavTreeForGroups/Preys/Jump"] 62 | script = ExtResource("10_ahpm3") 63 | fy = 5.0 64 | 65 | [node name="Predators" type="Node" parent="BehavTreeForGroups" groups=["Agent-C"]] 66 | script = ExtResource("2_ydp6m") 67 | 68 | [node name="ForceRandom" type="Node" parent="BehavTreeForGroups/Predators"] 69 | script = ExtResource("3_n8pv4") 70 | 71 | [node name="Eat" type="Node" parent="BehavTreeForGroups/Predators"] 72 | script = ExtResource("4_52da3") 73 | 74 | [node name="IfContact" type="Node" parent="BehavTreeForGroups/Predators/Eat"] 75 | script = ExtResource("7_3pti1") 76 | with_group = "Agent-B" 77 | 78 | [node name="AddAgent" type="Node" parent="BehavTreeForGroups/Predators/Eat"] 79 | script = ExtResource("6_6wxfy") 80 | agent_tscn = "res://Examples/various/agent_c.tscn" 81 | 82 | [node name="Death" type="Node" parent="BehavTreeForGroups/Predators"] 83 | script = ExtResource("4_52da3") 84 | 85 | [node name="IfProba" type="Node" parent="BehavTreeForGroups/Predators/Death"] 86 | script = ExtResource("5_jmidm") 87 | proba = 0.3 88 | 89 | [node name="Delete" type="Node" parent="BehavTreeForGroups/Predators/Death"] 90 | script = ExtResource("8_bqvrh") 91 | 92 | [node name="StayInBox" type="Node" parent="BehavTreeForGroups/Predators"] 93 | script = ExtResource("9_maaon") 94 | 95 | [node name="Camera3D" type="Camera3D" parent="."] 96 | transform = Transform3D(1, 0, 0, 0, 0.723714, 0.6901, 0, -0.6901, 0.723714, 0.0294014, 2.78409, 6.53686) 97 | 98 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 99 | transform = Transform3D(1, 0, 0, 0, 0.883782, 0.467899, 0, -0.467899, 0.883782, 0, 6.90312, 11.0244) 100 | 101 | [node name="Predator1" parent="." instance=ExtResource("10_sbjrl")] 102 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.48761, 0.7, -1.11156) 103 | 104 | [node name="Predator2" parent="." instance=ExtResource("10_sbjrl")] 105 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.19409, 0.7, -0.695615) 106 | 107 | [node name="Predator3" parent="." instance=ExtResource("10_sbjrl")] 108 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.968706, 0.7, -1.29503) 109 | 110 | [node name="Predator4" parent="." instance=ExtResource("10_sbjrl")] 111 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.02174, 0.7, -0.901522) 112 | 113 | [node name="Prey1" parent="." instance=ExtResource("9_1gvab")] 114 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.507974, 0.7, -0.246305) 115 | 116 | [node name="Prey2" parent="." instance=ExtResource("9_1gvab")] 117 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.01165, 0.7, -0.246305) 118 | 119 | [node name="Prey3" parent="." instance=ExtResource("9_1gvab")] 120 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.507974, 0.7, -0.959407) 121 | 122 | [node name="Prey4" parent="." instance=ExtResource("9_1gvab")] 123 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.01165, 0.7, -0.959407) 124 | 125 | [node name="Prey5" parent="." instance=ExtResource("9_1gvab")] 126 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.44594, 0.7, -0.246305) 127 | 128 | [node name="Prey6" parent="." instance=ExtResource("9_1gvab")] 129 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.94961, 0.7, -0.246305) 130 | 131 | [node name="Prey7" parent="." instance=ExtResource("9_1gvab")] 132 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.44594, 0.7, -0.959407) 133 | 134 | [node name="Prey8" parent="." instance=ExtResource("9_1gvab")] 135 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.94961, 0.7, -0.959407) 136 | 137 | [node name="Prey9" parent="." instance=ExtResource("9_1gvab")] 138 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.772096, 0.7, -0.735504) 139 | 140 | [node name="Prey10" parent="." instance=ExtResource("9_1gvab")] 141 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.27577, 0.7, -0.735504) 142 | 143 | [node name="Prey11" parent="." instance=ExtResource("9_1gvab")] 144 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.772096, 0.7, -1.44861) 145 | 146 | [node name="Prey12" parent="." instance=ExtResource("9_1gvab")] 147 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.27577, 0.7, -1.44861) 148 | 149 | [node name="Prey13" parent="." instance=ExtResource("9_1gvab")] 150 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71006, 0.7, -0.735504) 151 | 152 | [node name="Prey14" parent="." instance=ExtResource("9_1gvab")] 153 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.21374, 0.7, -0.735504) 154 | 155 | [node name="Prey15" parent="." instance=ExtResource("9_1gvab")] 156 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71006, 0.7, -1.44861) 157 | 158 | [node name="Prey16" parent="." instance=ExtResource("9_1gvab")] 159 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.21374, 0.7, -1.44861) 160 | 161 | [node name="Prey17" parent="." instance=ExtResource("9_1gvab")] 162 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.203144, 0.7, -0.0964099) 163 | 164 | [node name="Prey18" parent="." instance=ExtResource("9_1gvab")] 165 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.70682, 0.7, -0.0964099) 166 | 167 | [node name="Prey19" parent="." instance=ExtResource("9_1gvab")] 168 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.203144, 0.7, -0.809512) 169 | 170 | [node name="Prey20" parent="." instance=ExtResource("9_1gvab")] 171 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.70682, 0.7, -0.809512) 172 | 173 | [node name="Prey21" parent="." instance=ExtResource("9_1gvab")] 174 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.14111, 0.7, -0.0964099) 175 | 176 | [node name="Prey22" parent="." instance=ExtResource("9_1gvab")] 177 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.64478, 0.7, -0.0964099) 178 | 179 | [node name="Prey23" parent="." instance=ExtResource("9_1gvab")] 180 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.14111, 0.7, -0.809512) 181 | 182 | [node name="Prey24" parent="." instance=ExtResource("9_1gvab")] 183 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.64478, 0.7, -0.809512) 184 | 185 | [node name="Prey25" parent="." instance=ExtResource("9_1gvab")] 186 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.467266, 0.7, -0.585609) 187 | 188 | [node name="Prey26" parent="." instance=ExtResource("9_1gvab")] 189 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.97094, 0.7, -0.585609) 190 | 191 | [node name="Prey27" parent="." instance=ExtResource("9_1gvab")] 192 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.467266, 0.7, -1.29871) 193 | 194 | [node name="Prey28" parent="." instance=ExtResource("9_1gvab")] 195 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.97094, 0.7, -1.29871) 196 | 197 | [node name="Prey29" parent="." instance=ExtResource("9_1gvab")] 198 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.40523, 0.7, -0.585609) 199 | 200 | [node name="Prey30" parent="." instance=ExtResource("9_1gvab")] 201 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.90891, 0.7, -0.585609) 202 | 203 | [node name="Prey31" parent="." instance=ExtResource("9_1gvab")] 204 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.40523, 0.7, -1.29871) 205 | 206 | [node name="Prey32" parent="." instance=ExtResource("9_1gvab")] 207 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.90891, 0.7, -1.29871) 208 | 209 | [node name="Environment" type="MeshInstance3D" parent="."] 210 | transform = Transform3D(10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0) 211 | mesh = SubResource("BoxMesh_h8i4e") 212 | -------------------------------------------------------------------------------- /examples/various/test_generic_6dof_joint_3d.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://cki3e4t2gcdqr"] 2 | 3 | [sub_resource type="SphereShape3D" id="SphereShape3D_d8nr6"] 4 | 5 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pexjg"] 6 | albedo_color = Color(1, 0.584314, 0.552941, 1) 7 | 8 | [sub_resource type="BoxMesh" id="BoxMesh_3ci86"] 9 | 10 | [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4soa8"] 11 | albedo_color = Color(0.666667, 1, 0.682353, 1) 12 | 13 | [sub_resource type="BoxMesh" id="BoxMesh_xulsm"] 14 | 15 | [node name="TestGeneric6DOFJoint3D" type="Node3D"] 16 | 17 | [node name="Generic6DOFJoint3D" type="Generic6DOFJoint3D" parent="."] 18 | node_a = NodePath("../Fixed") 19 | node_b = NodePath("../Moves") 20 | linear_spring_x/stiffness = 0.001 21 | linear_spring_x/damping = 0.1 22 | linear_spring_x/equilibrium_point = 1.0 23 | linear_spring_y/stiffness = 0.001 24 | linear_spring_y/damping = 0.1 25 | linear_spring_y/equilibrium_point = 1.0 26 | linear_spring_z/stiffness = 0.001 27 | linear_spring_z/damping = 0.1 28 | linear_spring_z/equilibrium_point = 1.0 29 | angular_limit_x/restitution = 10.0 30 | angular_limit_y/restitution = 10.0 31 | angular_limit_z/restitution = 10.0 32 | 33 | [node name="Fixed" type="RigidBody3D" parent="."] 34 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) 35 | axis_lock_linear_x = true 36 | axis_lock_linear_y = true 37 | axis_lock_linear_z = true 38 | axis_lock_angular_x = true 39 | axis_lock_angular_y = true 40 | axis_lock_angular_z = true 41 | gravity_scale = 0.0 42 | 43 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Fixed"] 44 | shape = SubResource("SphereShape3D_d8nr6") 45 | 46 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Fixed"] 47 | material_override = SubResource("StandardMaterial3D_pexjg") 48 | mesh = SubResource("BoxMesh_3ci86") 49 | 50 | [node name="Moves" type="RigidBody3D" parent="."] 51 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.7, 2, 0) 52 | 53 | [node name="CollisionShape3D" type="CollisionShape3D" parent="Moves"] 54 | shape = SubResource("SphereShape3D_d8nr6") 55 | 56 | [node name="MeshInstance3D" type="MeshInstance3D" parent="Moves"] 57 | material_override = SubResource("StandardMaterial3D_4soa8") 58 | mesh = SubResource("BoxMesh_xulsm") 59 | 60 | [node name="Camera3D" type="Camera3D" parent="."] 61 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.767151, 4.75228) 62 | 63 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 64 | transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 5, 8) 65 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="behavior_tree_for_groups" 14 | config/description="A Behavior Tree to create swarm and multiagent systems based on Node's Groups." 15 | run/main_scene="res://examples/various/crowd_opposite_mvt.tscn" 16 | config/features=PackedStringArray("4.3", "Forward Plus") 17 | config/icon="res://addons/behav_tree_for_groups/icon.png" 18 | 19 | [display] 20 | 21 | window/stretch/mode="viewport" 22 | 23 | [editor_plugins] 24 | 25 | enabled=PackedStringArray("res://addons/behav_tree_for_groups/plugin.cfg") 26 | -------------------------------------------------------------------------------- /screenshots/.gdignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/.gdignore -------------------------------------------------------------------------------- /screenshots/BTFG_documentation_front_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/BTFG_documentation_front_page.png -------------------------------------------------------------------------------- /screenshots/BTFG_documentation_front_page.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d0or1opyfy513" 6 | path="res://.godot/imported/BTFG_documentation_front_page.png-ee3c8157e44908e447dc44db304e4256.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://screenshots/BTFG_documentation_front_page.png" 14 | dest_files=["res://.godot/imported/BTFG_documentation_front_page.png-ee3c8157e44908e447dc44db304e4256.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /screenshots/behav_tree_for_groups_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_for_groups_flow.png -------------------------------------------------------------------------------- /screenshots/behav_tree_for_groups_flow_th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_for_groups_flow_th.png -------------------------------------------------------------------------------- /screenshots/behav_tree_tor_groups_coag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_tor_groups_coag.png -------------------------------------------------------------------------------- /screenshots/behav_tree_tor_groups_coag_th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behav_tree_tor_groups_coag_th.png -------------------------------------------------------------------------------- /screenshots/behavior_tree_for_groups_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behavior_tree_for_groups_forest.png -------------------------------------------------------------------------------- /screenshots/behavior_tree_for_groups_forest_th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/behavior_tree_for_groups_forest_th.png -------------------------------------------------------------------------------- /screenshots/icon_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascal-ballet/BehaviorTreeForGroups/d360d5bd222d4a050594e2b749cae67753934a47/screenshots/icon_big.png --------------------------------------------------------------------------------