Removed a few addons

- Upgraded to Godot 4.2
This commit is contained in:
Tony Bark 2023-12-09 23:07:31 -05:00
parent 51d2475f4d
commit dd04a01651
97 changed files with 17 additions and 3766 deletions

View file

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,7 +0,0 @@
[plugin]
name="Yet Another Behavior Tree"
description="A Behavior Tree implementation for Godot Engine"
author="Adrien Quillet"
version="3.0.0"
script="yet_another_behavior_tree.gd"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b48sosvxi4n24"
path="res://.godot/imported/btaction.png-18977c497a76704723d083978b2ea595.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btaction.png"
dest_files=["res://.godot/imported/btaction.png-18977c497a76704723d083978b2ea595.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cbnehk2kgxha0"
path="res://.godot/imported/btactionblackboarddelete.png-e03a9a160a95593083f9e35e81bdc103.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboarddelete.png"
dest_files=["res://.godot/imported/btactionblackboarddelete.png-e03a9a160a95593083f9e35e81bdc103.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://boyttypw3logy"
path="res://.godot/imported/btactionblackboardset.png-1278deabaaedde513ea46a9a4bb621bb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboardset.png"
dest_files=["res://.godot/imported/btactionblackboardset.png-1278deabaaedde513ea46a9a4bb621bb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2oj3rjstv2l6"
path="res://.godot/imported/btactioncallable.png-8ff3e8c57248454d9afe7b8c14b8034f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btactioncallable.png"
dest_files=["res://.godot/imported/btactioncallable.png-8ff3e8c57248454d9afe7b8c14b8034f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ct3k7bwcr4n23"
path="res://.godot/imported/btactionwait.png-35eefe67990a95ed2449e53d56e2cf8f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionwait.png"
dest_files=["res://.godot/imported/btactionwait.png-35eefe67990a95ed2449e53d56e2cf8f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bc3t7dlq5ojd7"
path="res://.godot/imported/btblackboard.png-7f733cee4dbff616004368a725149731.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btblackboard.png"
dest_files=["res://.godot/imported/btblackboard.png-7f733cee4dbff616004368a725149731.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://61mky8di67wd"
path="res://.godot/imported/btcomposite.png-e026d4d004e93322dbcd1e6f926f41a2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btcomposite.png"
dest_files=["res://.godot/imported/btcomposite.png-e026d4d004e93322dbcd1e6f926f41a2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d30ihyblas1o0"
path="res://.godot/imported/btcondition.png-afc407604bdfe2e82f2cbf0d2c34ed27.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btcondition.png"
dest_files=["res://.godot/imported/btcondition.png-afc407604bdfe2e82f2cbf0d2c34ed27.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b4q7fnl5uons7"
path="res://.godot/imported/btconditionblackboardkeyexists.png-6b1c537ccdd672a561e7966389cda13e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditionblackboardkeyexists.png"
dest_files=["res://.godot/imported/btconditionblackboardkeyexists.png-6b1c537ccdd672a561e7966389cda13e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://fcjo6te2i4fh"
path="res://.godot/imported/btconditionblackboardvaluescomparison.png-eecd4feaf86eb841c950cbbeb86bd20e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditionblackboardvaluescomparison.png"
dest_files=["res://.godot/imported/btconditionblackboardvaluescomparison.png-eecd4feaf86eb841c950cbbeb86bd20e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://y6usgtpm8654"
path="res://.godot/imported/btconditioncallable.png-536cf1db6a6b7ab4d372e700c9ec5b2a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditioncallable.png"
dest_files=["res://.godot/imported/btconditioncallable.png-536cf1db6a6b7ab4d372e700c9ec5b2a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cmwqhdcyhptro"
path="res://.godot/imported/btdecorator.png-8fdc93bf956127379273d9a2949c9c1c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btdecorator.png"
dest_files=["res://.godot/imported/btdecorator.png-8fdc93bf956127379273d9a2949c9c1c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c73l5rvxyrnda"
path="res://.godot/imported/btfailure.png-43c62fa29ae4a153c528e033a8bbecc9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btfailure.png"
dest_files=["res://.godot/imported/btfailure.png-43c62fa29ae4a153c528e033a8bbecc9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://gutmaw46jlyh"
path="res://.godot/imported/btinverter.png-2f7d6a7358d40fcfcaf67b8a6acea047.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btinverter.png"
dest_files=["res://.godot/imported/btinverter.png-2f7d6a7358d40fcfcaf67b8a6acea047.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://gxdluh7wjomk"
path="res://.godot/imported/btleaf.png-c2431b3a96122c6dc535e0b78c164efc.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btleaf.png"
dest_files=["res://.godot/imported/btleaf.png-c2431b3a96122c6dc535e0b78c164efc.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://byk2pkxf1m2xm"
path="res://.godot/imported/btlimiter.png-4154342ba1ecd7c753485e0c1895d99d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btlimiter.png"
dest_files=["res://.godot/imported/btlimiter.png-4154342ba1ecd7c753485e0c1895d99d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://sccepp5a5goa"
path="res://.godot/imported/btnode.png-3ebad094cfaf4e989cef065b27b78174.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btnode.png"
dest_files=["res://.godot/imported/btnode.png-3ebad094cfaf4e989cef065b27b78174.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://i8yclvjdd2po"
path="res://.godot/imported/btparallel.png-72c2892f41b80e22bfa4396abf59a1a3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btparallel.png"
dest_files=["res://.godot/imported/btparallel.png-72c2892f41b80e22bfa4396abf59a1a3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cj1bxkdykjv23"
path="res://.godot/imported/btrandom.png-0f3e4c1202cc1fd7fd32f36ce482ef97.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandom.png"
dest_files=["res://.godot/imported/btrandom.png-0f3e4c1202cc1fd7fd32f36ce482ef97.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b3s6eyhvmsmca"
path="res://.godot/imported/btrandomselector.png-5bbaa6b1d149c5357046de0f8d6b7707.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandomselector.png"
dest_files=["res://.godot/imported/btrandomselector.png-5bbaa6b1d149c5357046de0f8d6b7707.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dtc18hhykvswh"
path="res://.godot/imported/btrepeatuntil.png-b92f22528a4b73d0ca2d27142e092367.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btrepeatuntil.png"
dest_files=["res://.godot/imported/btrepeatuntil.png-b92f22528a4b73d0ca2d27142e092367.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bs628dnvnsxwl"
path="res://.godot/imported/btroot.png-5ce207fd487015fa6d9a79efff94f0e4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btroot.png"
dest_files=["res://.godot/imported/btroot.png-5ce207fd487015fa6d9a79efff94f0e4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ctyhhfi6jks5a"
path="res://.godot/imported/btselector.png-68934baa4bd97bc50fd24775d28386ac.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btselector.png"
dest_files=["res://.godot/imported/btselector.png-68934baa4bd97bc50fd24775d28386ac.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://chnob03fb7a5"
path="res://.godot/imported/btsequence.png-c2e63f47520b7d091ffbf0c6bc2a76a0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btsequence.png"
dest_files=["res://.godot/imported/btsequence.png-c2e63f47520b7d091ffbf0c6bc2a76a0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

View file

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://v47uxlomir5w"
path="res://.godot/imported/btsuccess.png-7ab9f0bea97f3881521c44275dcb2c13.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/yet_another_behavior_tree/src/Assets/Icons/btsuccess.png"
dest_files=["res://.godot/imported/btsuccess.png-7ab9f0bea97f3881521c44275dcb2c13.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -1,89 +0,0 @@
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btblackboard.png")
class_name BTBlackboard
extends Node
## Blackboard allows to share data across nodes and behavior trees. You can create/retrieve/erase
## pairs of key-value. Keys and values are variants and can be anything.
## [br][br]
## Data in blackboard can be isolated in so-called [i]namespaces[/i]. A data key can exists only once in
## a namespace, but can exists multiple times across namespaces, allowing the user to isolate data when,
## for example, a blackboard is shared between multiple behavior trees. By default, if no namespace is
## specified when inserting a data into a blackboard, the [i]default namespace[/i] is used.
const DEFAULT_NAMESPACE:String = "_default_namespace"
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
## A dictionnary allowing to specifies default entries before tree first execution.
## [br][br]
## Those entries are added in the default namespace of the blackboard. If you want to add default entries
## in another namespace, you must do it in a script.
@export var data:Dictionary = {}
#------------------------------------------
# Variables privées
#------------------------------------------
# {
# "namespace" : {
# DATAS
# }
# }
var _execution_data:Dictionary = {}
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
# On copie le dico défini par l'utilisateur dans le dico privé
_get_namespace_board(DEFAULT_NAMESPACE).merge(data)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func get_delta() -> float:
# Delta is not in any namespace, since its a volatile data, that is valid just inside one tree tick
return get_data("delta")
func has_data(key:Variant, board_namespace:String = DEFAULT_NAMESPACE) -> bool:
var namespace_dico:Dictionary = _get_namespace_board(board_namespace)
return namespace_dico.has(key)
func get_data(key:Variant, default_value:Variant = null, board_namespace:String = DEFAULT_NAMESPACE) -> Variant:
var result:Variant = _get_namespace_board(board_namespace).get(key, default_value)
return result.get_ref() if result is WeakRef else result
func set_data(key:Variant, value:Variant, board_namespace:String = DEFAULT_NAMESPACE) -> Variant:
var namespace_dico:Dictionary = _get_namespace_board(board_namespace)
var old_value:Variant = namespace_dico[key] if namespace_dico.has(key) else null
namespace_dico[key] = weakref(value) if value is Node else value
return old_value.get_ref() if old_value is WeakRef else old_value
func delete_data(key:Variant, board_namespace:String = DEFAULT_NAMESPACE) -> Variant:
var namespace_dico:Dictionary = _get_namespace_board(board_namespace)
var old_value = namespace_dico[key] if namespace_dico.has(key) else null
namespace_dico.erase(key)
return old_value.get_ref() if old_value is WeakRef else old_value
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _get_namespace_board(board_namespace:String) -> Dictionary:
if not _execution_data.has(board_namespace):
_execution_data[board_namespace] = {}
return _execution_data[board_namespace]

View file

@ -1,126 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btnode.png")
class_name BTNode
extends Node
## Base object for all behavior tree nodes.
## [b][u]This node should never be used directly.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var _is_in_editor:bool = Engine.is_editor_hint()
var _children:Array[BTNode] = []
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _init() -> void:
super._init()
if _is_in_editor:
_connect_signal_if_needed(child_entered_tree, _update_configuration_warnings_1)
_connect_signal_if_needed(child_exiting_tree, _update_configuration_warnings_1)
_connect_signal_if_needed(tree_entered, _update_configuration_warnings_0)
_connect_signal_if_needed(tree_exited, _update_configuration_warnings_0)
_connect_signal_if_needed(child_entered_tree, _update_cached_children)
_connect_signal_if_needed(child_exiting_tree, _update_cached_children)
func _ready() -> void:
if _is_in_editor:
update_configuration_warnings()
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
return BTTickResult.SUCCESS
func is_leaf() -> bool:
return false
func enter(blackboard:BTBlackboard) -> void:
pass
func start(blackboard:BTBlackboard) -> void:
pass
func stop(blackboard:BTBlackboard) -> void:
pass
func exit(blackboard:BTBlackboard) -> void:
pass
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _update_configuration_warnings_0() -> void:
update_configuration_warnings()
func _update_configuration_warnings_1(any) -> void:
update_configuration_warnings()
func is_valid() -> bool:
return false
func _update_cached_children(any) -> void:
_children.clear()
for child in get_children():
if child is BTNode:
_children.append(child)
func _execute(actor:Node, blackboard:BTBlackboard) -> int:
if _is_in_editor:
return BTTickResult.FAILURE
_enter(blackboard);
_start(actor, blackboard)
var result:int = tick(actor, blackboard)
if result != BTTickResult.RUNNING:
_stop(actor, blackboard)
_exit(blackboard)
return result
func _enter(blackboard:BTBlackboard) -> void:
enter(blackboard)
pass
func _start(actor:Node, blackboard:BTBlackboard) -> void:
var blackboard_namespace:String = str(actor.get_instance_id())
blackboard.get_data("running_nodes", [], blackboard_namespace).append(self)
if not blackboard.get_data("previously_running_nodes", [], blackboard_namespace).has(self):
start(blackboard)
func _stop(actor:Node, blackboard:BTBlackboard) -> void:
var blackboard_namespace:String = str(actor.get_instance_id())
blackboard.get_data("running_nodes", [], blackboard_namespace).erase(self)
exit(blackboard)
stop(blackboard)
func _exit(blackboard:BTBlackboard) -> void:
pass
func _connect_signal_if_needed(sig:Signal, callable:Callable) -> void:
if not sig.is_connected(callable):
sig.connect(callable)

View file

@ -1,196 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btroot.png")
class_name BTRoot
extends BTNode
## This behavior tree is a Godot node that can be added to your Scene tree. The logic inside tree nodes
## will be run every frame, during process or physics process, depending on tree process mode.
## [br][br]
## At each frame, the [code]tick[/code] function of tree nodes will be run. This function has access to the
## [i]actor[/i] (the node the tree is describing behavior for), and a [i]blackboard[/i] (allowing to share
## data between nodes). The tick function can either returns:
## [br]
## - [code]SUCCESS[/code], indicating that node execution is successful,[br]
## - [code]RUNNING[/code], indicating that node is doing a long computation/action/whatever you want, that is not finished yet,[br]
## - [code]FAILURE[/code], indicating that something went wrong during child execution (condition not met, ...).
## [br][br]
## Depending on your tree structure, node result will produce various behaviors. See node documentation for
## mor details.
enum BTRootProcessMode {
PROCESS,
PHYSIC_PROCESS
}
#------------------------------------------
# Signaux
#------------------------------------------
signal on_running(running_node_names:Array)
signal on_idle()
#------------------------------------------
# Exports
#------------------------------------------
## Indicates if tree should run or not
@export var enabled:bool = true:
set(value):
enabled = value
set_process(enabled)
set_physics_process(enabled)
## Indicates whether tree should execute during [i]process[/i] or [i]physics process[/i].
@export var root_process_mode:BTRootProcessMode = BTRootProcessMode.PHYSIC_PROCESS
## Path to the node that the tree is drescribing actions for. This is the node that will be passed to all
## tree nodes, allowing you to manipulate the actor at every tree step.
@export var actor_path:NodePath :
set(value):
actor_path = value
_update_actor_from_path()
update_configuration_warnings()
## Path to the blackboard node. This allows to share a same blackboard between several trees, for example to code
## a group of enemies acting together, or to specify some default entries using the editor. If empty, a default
## empty blackboard will be used during tree execution.
@export var blackboard:BTBlackboard = null :
set(value):
blackboard = value
_update_blackboard()
update_configuration_warnings()
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _blackboard:BTBlackboard
var _previous_running_nodes:Array[BTNode] = []
var _actor:Node
var _execution_start_time_ms:float
var _execution_stop_time_ms:float
@onready var _performance_monitor_identifier:String = "BTRoot/%s-%s" % [get_name(), get_instance_id()]
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
super._ready()
if not is_valid():
push_error("BTRoot '%s'(%s) is not valid, check its configuration" % [get_name(), get_instance_id()])
# Init du blackboard: soit celui de l'utilisateur, soit un tout neuf
_update_blackboard()
if not Engine.is_editor_hint():
_add_custom_performance_monitor()
tree_entered.connect(_add_custom_performance_monitor)
tree_exited.connect(_remove_custom_performance_monitor)
func _process(delta:float) -> void:
if not Engine.is_editor_hint() and enabled and root_process_mode == BTRootProcessMode.PROCESS:
_do_execute(delta)
func _physics_process(delta:float) -> void:
if not Engine.is_editor_hint() and enabled and root_process_mode == BTRootProcessMode.PHYSIC_PROCESS:
_do_execute(delta)
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
if not _check_direct_children_validity():
warnings.append("Root tree must contains only one child of type BTComposite")
if not _check_actor_validity():
warnings.append("Root tree actor must be filled")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _check_direct_children_validity() and _check_actor_validity()
func _check_direct_children_validity() -> bool:
var is_valid:bool = get_child_count() == 1
if is_valid:
is_valid = get_child(0) is BTComposite
return is_valid
func _check_actor_validity() -> bool:
var is_valid:bool = actor_path != null and not actor_path.is_empty()
if is_valid:
_update_actor_from_path()
is_valid =_actor != null and is_instance_valid(_actor)
return is_valid
func _update_blackboard() -> void:
if blackboard != null and is_instance_valid(blackboard):
_blackboard= blackboard
else:
_blackboard = BTBlackboard.new()
func _update_actor_from_path() -> void:
_actor = get_node_or_null(actor_path)
if not is_instance_valid(_actor) and is_inside_tree():
# Fallback : si le chemin donné n'était pas relatif à la scene courante, on le check en absolu
_actor = get_tree().current_scene.get_node_or_null(actor_path)
func _do_execute(delta:float):
_register_execution_start()
var blackboard_namespace:String = str(_actor.get_instance_id())
# delta est une donnée volatile, elle n'est donc pas dans un namespace puisque chaque arbre tourne
# séquentiellement, donc il n'y a pas de collision de données en cas de partage du blackboard
_blackboard.set_data("delta", delta)
_blackboard.set_data("previously_running_nodes", Array(_previous_running_nodes), blackboard_namespace)
_blackboard.set_data("running_nodes", [], blackboard_namespace)
_children[0]._execute(_actor, _blackboard)
var raw_running_nodes:Array = _blackboard.get_data("running_nodes", [], blackboard_namespace)
var running_nodes:Array[BTNode] = []
running_nodes.append_array(raw_running_nodes)
if _previous_running_nodes != running_nodes:
for n in _previous_running_nodes:
if not running_nodes.has(n):
n._stop(_actor, _blackboard)
if not running_nodes.is_empty():
var running_node_names:Array[String] = []
for running_node in running_nodes:
if running_node.is_leaf():
running_node_names.append(str(running_node.name))
on_running.emit(running_node_names)
else:
on_idle.emit()
_previous_running_nodes = running_nodes
_register_execution_stop()
func _add_custom_performance_monitor() -> void:
if not Performance.has_custom_monitor(_performance_monitor_identifier):
Performance.add_custom_monitor(_performance_monitor_identifier, _compute_last_exec_time)
func _remove_custom_performance_monitor() -> void:
if Performance.has_custom_monitor(_performance_monitor_identifier):
Performance.remove_custom_monitor(_performance_monitor_identifier)
func _register_execution_start() -> void:
_execution_start_time_ms = Time.get_ticks_msec()
func _register_execution_stop() -> void:
_execution_stop_time_ms = Time.get_ticks_msec()
func _compute_last_exec_time() -> float:
return _execution_stop_time_ms - _execution_start_time_ms

View file

@ -1,59 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btcomposite.png")
class_name BTComposite
extends BTNode
## Base object for all behavior tree composites.
## Composite nodes defines the root of a tree branch : each branch can be seen as a rule for your AI.
## They accept any kind of behavior tree nodes as children. It can either be a composite, decorator or leaf nodes
## [b][u]This node should never be used directly.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
if not _has_at_least_one_child():
warnings.append("A composite must have at least one child node")
if not _all_children_are_bt_nodes():
warnings.append("A composite must have children nodes of type BTNode")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _has_at_least_one_child() and _all_children_are_bt_nodes()
func _has_at_least_one_child() -> bool:
return get_child_count() >= 1
func _all_children_are_bt_nodes() -> bool:
for child in get_children():
if not child is BTNode:
return false
return true

View file

@ -1,58 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btparallel.png")
class_name BTParallel
extends BTComposite
## The parallel node is a [i]composite node[/i] that executes all its children at each [code]tick[/code].
## If at least one child is is running, the parallel reports it's running too. If no child is running,
## then if at least one child succeeded, the parallel reports success, else it reports failure.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var at_least_one_child_running:bool = false
var at_least_one_child_success:bool = false
for child in _children:
var result:int = child._execute(actor, blackboard)
if result == BTTickResult.SUCCESS:
at_least_one_child_success = true
if result == BTTickResult.RUNNING:
at_least_one_child_running = true
# At least one running : this is still running !
if at_least_one_child_running:
return BTTickResult.RUNNING
# No one is running, so, at least one success > success, else failure
elif at_least_one_child_success:
return BTTickResult.SUCCESS
else:
return BTTickResult.FAILURE
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,42 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandomselector.png")
class_name BTRandomSelector
extends BTSelector
## The random selector node is a [i]composite node[/i] that behaves like the [code]BTSelector[/code] node,
## except that it executes its children in random order.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func start(blackboard:BTBlackboard) -> void:
super.start(blackboard)
if not save_progression or _running_child_index == -1:
_children.shuffle()

View file

@ -1,63 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btselector.png")
class_name BTSelector
extends BTComposite
## The selector node is a [i]composite node[/i] that executes its children from the first one to the last one,
## in order, until one of them returns [code]SUCCESS[/code]. If a selector child succeeds, the selector
## succeed too. If all selector children failed, the selector fails too.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Indicates whether the selector should resume to the last running child on next tree execution ([code]on[/code]),
## or restart from its first child ([code]off[/code]). Its usefull to describe a non-interruptible action,
## or to optimize process time.
@export var save_progression:bool = false
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _running_child_index:int = -1
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
for child_index in _children.size():
if not save_progression or child_index >= _running_child_index:
var child:BTNode = _children[child_index]
var result:int = child._execute(actor, blackboard)
if result != BTTickResult.FAILURE:
if save_progression and result == BTTickResult.RUNNING:
_running_child_index = child_index
return result
return BTTickResult.FAILURE
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func start(blackboard:BTBlackboard) -> void:
_running_child_index = 0
func stop(blackboard:BTBlackboard) -> void:
_running_child_index = -1

View file

@ -1,63 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btsequence.png")
class_name BTSequence
extends BTComposite
## The sequence node is a [i]composite node[/i] that executes its children from the first one to the last
## one, until all children succeed or one of its children fails. If all children succeed, the sequence
## succeeds too ; if one child fails, the sequence fails too.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Indicates whether the sequence should resume to the last running child on next tree execution ([code]on[/code]),
## or restart from its first child ([code]off[/code]). Its usefull to describe a non-interruptible action, or to
## optimize process time.
@export var save_progression:bool = false
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _running_child_index:int = -1
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
for child_index in _children.size():
if not save_progression or child_index >= _running_child_index:
var child:BTNode = _children[child_index]
var result:int = child._execute(actor, blackboard)
if result != BTTickResult.SUCCESS:
if save_progression and result == BTTickResult.RUNNING:
_running_child_index = child_index
return result
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func start(blackboard:BTBlackboard) -> void:
_running_child_index = 0
func stop(blackboard:BTBlackboard) -> void:
_running_child_index = -1

View file

@ -1,58 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btdecorator.png")
class_name BTDecorator
extends BTNode
## Base object for all behavior tree decorators.
## Decorator nodes allow to customize result of its only child node.
## [b][u]This node should never be used directly.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
if not _has_only_one_child():
warnings.append("A decorator must have only one child")
if not _child_is_bt_node():
warnings.append("A decorator must have a child of type BTNode")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _has_only_one_child() and _child_is_bt_node()
func _has_only_one_child() -> bool:
return get_child_count() >= 1
func _child_is_bt_node() -> bool:
for child in get_children():
if not child is BTNode:
return false
return true

View file

@ -1,41 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btfailure.png")
class_name BTFailure
extends BTDecorator
## The failure node is a [i]decorator[/i] node that always returns [i]failed[/i] on child execution.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
_children[0]._execute(actor, blackboard)
return BTTickResult.FAILURE
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,47 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btinverter.png")
class_name BTInverter
extends BTDecorator
## The inverter node is a [i]decorator[/i] node returns [i]success[/i] when its child fails its execution,
## and [i]failure[/i] when its child succeeds its execution. When its child is [i]running[/i], it returns
## [i]running[/i] too.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var child_result:int = _children[0]._execute(actor, blackboard)
if child_result == BTTickResult.SUCCESS:
return BTTickResult.FAILURE
if child_result == BTTickResult.FAILURE:
return BTTickResult.SUCCESS
return BTTickResult.RUNNING
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,60 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btlimiter.png")
class_name BTLimiter
extends BTDecorator
## The limiter node is a [i]decorator[/i] node that limits the total number of execution of its child node.
## When the limit is not reachs, the limiter nodes reports its child execution status. Once the limit is reachs,
## it never executs its child and always report a [i]failed[/i] execution.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Number of allowed child execution.
@export_range(0, 9999999, 1) var limit:int = 1
## Whether or not the [code]limit[/code] value is included into the number of times the child can run.
## It clarifies the usage of the limit.
@export var include_limit:bool = true
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _invocation_count:int = 0
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var limit_reached:bool = _invocation_count >= limit
if not include_limit:
limit_reached = _invocation_count >= limit - 1
if limit_reached:
return BTTickResult.FAILURE
var result:int = _children[0]._execute(actor, blackboard)
if result != BTTickResult.RUNNING:
_invocation_count += 1
return result
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,47 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandom.png")
class_name BTRandom
extends BTDecorator
## The random node is a [i]decorator[/i] node randomly execute its child. If the child is executed,
## the node result is the same as its child result. Otherwise, result is [i]failure[/i].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## A float between [code]0[/code] (included) and [code]1[/code] (included) indicating the probability of child
## execution.
@export_range(0, 1) var probability:float = 0.5
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var random_float:float = randf()
if random_float > probability:
return BTTickResult.FAILURE
return _children[0]._execute(actor, blackboard)
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,67 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrepeatuntil.png")
class_name BTRepeatUntil
extends BTDecorator
## The repeat until node is a [i]decorator[/i] node that loop its child execution until child execution result
## is as excepted. It is possible to specifies the maximum number of loop execution allowed to obtain the desired
## result. If desired result is obtained before the loop execution limit, the repeat until node returns the
## obtained result. If not, its returns a [i]failure[/i].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Expected child result to stop the loop.
@export_enum("SUCCESS:0", "RUNNING:1", "FAILURE:2") var stop_condition:int = 0
## Maximum number of child execution to obtain the desired result. If value is [code]0[/code], there is
## [b]no limit[/b] to the number of times the loop can run (⚠️ be careful to not create an infinite loop).
## If value is more than zero, its represents the maximum number of loop execution.
@export_range(0, 999999) var max_iteration:int = 0
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var result:int
var not_stopped:bool = true
var iteration_count:int = 0
while not_stopped:
result = _children[0]._execute(actor, blackboard)
if stop_condition == BTTickResult.SUCCESS and result == BTTickResult.SUCCESS:
not_stopped = false
if stop_condition == BTTickResult.RUNNING and result == BTTickResult.RUNNING:
not_stopped = false
if stop_condition == BTTickResult.FAILURE and result == BTTickResult.FAILURE:
not_stopped = false
if max_iteration > 0:
iteration_count += 1
if not not_stopped and iteration_count > max_iteration:
not_stopped = false
return result
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,41 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btsuccess.png")
class_name BTSuccess
extends BTDecorator
## The success node is a [i]decorator[/i] node that always returns [i]success[/i] on child execution.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
_children[0]._execute(actor, blackboard)
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,38 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btaction.png")
class_name BTAction
extends BTLeaf
## The action node is a [i]leaf[/i] node. Its purpose is to return [i]success[/i] when an action is completed,
## [i]failure[/i] if its fails to execute, and [i]running[/i] if the action is occuring but is not completed yet.
## [b][u]Users must subclass this node to implements their own actions.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,64 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboarddelete.png")
class_name BTActionBlackboardDelete
extends BTLeaf
## The blackboard delete action node is a [i]leaf[/i] node. It allows to erase a key from the tree blackboard.
## This node operates in the blackboard [i]default namespace[/i].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Name of the key that must be erased from blackboard, in [i]default namespace[/i]
@export var blackboard_key:String = "" :
set(value):
blackboard_key = value
update_configuration_warnings()
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _blackboard_key_is_set():
warnings.append("Blackboard key must be set")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
blackboard.delete_data(blackboard_key)
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
var is_valid:bool = super.is_valid()
if is_valid:
is_valid = _blackboard_key_is_set()
return is_valid
func _blackboard_key_is_set() -> bool:
return blackboard_key != null and not blackboard_key.is_empty()

View file

@ -1,98 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboardset.png")
class_name BTActionBlackboardSet
extends BTLeaf
## The blackboard set action node is a [i]leaf[/i] node. It allows to set a value in the blackboard.
## Its execution always returns [i]success[/i]. This node operates in the blackboard [i]default namespace[/i].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Name of the key that must be set, in [i]default namespace[/i]
@export var blackboard_key:String = "" :
set(value):
blackboard_key = value
update_configuration_warnings()
## An expression representing the value to associated to the given key. The expression will be evaluated by
## Godot Engine during child execution. It should be simple. See [url=https://docs.godotengine.org/en/latest/classes/class_expression.html]Godot Expression[/url]
## for details. In expression, user has access to two predefined variables:[br]
## - [code]actor[/code]: the node the tree is describing action for,[br]
## - [code]blackboard[/code]: the tree blackboard,[br]
## - [code]delta[/code]: the [i]_process[/i] or [i]_physics_process[/i] delta value, as a [code]float[/code].
@export_multiline var expression:String = "" :
set(value):
if value != expression:
expression = value
_update_expression()
update_configuration_warnings()
## Indicates if the value must be overwritten if it already exists or not
@export var can_overwrite_value:bool = false
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _expression:BTExpression = BTExpression.new()
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _blackboard_key_is_set():
warnings.append("Blackboard key must be set")
if not _expression_key_is_set():
warnings.append("Expression must be set")
if not _expression_is_valid():
warnings.append("Expression is not valid")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
if can_overwrite_value or not blackboard.has_data(blackboard_key):
var value:Variant = _expression.evaluate(actor, blackboard)
blackboard.set_data(blackboard_key, value)
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
var is_valid:bool = super.is_valid()
if is_valid:
is_valid = _blackboard_key_is_set()
if is_valid:
is_valid = _expression_key_is_set()
return is_valid
func _blackboard_key_is_set() -> bool:
return blackboard_key != null and not blackboard_key.is_empty()
func _expression_key_is_set() -> bool:
return expression != null and not expression.is_empty()
func _expression_is_valid() -> bool:
return _expression.is_valid()
func _update_expression() -> void:
_expression.expression = expression

View file

@ -1,123 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactioncallable.png")
class_name BTActionCallable
extends BTLeaf
## The callable action node is a [i]leaf[/i] node. At each tick, the node calls a function from an object that has
## been parametrized. It can also pass arguments to this function. Its result depends of the specified function
## result:
## [br]
## - If specified function returns a [code]bool[/code], then the tick result is [i]success[i] is boolean
## is [code]true[/code], [i]failure[/i] otherwise,[br]
## - If the specified function returns an [code]int[/code], it is interpreted as the enum values [code]SUCCESS[/code],
## [code]RUNNING[/code] or [code]FAILURE[/code] from [code]BTTickResult[/code] object. If another value is returned
## by specified function, behavior is undefined,[br]
## - If specified function returns nothing ([code]void[/code] or [code]null[/code] result), then [i]success[/i]
## is returned.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Path to the node that contains the function to call
@export var method_owner_path:NodePath:
set(value):
method_owner_path = value
_update_method_owner_from_path()
update_configuration_warnings()
## Name of the function to call in the [i]method owner node[/i]
@export var method_name:String = "":
set(value):
method_name = value
update_configuration_warnings()
## Array of arguments to pass when calling the function. Arguments are expressions that will
## be evaluated by Godot Engine at runtime to produce the desired value. See [url=https://docs.godotengine.org/en/latest/classes/class_expression.html]Godot Expression[/url]
## for details. In expression, user has access to two predefined variables:[br]
## - [code]actor[/code]: the node the tree is describing action for,[br]
## - [code]blackboard[/code]: the tree blackboard,[br]
## - [code]delta[/code]: the [i]_process[/i] or [i]_physics_process[/i] delta value, as a [code]float[/code].[br]
## Number and types of arguments must match function prototype, or an error will occurs at runtime.
@export var method_arguments:Array[String] = []
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _method_owner:Node
var _cached_method_arguments:Array[String] = []
var _argument_expression:Array[BTExpression] = []
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_update_method_owner_from_path()
_update_argument_expressions()
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _check_method_owner_validity():
warnings.append("Method owner must be set")
if not _check_method_name_validity():
warnings.append("Method name must be set")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
_update_argument_expressions()
var arguments:Array[Variant] = _argument_expression.map(func(expr):return expr.evaluate(actor, blackboard))
var result:Variant = _method_owner.callv(method_name, arguments)
if result is bool:
return BTTickResult.SUCCESS if result else BTTickResult.FAILURE
if result is int:
return result
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _check_method_owner_validity() and _check_method_name_validity()
func _check_method_owner_validity() -> bool:
var is_valid:bool = method_owner_path != null and not method_owner_path.is_empty()
if is_valid:
_update_method_owner_from_path()
is_valid = _method_owner != null and is_instance_valid(_method_owner)
return is_valid
func _check_method_name_validity() -> bool:
return method_name != null and not method_name.is_empty()
func _update_method_owner_from_path() -> void:
_method_owner = get_node_or_null(method_owner_path)
if not is_instance_valid(_method_owner) and is_inside_tree():
# Fallback : si le chemin donné n'était pas relatif à la scene courante, on le check en absolu
_method_owner = get_tree().current_scene.get_node_or_null(method_owner_path)
func _update_argument_expressions() -> void:
if _cached_method_arguments != method_arguments:
_cached_method_arguments = Array(method_arguments)
_argument_expression.clear()
for expr in _cached_method_arguments:
var btexpression:BTExpression = BTExpression.new()
btexpression.expression = expr
_argument_expression.append(btexpression)

View file

@ -1,62 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionwait.png")
class_name BTActionWait
extends BTLeaf
## The wait action node is a [i]leaf[/i] node. Its execution returns [i]running[/i] during the specified wait time,
## then returns *success* when specified time is elapsed. After succeeded, the wait time is rearmed for next
## tree execution.
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Number of milliseconds to wait before returning [i]success[/i]
@export var wait_time_ms:int = 1_000
## Indicates if a random deviation should be applied to the wait time. [code]0[/code] means there is no
## deviation et the wait time will be strictyl respected. Random deviation may change after each node rearm.
@export var random_deviation_ms:int = 0
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _current_time_ms:float = 0
var _time_to_reach_ms:int
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
_current_time_ms += blackboard.get_delta() * 1_000
if _current_time_ms <= _time_to_reach_ms:
return BTTickResult.RUNNING
return BTTickResult.SUCCESS
func start(blackboard:BTBlackboard) -> void:
_current_time_ms = 0
_time_to_reach_ms = wait_time_ms
if random_deviation_ms != 0:
_time_to_reach_ms += randi_range(0, random_deviation_ms)
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,38 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btcondition.png")
class_name BTCondition
extends BTLeaf
## The condition node is a [i]leaf[/i] node. Its purpose is to return [i]success[/i] when a condition is meet,
## [i]failure[/i] otherwise. This node should never return [i]running[/i].
## [b][u]Users must subclass this node to implements their own conditions.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,66 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditionblackboardkeyexists.png")
class_name BTConditionBlackboardKeyExists
extends BTLeaf
## The blackboard key exists condition node is a [i]leaf[/i] node. It returns [i]success[/i] if a certain key
## is present in the tree blackboard during its execution, [i]failure[/i] otherwise. This node operates in the blackboard
## [i]default namespace[/i].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Name of the key that must exists in the blackboard, in [i]default namespace[/i]
@export var blackboard_key:String = "" :
set(value):
blackboard_key = value
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _blackboard_key_is_set():
warnings.append("Blackboard key must be set")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var result:int = BTTickResult.FAILURE
if blackboard.has_data(blackboard_key):
result = BTTickResult.SUCCESS
return result
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
var is_valid:bool = super.is_valid()
if is_valid:
is_valid = _blackboard_key_is_set()
return is_valid
func _blackboard_key_is_set() -> bool:
return blackboard_key != null and not blackboard_key.is_empty()

View file

@ -1,105 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditionblackboardvaluescomparison.png")
class_name BTConditionBlackboardValuesComparison
extends BTLeaf
## The blackboard values comparison condition node is a [i]leaf[/i] node. It returns [i]success[/i] both values
## represented by specified keys returns true when compared using the given operator. This node operates in the blackboard
## [i]default namespace[/i].
enum Operator {
EQUAL = 1,
NOT_EQUAL = 2,
LOWER = 3,
LOWER_OR_EQUAL = 4,
GREATER = 5,
GREATER_OR_EQUAL = 6
}
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Name of the key that old the first value to compare, in [i]default namespace[/i]
@export var first_operand_blackboard_key:String = "" :
set(value):
first_operand_blackboard_key = value
update_configuration_warnings()
## Operator used to compare values
@export_enum("EQUAL:1", "NOT_EQUAL:2", "LOWER:3", "LOWER_OR_EQUAL:4", "GREATER:5", "GREATER_OR_EQUAL:6") var operator:int = 0
## Name of the key that old the second value to compare, [i]default namespace[/i]
@export var second_operand_blackboard_key:String = "" :
set(value):
second_operand_blackboard_key = value
update_configuration_warnings()
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _parsed_compared_value:Variant
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _blackboard_keys_are_set():
warnings.append("Blackboard keys must be set")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
var result:int = BTTickResult.FAILURE
var first_operand:Variant = blackboard.get_data(first_operand_blackboard_key)
var second_operand:Variant = blackboard.get_data(second_operand_blackboard_key)
if first_operand != null and second_operand != null:
var compare_result:bool = false
match(operator):
Operator.EQUAL:
compare_result = first_operand == second_operand
Operator.NOT_EQUAL:
compare_result = first_operand != second_operand
Operator.LOWER:
compare_result = first_operand < second_operand
Operator.LOWER_OR_EQUAL:
compare_result = first_operand <= second_operand
Operator.GREATER:
compare_result = first_operand > second_operand
Operator.GREATER_OR_EQUAL:
compare_result = first_operand >= second_operand
if compare_result:
return BTTickResult.SUCCESS
return result
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
var is_valid:bool = super.is_valid()
if is_valid:
is_valid = _blackboard_keys_are_set()
return is_valid
func _blackboard_keys_are_set() -> bool:
return first_operand_blackboard_key != null and not first_operand_blackboard_key.is_empty() and second_operand_blackboard_key != null and not second_operand_blackboard_key.is_empty()

View file

@ -1,112 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btconditioncallable.png")
class_name BTConditionCallable
extends BTLeaf
## The callable condition node is a [i]leaf[/i] node. The node calls a function from an object that has been
## parametrized to check for a condition. It can also pass arguments to this function. Its result is the function
## result, meaning that specified function must returns a [code]bool[/code] value. This nodes returns
## [i]success[/i] if function call returned [code]true[/code], and [i]failure[/i] if function call returned [code]false[/code].
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
## Path to the node that contains the function to call
@export var method_owner_path:NodePath:
set(value):
method_owner_path = value
_update_method_owner_from_path()
update_configuration_warnings()
## Name of the function to call in the [i]method owner node[i]
@export var method_name:String = "":
set(value):
method_name = value
update_configuration_warnings()
## Array of arguments to pass when calling the function. Arguments are expressions that will
## be evaluated by Godot Engine at runtime to produce the desired value. See [url=https://docs.godotengine.org/en/latest/classes/class_expression.html]Godot Expression[/url]
## for details. In expression, user has access to two predefined variables:[br]
## - [code]actor[/code]: the node the tree is describing action for,[br]
## - [code]blackboard[/code]: the tree blackboard,[br]
## - [code]delta[/code]: the [i]_process[/i] or [i]_physics_process[/i] delta value, as a [code]float[/code].[br]
## Number and types of arguments must match function prototype, or an error will occurs at runtime.
@export var method_arguments:Array[String] = []
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _method_owner:Node
var _cached_method_arguments:Array[String] = []
var _argument_expression:Array[BTExpression] = []
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_update_method_owner_from_path()
_update_argument_expressions()
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
warnings.append_array(super._get_configuration_warnings())
if not _check_method_owner_validity():
warnings.append("Method owner must be set")
if not _check_method_name_validity():
warnings.append("Method name must be set")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node, blackboard:BTBlackboard) -> int:
_update_argument_expressions()
var arguments:Array[Variant] = _argument_expression.map(func(expr):return expr.evaluate(actor, blackboard))
var result:bool = _method_owner.callv(method_name, arguments)
return BTTickResult.SUCCESS if result else BTTickResult.FAILURE
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _check_method_owner_validity() and _check_method_name_validity()
func _check_method_owner_validity() -> bool:
var is_valid:bool = method_owner_path != null and not method_owner_path.is_empty()
if is_valid:
_update_method_owner_from_path()
is_valid = _method_owner != null and is_instance_valid(_method_owner)
return is_valid
func _check_method_name_validity() -> bool:
return method_name != null and not method_name.is_empty()
func _update_method_owner_from_path() -> void:
_method_owner = get_node_or_null(method_owner_path)
if not is_instance_valid(_method_owner) and is_inside_tree():
# Fallback : si le chemin donné n'était pas relatif à la scene courante, on le check en absolu
_method_owner = get_tree().current_scene.get_node_or_null(method_owner_path)
func _update_argument_expressions() -> void:
if _cached_method_arguments != method_arguments:
_cached_method_arguments = Array(method_arguments)
_argument_expression.clear()
for expr in _cached_method_arguments:
var btexpression:BTExpression = BTExpression.new()
btexpression.expression = expr
_argument_expression.append(btexpression)

View file

@ -1,55 +0,0 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btleaf.png")
class_name BTLeaf
extends BTNode
## Base object for all behavior tree leaves.
## Leaf nodes, as their name implies, do not have any child. They represents basic unit of work of your
## AI, which can be separated into two notions: conditions and actions.
## [b][u]This node should never be used directly.[/u][/b]
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _get_configuration_warnings() -> PackedStringArray:
var warnings:PackedStringArray = []
if not _has_no_child():
warnings.append("A leaf must not have child")
return warnings
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func is_leaf() -> bool:
return true
#------------------------------------------
# Fonctions privées
#------------------------------------------
func is_valid() -> bool:
return _has_no_child()
func _has_no_child() -> bool:
return get_child_count() == 0

View file

@ -1,36 +0,0 @@
extends RefCounted
class_name BTTickResult
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
enum {
SUCCESS = 0,
RUNNING = 1,
FAILURE = 2
}
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,64 +0,0 @@
extends RefCounted
class_name BTExpression
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
var expression:String = "":
set(value):
if value != expression:
expression = value
_expression = _parse_expression(expression)
#------------------------------------------
# Variables privées
#------------------------------------------
var _expression:Expression
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func is_valid() -> bool:
return _expression != null
func evaluate(actor:Node, blackboard:BTBlackboard) -> Variant:
var arguments:Array[Variant] = [actor, blackboard, blackboard.get_delta()]
return _execute_expression(arguments)
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _parse_expression(string_expr:String) -> Expression:
var expr:Expression = Expression.new()
var parse_code:int = expr.parse(string_expr, ["actor", "blackboard", "delta"])
if parse_code != OK:
push_error("Unable to parse expression '%s' : %s" % [string_expr, expr.get_error_text()])
return null
return expr
func _execute_expression(arguments:Array[Variant]) -> Variant:
var result:Variant = null
if _expression == null:
_expression = _parse_expression(expression)
if _expression != null:
result = _expression.execute(arguments, self, true)
if _expression.has_execute_failed():
result = null
push_error("Unable to execute expression '%s' : %s" % [expression, _expression.get_error_text()])
return result

View file

@ -1,12 +0,0 @@
@tool
extends EditorPlugin
func _enter_tree() -> void:
# Initialization of the plugin goes here.
pass
func _exit_tree() -> void:
# Clean-up of the plugin goes here.
pass

View file

@ -3,16 +3,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cc4ebemse18ew"
path.etc2="res://.godot/imported/Items_Albedo.png-205aaab346b168397ea1ea1ce5aceabf.etc2.ctex"
path.s3tc="res://.godot/imported/Items_Albedo.png-205aaab346b168397ea1ea1ce5aceabf.s3tc.ctex"
metadata={
"imported_formats": ["etc2_astc"],
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/Items_Albedo.png"
dest_files=["res://.godot/imported/Items_Albedo.png-205aaab346b168397ea1ea1ce5aceabf.etc2.ctex"]
dest_files=["res://.godot/imported/Items_Albedo.png-205aaab346b168397ea1ea1ce5aceabf.s3tc.ctex"]
[params]

View file

@ -3,16 +3,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dope3srd2yn16"
path.etc2="res://.godot/imported/Items_EM.png-d56acc99adf5d5835b381b256fd4a6e3.etc2.ctex"
path.s3tc="res://.godot/imported/Items_EM.png-d56acc99adf5d5835b381b256fd4a6e3.s3tc.ctex"
metadata={
"imported_formats": ["etc2_astc"],
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/Items_EM.png"
dest_files=["res://.godot/imported/Items_EM.png-d56acc99adf5d5835b381b256fd4a6e3.etc2.ctex"]
dest_files=["res://.godot/imported/Items_EM.png-d56acc99adf5d5835b381b256fd4a6e3.s3tc.ctex"]
[params]

View file

@ -1,12 +0,0 @@
# 🗣️ Sharing blackboard : the talking game !
This example demonstrates how to share a single blackboard in multiple behavior trees.
Sharing a blackboard can be necessary if you want to easily share data between trees, for example, to synchronize multiple NPCs.
The blackboard can be instantiate in a Scene Tree via the editor, or in a script (as in this example).
## Technical elements
- `main.tscn` : scene to run. The main scene instantiates a unique blackboard and give it to all player trees,
- `player.tscn` : a player in the talking game. They all share the same blackboard to known who is the next to talk.

View file

@ -1,42 +0,0 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _shared_blackboard:BTBlackboard
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_shared_blackboard = BTBlackboard.new()
_shared_blackboard.set_data("next_talking", "Alice")
_shared_blackboard.set_data("players", [])
$"PlayerAlice/BTRoot/".blackboard = _shared_blackboard
$"PlayerBob/BTRoot/".blackboard = _shared_blackboard
$"PlayerCharles/BTRoot/".blackboard = _shared_blackboard
$"PlayerEmily/BTRoot/".blackboard = _shared_blackboard
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,23 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://d1s5iyoblr4cm"]
[ext_resource type="Script" path="res://examples/blackboard_sharing/main.gd" id="1_g7q7h"]
[ext_resource type="PackedScene" uid="uid://7k8r0e84lcr3" path="res://examples/blackboard_sharing/player.tscn" id="2_y55mt"]
[node name="World" type="Node2D"]
script = ExtResource("1_g7q7h")
[node name="PlayerAlice" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(509, 181)
player_name = "Alice"
[node name="PlayerBob" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(515, 477)
player_name = "Bob"
[node name="PlayerCharles" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(309, 324)
player_name = "Charles"
[node name="PlayerEmily" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(733, 322)
player_name = "Emily"

View file

@ -1,63 +0,0 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var player_name:String = "":
set(value):
player_name = value
if _name_label:
_name_label.text = player_name
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var _text_label:Label = $GUI/Text
@onready var _name_label:Label = $GUI/Name
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_name_label.text = player_name
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func declare_presence(blackboard:BTBlackboard) -> int:
blackboard.get_data("players").append(player_name)
return BTTickResult.SUCCESS
func is_my_turn_to_talk(next_talking:String) -> bool:
return player_name == next_talking
func talk() -> int:
_text_label.visible = true
get_tree().create_timer(1).timeout.connect(func():_text_label.visible = false)
return BTTickResult.SUCCESS
func choose_next_player_talking(blackboard:BTBlackboard) -> int:
blackboard.set_data("next_talking", _pick_next_player(blackboard.get_data("players")))
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _pick_next_player(players:Array) -> String:
var result:String = players.pick_random()
while result == player_name:
result = players.pick_random()
return result

View file

@ -1,123 +0,0 @@
[gd_scene load_steps=11 format=3 uid="uid://7k8r0e84lcr3"]
[ext_resource type="Script" path="res://examples/blackboard_sharing/player.gd" id="1_1ti0g"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/BTRoot.gd" id="2_sdd0w"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSelector.gd" id="3_2v3m1"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSequence.gd" id="4_fjw5l"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTSuccess.gd" id="4_qnbqx"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTConditionCallable.gd" id="5_8tfvp"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTLimiter.gd" id="5_d3jao"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionCallable.gd" id="6_i6lan"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionWait.gd" id="10_1e6f0"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTInverter.gd" id="11_fvy66"]
[node name="Player" type="Node2D"]
script = ExtResource("1_1ti0g")
[node name="Shape" type="Node2D" parent="."]
[node name="Ahahahah" type="Polygon2D" parent="Shape"]
color = Color(0.188235, 0.490196, 0.505882, 1)
polygon = PackedVector2Array(-27, -55, 22, -55, 22, -25, 10, -18, 24, 17, -30, 17, -30, 17, -30, 17, -13, -18, -13, -18, -13, -18, -27, -26, -27, -26, -27, -26)
[node name="GUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 0
offset_left = -61.0
offset_top = -84.0
offset_right = 61.0
offset_bottom = -58.0
[node name="Text" type="Label" parent="GUI"]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "My turn !"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Name" type="Label" parent="GUI"]
layout_mode = 0
offset_left = 24.0
offset_top = 104.0
offset_right = 98.0
offset_bottom = 127.0
horizontal_alignment = 1
vertical_alignment = 1
[node name="BTRoot" type="Node" parent="."]
script = ExtResource("2_sdd0w")
actor_path = NodePath("..")
[node name="Do" type="Node" parent="BTRoot"]
script = ExtResource("4_fjw5l")
[node name="Init" type="Node" parent="BTRoot/Do"]
script = ExtResource("4_fjw5l")
save_progression = true
[node name="Declare I am playing" type="Node" parent="BTRoot/Do/Init"]
script = ExtResource("4_qnbqx")
[node name="Do once" type="Node" parent="BTRoot/Do/Init/Declare I am playing"]
script = ExtResource("5_d3jao")
[node name="I\'m here !" type="Node" parent="BTRoot/Do/Init/Declare I am playing/Do once"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../../..")
method_name = "declare_presence"
method_arguments = Array[String](["blackboard"])
[node name="Invert" type="Node" parent="BTRoot/Do/Init"]
script = ExtResource("11_fvy66")
[node name="Do once" type="Node" parent="BTRoot/Do/Init/Invert"]
script = ExtResource("5_d3jao")
[node name="Wait 1s" type="Node" parent="BTRoot/Do/Init/Invert/Do once"]
script = ExtResource("10_1e6f0")
[node name="One Between" type="Node" parent="BTRoot/Do"]
script = ExtResource("3_2v3m1")
save_progression = true
[node name="I must talk" type="Node" parent="BTRoot/Do/One Between"]
script = ExtResource("4_fjw5l")
save_progression = true
[node name="Is my Turn ?" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("5_8tfvp")
method_owner_path = NodePath("../../../../..")
method_name = "is_my_turn_to_talk"
method_arguments = Array[String](["blackboard.get_data(\"next_talking\")"])
[node name="Talk" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../..")
method_name = "talk"
[node name="Wait a little bit" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("10_1e6f0")
random_deviation_ms = 300
[node name="Set Next Player To Talk" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../..")
method_name = "choose_next_player_talking"
method_arguments = Array[String](["blackboard"])
[node name="I must listen" type="Node" parent="BTRoot/Do/One Between"]
script = ExtResource("4_fjw5l")
[node name="Not my turn" type="Node" parent="BTRoot/Do/One Between/I must listen"]
script = ExtResource("11_fvy66")
[node name="Is my Turn ?" type="Node" parent="BTRoot/Do/One Between/I must listen/Not my turn"]
script = ExtResource("5_8tfvp")
method_owner_path = NodePath("../../../../../..")
method_name = "is_my_turn_to_talk"
method_arguments = Array[String](["blackboard.get_data(\"next_talking\")"])

View file

@ -1,12 +0,0 @@
# 🪵 Simple AI logic : the lumberjack !
This example is about a lumberjack that needs to cut logs. He can carry a certain quantity of logs before going back to the nearest warehouse to drop logs. When logs are dropped, he moves back to the tree he was cutting (or, the nearest tree if the tree is cut), and cut logs again.
The aim of this example is to show how to implement a simple AI logic, composed of differents phases, using a behavior tree. This is just a proposal, there are several ways to create our lumberjack !
In lumberjack behavior tree, you can notice there is no custom tree node (action or condition) : only based ones are used. To execute functional actions, like dropping logs, the `BTActionCallable` is used. It allows to call a method in a node. For simple behavior trees, it allows to contain all logic into the same script.
## Technical elements
- `main.tscn` : scene to run,
- `lumberjack.tscn` : the lumberjack. The behavior tree is in this scene.

View file

@ -1,49 +0,0 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var max_log_count:int = 3
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var remaining_logs:int = max_log_count
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _draw():
var poly = $ShapeFull/Leaves.polygon
for i in range(1 , poly.size()):
draw_line(poly[i-1] , poly[i], Color.BLACK , 1)
draw_line(poly[poly.size() - 1] , poly[0], Color.BLACK , 1)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func has_logs() -> bool:
return remaining_logs > 0
func cut_log() -> void:
if remaining_logs > 0:
remaining_logs -= 1
if remaining_logs == 0:
queue_free()
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,27 +0,0 @@
[gd_scene load_steps=5 format=3]
[ext_resource type="Script" path="res://examples/simple_ai_logic/env/tree.gd" id="1_r2ta2"]
[sub_resource type="Gradient" id="Gradient_aa3nm"]
colors = PackedColorArray(0.408848, 0.73338, 3.85046e-07, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_2o5uu"]
frequency = 0.025
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_0hflj"]
color_ramp = SubResource("Gradient_aa3nm")
noise = SubResource("FastNoiseLite_2o5uu")
[node name="Tree" type="Node2D" groups=["tree"]]
script = ExtResource("1_r2ta2")
[node name="ShapeFull" type="Node2D" parent="."]
[node name="Base" type="Polygon2D" parent="ShapeFull"]
color = Color(0.270588, 0.141176, 0, 1)
polygon = PackedVector2Array(-15, 7, -15, 7, 11, 7, 11, 7, 11, 7, 1, -6, 1, -6, 1, -6, 6, -38, -4, -38, -4, -38, -4, -38)
[node name="Leaves" type="Polygon2D" parent="ShapeFull"]
color = Color(0.121569, 0.301961, 0.0470588, 1)
texture = SubResource("NoiseTexture2D_0hflj")
polygon = PackedVector2Array(-3, -22, -3, -22, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -47, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -21, -76, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21)

View file

@ -1,9 +0,0 @@
[gd_scene format=3 uid="uid://i4372roabk7a"]
[node name="Warehouse" type="Node2D" groups=["warehouse"]]
[node name="Shape" type="Polygon2D" parent="."]
position = Vector2(0, 7)
scale = Vector2(0.28841, 0.28841)
color = Color(0.270588, 0.145098, 0.0117647, 1)
polygon = PackedVector2Array(-110.953, 0, 232.308, 0, 232.308, -225.374, 138.691, -298.187, -180.299, -218.439, -110.953, -218.439)

View file

@ -1,102 +0,0 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export_category("Logger")
@export var max_log_capacity:int = 2
#------------------------------------------
# Variables publiques
#------------------------------------------
var logs_count:int = 0
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var _btroot:BTRoot = $AI
var _cutting_log:bool = false
var _cutting_tree:Node2D
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func on_state_entered() :
_btroot.on_running.connect(func(s):print(s))
_btroot.on_idle.connect(func():print("idle..."))
_btroot.enabled = true
func can_carry_more_logs() -> bool:
return logs_count < max_log_capacity
func has_no_log() -> bool:
return logs_count == 0
func has_remaining_trees() -> bool:
return not get_tree().get_nodes_in_group("tree").is_empty()
func get_nearest_tree() -> Node2D:
var nearest_tree:Node2D
var nearest_distance_to_tree:float = 99999.0
for tree in get_tree().get_nodes_in_group("tree"):
var distance_to_tree:float = global_position.distance_to(tree.global_position)
if distance_to_tree < nearest_distance_to_tree:
nearest_distance_to_tree = distance_to_tree
nearest_tree = tree
return nearest_tree
func get_nearest_warehouse() -> Node2D:
var nearest_warehouse:Node2D
var nearest_distance_to_warehouse:float = 99999.0
for warehouse in get_tree().get_nodes_in_group("warehouse"):
var distance_to_warehouse:float = global_position.distance_to(warehouse.global_position)
if distance_to_warehouse < nearest_distance_to_warehouse:
nearest_distance_to_warehouse = distance_to_warehouse
nearest_warehouse = warehouse
return nearest_warehouse
func tree_is_valid(tree:Node2D) -> bool:
return is_instance_valid(tree) and tree.has_logs()
func cut_log(tree:Node2D) -> int:
if not _cutting_log:
_cutting_log = true
_cutting_tree = tree
get_tree().create_timer(1).timeout.connect(_on_log_cut, CONNECT_ONE_SHOT)
return BTTickResult.RUNNING if _cutting_log else BTTickResult.FAILURE
func drop_logs_to_warehouse() -> void:
logs_count = 0
func move_to(delta:float, node:Node2D) -> int:
if global_position.distance_to(node.global_position) > 10:
global_position = global_position.move_toward(node.global_position, delta * 300)
return BTTickResult.RUNNING
else:
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _on_log_cut() -> void:
if is_instance_valid(_cutting_tree):
_cutting_tree.cut_log()
_cutting_tree = null
logs_count += 1
_cutting_log = false

View file

@ -1,167 +0,0 @@
[gd_scene load_steps=11 format=3 uid="uid://bl8kvanpmae2g"]
[ext_resource type="Script" path="res://examples/simple_ai_logic/lumberjack.gd" id="1_4c8nf"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/BTRoot.gd" id="2_hoy6d"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSelector.gd" id="3_5vl0m"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSequence.gd" id="4_c83di"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTInverter.gd" id="5_iaq0m"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTConditionCallable.gd" id="6_wov0v"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionBlackboardSet.gd" id="7_f8o6y"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionCallable.gd" id="8_mjt8i"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTFailure.gd" id="9_ojjv5"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionBlackboardDelete.gd" id="10_7bq5a"]
[node name="LumberJack" type="Node2D"]
script = ExtResource("1_4c8nf")
[node name="Shape" type="Node2D" parent="."]
[node name="Polygon2D" type="Polygon2D" parent="Shape"]
color = Color(0.54902, 0.0862745, 0.117647, 1)
polygon = PackedVector2Array(-2, -5, -2, -2, -1, -2, -1, 0, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, 4, 5, 1, 0, 1, -2, 2, -2, 2, -5)
[node name="AI" type="Node" parent="."]
script = ExtResource("2_hoy6d")
actor_path = NodePath("..")
[node name="One Between" type="Node" parent="AI"]
script = ExtResource("3_5vl0m")
[node name="Idle To Warehouse" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="No Remaining Tree" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("5_iaq0m")
[node name="At Least One Tree" type="Node" parent="AI/One Between/Idle To Warehouse/No Remaining Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "has_remaining_trees"
[node name="Has No Log" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../..")
method_name = "has_no_log"
[node name="Move To Nearest Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("4_c83di")
[node name="Get Nearest Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_warehouse"
expression = "actor.get_nearest_warehouse()"
can_overwrite_value = true
[node name="Move To Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_warehouse\")"])
[node name="Put Logs To Warehouse" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="One Between" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("3_5vl0m")
[node name="Can NOT Carry More Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between"]
script = ExtResource("5_iaq0m")
[node name="Can Cary More Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between/Can NOT Carry More Logs"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "can_carry_more_logs"
[node name="No Remaining Tree" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between"]
script = ExtResource("5_iaq0m")
[node name="At Least One Tree" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between/No Remaining Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "has_remaining_trees"
[node name="Move To Nearest Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("4_c83di")
[node name="Get Nearest Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_warehouse"
expression = "actor.get_nearest_warehouse()"
can_overwrite_value = true
[node name="Move To Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_warehouse\")"])
[node name="Drop Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../..")
method_name = "drop_logs_to_warehouse"
[node name="Get Log" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="Can Carry More Logs" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../..")
method_name = "can_carry_more_logs"
[node name="Move To Nearest Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="Has Remaning Trees" type="Node" parent="AI/One Between/Get Log/Move To Nearest Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "has_remaining_trees"
[node name="Get Nearest Tree" type="Node" parent="AI/One Between/Get Log/Move To Nearest Tree"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_tree"
expression = "actor.get_nearest_tree()"
[node name="Stop If Nearest Tree If Invalid" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="OR" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid"]
script = ExtResource("3_5vl0m")
[node name="Tree Is Valid" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "tree_is_valid"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])
[node name="Stop Because Tree Invalid" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR"]
script = ExtResource("9_ojjv5")
[node name="Delete Nearest Tree Ref" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR/Stop Because Tree Invalid"]
script = ExtResource("10_7bq5a")
blackboard_key = "nearest_tree"
[node name="Move To Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_tree\")"])
[node name="Cut Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="Nearest Tree Is Valid" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "tree_is_valid"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])
[node name="Can Carry More Logs" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "can_carry_more_logs"
[node name="Cut Log From Tree" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "cut_log"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])

View file

@ -1,36 +0,0 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _process(_delta:float) -> void:
if Input.is_action_just_released("ui_accept"):
var new_tree:Node2D = preload("res://examples/simple_ai_logic/env/tree.tscn").instantiate()
new_tree.global_position = get_global_mouse_position()
$Trees.add_child(new_tree)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -1,104 +0,0 @@
[gd_scene load_steps=8 format=3 uid="uid://ccttcdvcigdoe"]
[ext_resource type="Script" path="res://examples/simple_ai_logic/main.gd" id="1_23dkn"]
[ext_resource type="PackedScene" uid="uid://i4372roabk7a" path="res://examples/simple_ai_logic/env/warehouse.tscn" id="2_hh1py"]
[ext_resource type="PackedScene" path="res://examples/simple_ai_logic/env/tree.tscn" id="3_qyub5"]
[ext_resource type="PackedScene" uid="uid://bl8kvanpmae2g" path="res://examples/simple_ai_logic/lumberjack.tscn" id="4_782kh"]
[sub_resource type="Gradient" id="Gradient_rssdc"]
colors = PackedColorArray(0.787759, 0.787759, 0.787759, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ql20u"]
noise_type = 2
frequency = 0.005
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_181qe"]
width = 2050
height = 2050
color_ramp = SubResource("Gradient_rssdc")
noise = SubResource("FastNoiseLite_ql20u")
[node name="World" type="Node2D"]
script = ExtResource("1_23dkn")
[node name="Background" type="Polygon2D" parent="."]
color = Color(0.466667, 0.670588, 0, 1)
texture = SubResource("NoiseTexture2D_181qe")
polygon = PackedVector2Array(-7, -7, -7, -7, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7)
[node name="Warehouses" type="Node2D" parent="."]
[node name="Warehouse1" parent="Warehouses" instance=ExtResource("2_hh1py")]
position = Vector2(805, 229)
[node name="Warehouse2" parent="Warehouses" instance=ExtResource("2_hh1py")]
position = Vector2(268, 556)
[node name="Trees" type="Node2D" parent="."]
y_sort_enabled = true
[node name="Tree" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(132, 126)
[node name="Tree2" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(46, 69)
[node name="Tree3" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(186, 110)
[node name="Tree4" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(78, 126)
[node name="Tree5" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(140, 185)
[node name="Tree6" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(83, 215)
[node name="Tree7" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(581, 604)
[node name="Tree8" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(465, 473)
[node name="Tree9" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(503, 523)
[node name="Tree10" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(541, 495)
[node name="Tree11" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1044, 124)
[node name="Tree12" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1074, 235)
[node name="Tree13" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(976, 178)
[node name="Tree14" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1035, 188)
[node name="Tree15" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1091, 155)
[node name="Tree16" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(998, 101)
[node name="GUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="ControlDesc" type="Label" parent="GUI"]
layout_mode = 0
offset_left = 23.0
offset_top = 605.0
offset_right = 371.0
offset_bottom = 631.0
text = "SPACE : plant a tree at mouse location"
[node name="LumberJack" parent="." instance=ExtResource("4_782kh")]
position = Vector2(685, 300)
scale = Vector2(3.5, 3.5)

View file

@ -13,19 +13,27 @@ config_version=5
config/name="City Limits"
config/description="Based on the original sprites, CityLimits is an open source reimagining of SimCity Classic based on Godot."
run/main_scene="res://scenes/game.tscn"
config/features=PackedStringArray("4.0", "Forward Plus")
config/features=PackedStringArray("4.2", "Forward Plus")
config/icon="res://icon.png"
config/macos_native_icon="res://icon.icns"
config/windows_native_icon="res://icon.ico"
[dotnet]
project/assembly_name="CityLimits"
[editor_plugins]
enabled=PackedStringArray("res://addons/simplelicense/plugin.cfg", "res://addons/fontawesome/plugin.cfg", "res://addons/SpritesheetGenerator/plugin.cfg", "res://addons/yet_another_behavior_tree/plugin.cfg")
enabled=PackedStringArray("res://addons/SpritesheetGenerator/plugin.cfg", "res://addons/fontawesome/plugin.cfg", "res://addons/simplelicense/plugin.cfg")
[input]
mb_left={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"pressed":false,"double_click":false,"script":null)
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}
[rendering]
renderer/rendering_method="mobile"