24 Commits

Author SHA1 Message Date
26f17fbd03 Show network Ping & start AI behaviour tree 2023-01-22 23:44:41 +01:00
ce7b74c832 Networking 2023-01-17 22:30:12 +01:00
9893bc45b4 fully sync player movements over network 2023-01-17 13:54:26 +01:00
1ef5d54d6c start Multiplayer 2023-01-15 23:59:12 +01:00
5cfc0839f7 add entity collision option 2023-01-03 23:43:30 +01:00
2e4c378991 small fix 2023-01-03 23:29:55 +01:00
40d73f2590 improve runtimeloader for glb files 2023-01-03 23:28:43 +01:00
a7118b3d77 update scoom data 2023-01-03 23:18:52 +01:00
b2b82271f7 fix weapon draw bug 2023-01-03 23:16:05 +01:00
b5286a5f54 extend PCK support 2023-01-03 01:00:11 +01:00
4c8499f4f0 add Scoom-Data submodule 2023-01-02 22:10:27 +01:00
5a891a5636 delete unwanted files 2023-01-02 22:07:30 +01:00
701bcfd39c PCK File loader 2023-01-02 17:55:28 +01:00
4de8162f48 Merge branch 'main' of ssh://git.peroxy.dev:222/kookroach/Scoom 2023-01-01 19:35:00 +01:00
face5c4527 Pre-Release 2023-01-01 19:34:37 +01:00
2c2641c1d3 Add 'README.md' 2022-12-31 12:01:35 +01:00
54a90ab22c add trenchbroom map 2022-12-31 03:49:35 +01:00
d808ef5a53 add runtime object loader (gltf only) 2022-12-31 03:49:01 +01:00
56255f5473 add modding support 2022-12-31 03:48:00 +01:00
d2ed1afdc7 Add modified weapon models 2022-12-07 08:41:10 +01:00
307eec1f4e Add Reload Animation 2022-12-06 15:10:38 +01:00
9eb5099b0e Update 'README.md' 2022-12-06 14:04:08 +01:00
140a97a15a Update README.md 2022-12-06 14:03:36 +01:00
6bc2b07ab6 Start Hitscan & add Crosshair shader 2022-12-06 14:02:22 +01:00
162 changed files with 4450 additions and 1977 deletions

BIN
.exr Normal file

Binary file not shown.

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bk3khvviorvmm"
path="res://.godot/imported/untitled.png-d7b497081dc8ae225dae2b6ac59973dc.ctex"
uid="uid://bpsjhyhlis3ov"
path="res://.godot/imported/.exr-a7725c7e971a9679cf60303f5fa7defa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Weapons/Bullet/untitled.png"
dest_files=["res://.godot/imported/untitled.png-d7b497081dc8ae225dae2b6ac59973dc.ctex"]
source_file="res://.exr"
dest_files=["res://.godot/imported/.exr-a7725c7e971a9679cf60303f5fa7defa.ctex"]
[params]

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "scoom"]
path = scoom
url = ssh://git@git.peroxy.dev:222/kookroach/Scoom-Data.git

BIN
Game.exr

Binary file not shown.

View File

@@ -1,28 +0,0 @@
[remap]
importer="2d_array_texture"
type="CompressedTexture2DArray"
uid="uid://djhovwrdokme0"
path.etc2="res://.godot/imported/Game.exr-72bd638e1628ca77f007b851e1ccfc0d.etc2.ctexarray"
path.s3tc="res://.godot/imported/Game.exr-72bd638e1628ca77f007b851e1ccfc0d.s3tc.ctexarray"
metadata={
"imported_formats": ["etc2", "s3tc"],
"vram_texture": true
}
[deps]
source_file="res://Game.exr"
dest_files=["res://.godot/imported/Game.exr-72bd638e1628ca77f007b851e1ccfc0d.etc2.ctexarray", "res://.godot/imported/Game.exr-72bd638e1628ca77f007b851e1ccfc0d.s3tc.ctexarray"]
[params]
compress/mode=2
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/channel_pack=1
mipmaps/generate=false
mipmaps/limit=-1
slices/horizontal=1
slices/vertical=1

29
Game.gd
View File

@@ -1,18 +1,30 @@
extends Node3D
class_name Game
signal game_loaded
@onready var label : Label = $CanvasLayer/Label
@onready var player : CharacterBody3D = $PlayerQ3
var init_config
var weapon_config
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
weapon_config = Runtimeloader.loadConfig("weapons.cfg") as ConfigFile
init_config = Runtimeloader.loadConfig("init.cfg") as ConfigFile
print("Loading PCK...")
for map_list in init_config.get_section_keys("MAPS"):
for map in init_config.get_value("MAPS", map_list):
Runtimeloader.loadPCK(map)
func _process(_delta):
label.text = "H Velocity: %3.2f" % [Vector2(player.velocity.x, player.velocity.z).length()]
label.text += "\nV Velocity: %3.2f" % [player.velocity.y]
label.text += "\nOn floor: %s" % player.is_on_floor()
for weapons_list in init_config.get_section_keys("WEAPONS"):
for weapon in init_config.get_value("WEAPONS", weapons_list):
Runtimeloader.loadPCK(weapon)
print("Loading Resources Done.")
func load_map():
Runtimeloader.loadScene("maps/test_map.tscn", self)
#Runtimeloader.get_all_entities(node)
game_loaded.emit()
func _input(event):
@@ -24,3 +36,4 @@ func _input(event):
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
elif event.keycode == KEY_ESCAPE:
get_tree().quit()

Binary file not shown.

View File

@@ -1,51 +0,0 @@
[gd_scene load_steps=8 format=3 uid="uid://cqutof7bvocqc"]
[ext_resource type="LightmapGIData" uid="uid://k5haifo34pp6" path="res://Game.lmbake" id="2_3k1jt"]
[ext_resource type="PackedScene" uid="uid://bl7jynld7s25o" path="res://scenes/player/PlayerQ3.tscn" id="2_dhifo"]
[ext_resource type="Script" path="res://Game.gd" id="3"]
[ext_resource type="PackedScene" uid="uid://bke5cip8sjpoq" path="res://scenes/map/entity_0_worldspawn.tscn" id="3_3r3q4"]
[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_mv01y"]
[sub_resource type="Sky" id="Sky_ybtis"]
sky_material = SubResource("PhysicalSkyMaterial_mv01y")
[sub_resource type="Environment" id="Environment_ul6y4"]
background_mode = 2
sky = SubResource("Sky_ybtis")
ambient_light_source = 3
reflected_light_source = 2
tonemap_mode = 2
tonemap_exposure = 2.0
[node name="Game" type="Node3D"]
script = ExtResource("3")
[node name="LightmapGI" type="LightmapGI" parent="."]
visible = false
quality = 2
bounces = 6
light_data = ExtResource("2_3k1jt")
[node name="LightmapProbe" type="LightmapProbe" parent="."]
visible = false
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_ul6y4")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.77938, 0.395123, -0.486256, 0.383799, 0.312364, 0.86898, 0.495243, -0.86389, 0.0918022, 0, 22.9909, 0)
light_indirect_energy = 1.5
light_bake_mode = 1
shadow_enabled = true
[node name="entity_0_worldspawn" parent="." instance=ExtResource("3_3r3q4")]
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="Label" type="Label" parent="CanvasLayer"]
offset_right = 40.0
offset_bottom = 14.0
[node name="PlayerQ3" parent="." instance=ExtResource("2_dhifo")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.6672, 11.2181)

View File

@@ -1,4 +1,6 @@
# SCOOM (name may be changed)
Developing a 3D game inspired by Doom64 on Godot 4 engine.
[Simple-Q3-Controller](https://github.com/fossegutten/Simple-Q3-Controller) by fossegutten
Using:
- [Simple-Q3-Controller](https://github.com/fossegutten/Simple-Q3-Controller) by fossegutten
- [CrosshairShader](https://github.com/0xspig/CrosshairShader) by 0xspig

View File

@@ -1,20 +0,0 @@
@tool
extends EditorPlugin
func _enter_tree() -> void:
add_custom_type(
"SfxrStreamPlayer", "AudioStreamPlayer", load("res://addons/godot_sfxr/SfxrStreamPlayer.gd"),
get_editor_interface().get_base_control().get_theme_icon("AudioStreamPlayer", "EditorIcons"))
add_custom_type(
"SfxrStreamPlayer2D", "AudioStreamPlayer2D", load("res://addons/godot_sfxr/SfxrStreamPlayer2D.gd"),
get_editor_interface().get_base_control().get_theme_icon("AudioStreamPlayer2D", "EditorIcons"))
add_custom_type(
"SfxrStreamPlayer3D", "AudioStreamPlayer3D", load("res://addons/godot_sfxr/SfxrStreamPlayer3D.gd"),
get_editor_interface().get_base_control().get_theme_icon("AudioStreamPlayer3D", "EditorIcons"))
func _exit_tree() -> void:
remove_custom_type("SfxrStreamPlayer")
remove_custom_type("SfxrStreamPlayer2D")
remove_custom_type("SfxrStreamPlayer3D")

View File

@@ -1,309 +0,0 @@
extends RefCounted
class_name SfxrGenerator
var params
var wave_shape: int
var repeat_time: float
var elapsed_since_repeat: float
var arpeggio_time: int
var arpeggio_multiplier: float
var period: float
var period_mult: float
var period_mult_slide: float
var period_max: float
var enable_frequency_cutoff: bool
var duty_cycle: float
var duty_cycle_slide: float
var fltw: float
var fltw_d: float
var fltdmp: float
var flthp: float
var flthp_d: float
var enable_low_pass_filter: bool
var vibrato_speed: float
var vibrato_amplitude: float
var envelope_length: Array
var envelope_punch: float
var flanger_offset: float
var flanger_offset_slide: float
var gain: float
var sample_rate: float
func init_params(stream_player) -> void:
params = stream_player
prepare_values()
# Wave shape
wave_shape = params.wave_type
# Filter
fltw = pow(params.p_lpf_freq, 3.0) * 0.1
enable_low_pass_filter = params.p_lpf_freq != 1.0
fltw_d = 1.0 + params.p_lpf_ramp * 0.0001
fltdmp = 5.0 / (1.0 + pow(params.p_lpf_resonance, 2.0) * 20.0) * (0.01 + fltw)
if (fltdmp > 0.8):
fltdmp = 0.8
flthp = pow(params.p_hpf_freq, 2.0) * 0.1
flthp_d = 1 + params.p_hpf_ramp * 0.0003
# Vibrato
vibrato_speed = pow(params.p_vib_speed, 2.0) * 0.01
vibrato_amplitude = params.p_vib_strength * 0.5
# Envelope
envelope_length = [
floor(params.p_env_attack * params.p_env_attack * 100000.0),
floor(params.p_env_sustain * params.p_env_sustain * 100000.0),
floor(params.p_env_decay * params.p_env_decay * 100000.0),
]
envelope_punch = params.p_env_punch
# Flanger
flanger_offset = pow(params.p_pha_offset, 2.0) * 1020.0
if (params.p_pha_offset < 0.0):
flanger_offset = -flanger_offset
flanger_offset_slide = pow(params.p_pha_ramp, 2.0) * 1.0
if (params.p_pha_ramp < 0.0):
flanger_offset_slide = -flanger_offset_slide
# Repeat
repeat_time = floor(pow(1 - params.p_repeat_speed, 2.0) * 20000.0 + 32.0)
if (params.p_repeat_speed == 0.0):
repeat_time = 0.0
gain = exp(params.sound_vol) - 1.0
sample_rate = params.sample_rate
func prepare_values() -> void:
elapsed_since_repeat = 0.0
period = 100.0 / (params.p_base_freq * params.p_base_freq + 0.001)
period_max = 100.0 / (params.p_freq_limit * params.p_freq_limit + 0.001)
enable_frequency_cutoff = params.p_freq_limit > 0.0
period_mult = 1.0 - pow(params.p_freq_ramp, 3.0) * 0.01
period_mult_slide = -pow(params.p_freq_dramp, 3.0) * 0.000001
duty_cycle = 0.5 - params.p_duty * 0.5
duty_cycle_slide = -params.p_duty_ramp * 0.00005
if (params.p_arp_mod >= 0.0):
arpeggio_multiplier = 1.0 - pow(params.p_arp_mod, 2.0) * 0.9
else:
arpeggio_multiplier = 1.0 + pow(params.p_arp_mod, 2.0) * 10.0
arpeggio_time = floor(pow(1.0 - params.p_arp_speed, 2.0) * 20000.0 + 32.0)
if (params.p_arp_speed == 1.0):
arpeggio_time = 0
func get_raw_buffer() -> Array:
randomize()
var fltp: float = 0.0
var fltdp: float = 0.0
var fltphp: float = 0.0
var noise_buffer_length: int = 32
var noise_buffer: Array = []
for i in noise_buffer_length:
noise_buffer.append(randf() * 2.0 - 1.0)
var envelope_stage: int = 0
var envelope_elapsed: float = 0.0
var vibrato_phase: float = 0.0
var phase: int = 0
var ipp: int = 0
var flanger_buffer_length: int = 1024
var flanger_buffer: Array = []
for i in flanger_buffer_length:
flanger_buffer.append(0.0)
var _buffer: Array = []
var sample_sum: float = 0.0
var num_summed: float = 0.0
var summands: int = floor(44100.0 / sample_rate)
var t: float = -1.0
while t < INF:
t += 1
# Repeats
elapsed_since_repeat += 1.0
if (repeat_time != 0.0 and elapsed_since_repeat >= repeat_time):
prepare_values()
# Arpeggio (single)
if (arpeggio_time != 0 and t >= arpeggio_time):
arpeggio_time = 0
period *= arpeggio_multiplier
# Frequency slide, and frequency slide slide!
period_mult += period_mult_slide
period *= period_mult
if (period > period_max):
period = period_max
if (enable_frequency_cutoff):
break
# Vibrato
var rfperiod: float = period
if (vibrato_amplitude > 0.0):
vibrato_phase += vibrato_speed
rfperiod = period * (1.0 + sin(vibrato_phase) * vibrato_amplitude)
var iperiod: int = floor(rfperiod)
if (iperiod < SfxrGlobals.OVERSAMPLING):
iperiod = SfxrGlobals.OVERSAMPLING
# Square wave duty cycle
duty_cycle = duty_cycle + duty_cycle_slide
if (duty_cycle > 0.5):
duty_cycle = 0.5
elif (duty_cycle < 0.0):
duty_cycle = 0.0
# Volume envelope
envelope_elapsed += 1.0
if (envelope_elapsed > envelope_length[envelope_stage]):
envelope_elapsed = 0.0
envelope_stage += 1.0
if (envelope_stage > 2.0):
break
if (envelope_length[envelope_stage] == 0):
continue
var env_vol: float = 0.0
var envf: float = envelope_elapsed / envelope_length[envelope_stage]
if (envelope_stage == 0.0): # Attack
env_vol = envf
elif (envelope_stage == 1.0): # Sustain
env_vol = 1.0 + (1.0 - envf) * 2.0 * envelope_punch
else: # Decay
env_vol = 1.0 - envf
# Flanger step
flanger_offset += flanger_offset_slide
var iphase: int = abs(floor(flanger_offset))
if (iphase > 1023):
iphase = 1023
if (flthp_d != 0.0):
flthp = flthp * flthp_d
if (flthp > 0.1):
flthp = 0.1
elif (flthp < 0.00001):
flthp = 0.00001
# 8x Oversampling
var sample: float = 0.0
for i in SfxrGlobals.OVERSAMPLING:
var sub_sample: float = 0.0
phase += 1
if (phase >= iperiod):
phase %= iperiod
if (wave_shape == SfxrGlobals.WAVE_SHAPES.NOISE):
for j in noise_buffer_length:
noise_buffer[i] = randf() * 2.0 - 1.0
# Base waveform
var fp: float = float(phase) / float(iperiod)
if (wave_shape == SfxrGlobals.WAVE_SHAPES.SQUARE):
if (fp < duty_cycle):
sub_sample = 0.5
else:
sub_sample = -0.5
elif (wave_shape == SfxrGlobals.WAVE_SHAPES.SAWTOOTH):
if (fp < duty_cycle):
sub_sample = -1.0 + 2.0 * fp / duty_cycle
else:
sub_sample = 1.0 - 2.0 * (fp - duty_cycle) / (1 - duty_cycle)
elif (wave_shape == SfxrGlobals.WAVE_SHAPES.SINE):
sub_sample = sin(fp * 2.0 * PI)
elif (wave_shape == SfxrGlobals.WAVE_SHAPES.NOISE):
sub_sample = noise_buffer[int(floor(phase * 32.0 / iperiod))]
else:
printerr("ERROR: Bad wave type: " + str(wave_shape))
sub_sample = 0
# Low-pass filter
var pp: float = fltp
fltw *= fltw_d
if (fltw > 0.1):
fltw = 0.1
elif (fltw < 0.0):
fltw = 0.0
if (enable_low_pass_filter):
fltdp += (sub_sample - fltp) * fltw
fltdp -= fltdp * fltdmp
else:
fltp = sub_sample
fltdp = 0.0
fltp += fltdp
# High-pass filter
fltphp += fltp - pp
fltphp -= fltphp * flthp
sub_sample = fltphp
# Flanger
flanger_buffer[ipp & 1023] = sub_sample
sub_sample += flanger_buffer[(ipp - iphase + 1024) & 1023]
ipp = (ipp + 1) & 1023
# Final accumulation and envelope application
sample += sub_sample * env_vol
# Accumulate samples appropriately for sample rate
sample_sum += sample
num_summed += 1.0
if (num_summed >= summands):
num_summed = 0.0
sample = sample_sum / summands
sample_sum = 0.0
else:
continue
sample = sample / SfxrGlobals.OVERSAMPLING * SfxrGlobals.MASTER_VOLUME
sample *= gain
sample = floor((sample + 1) * 128)
if (sample > 255):
sample = 255;
elif (sample < 0):
sample = 0
sample += 128
if sample > 255:
sample -= 255
_buffer.append(sample)
return _buffer
func build_sample(stream_player):
init_params(stream_player)
var sample: AudioStreamWAV = stream_player.stream
if (not sample):
stream_player.stream = AudioStreamWAV.new()
sample = stream_player.stream
sample.mix_rate = sample_rate
sample.data = PackedByteArray(get_raw_buffer())
return sample

View File

@@ -1,30 +0,0 @@
extends Object
class_name SfxrGlobals
enum WAVE_SHAPES {
SQUARE,
SAWTOOTH,
SINE,
NOISE,
}
enum PRESETS {
NONE,
PICKUP,
LASER,
EXPLOSION,
POWERUP,
HIT,
JUMP,
CLICK,
BLIP,
SYNTH,
RANDOM,
TONE,
MUTATE,
}
const OVERSAMPLING = 8
const MASTER_VOLUME = 1

View File

@@ -1,119 +0,0 @@
@tool
extends AudioStreamPlayer
# Wave Shape
var wave_type: int
# Envelope
var p_env_attack: float
var p_env_sustain: float
var p_env_punch: float
var p_env_decay: float
# Tone
var p_base_freq: float
var p_freq_limit: float
var p_freq_ramp: float
var p_freq_dramp: float
# Vibrato
var p_vib_strength: float
var p_vib_speed: float
# Tonal Change
var p_arp_mod: float
var p_arp_speed: float
# Square wve duty (proportion of time signal is high vs low)
var p_duty: float
var p_duty_ramp: float
# Repeat
var p_repeat_speed: float
# Flanger
var p_pha_offset: float
var p_pha_ramp: float
# Low-pass filter
var p_lpf_freq: float
var p_lpf_ramp: float
var p_lpf_resonance: float
# High-pass filter
var p_hpf_freq: float
var p_hpf_ramp: float
# Sample parameters
var sound_vol: float
var sample_rate: float
# Sfx Generation
var sfx_timer: SceneTreeTimer
##################################
# Inspector Properties
##################################
func _get_property_list() -> Array:
return SfxrStreamPlayerInterface.object_get_property_list()
func _get(property):
return SfxrStreamPlayerInterface.object_get(self, property)
func _set(property, value) -> bool:
return SfxrStreamPlayerInterface.object_set(self, property, value)
##################################
# Defaults
##################################
func _init():
SfxrStreamPlayerInterface.object_set_defaults(self)
func property_can_revert(property: String):
return SfxrStreamPlayerInterface.object_property_can_revert(property)
func property_get_revert(property: String):
return SfxrStreamPlayerInterface.object_property_get_revert(property)
##################################
# Presets
##################################
func random_preset() -> bool:
return SfxrStreamPlayerInterface.random_preset(self)
func preset_values(preset_key: int) -> bool:
return SfxrStreamPlayerInterface.preset_values(self, preset_key)
##################################
# Playback
##################################
func _on_sfx_timer_timeout(timer: SceneTreeTimer, play_after_build: bool):
SfxrStreamPlayerInterface._on_sfx_timer_timeout(self, timer, play_after_build)
func build_sfx(play_after_build: bool = false):
SfxrStreamPlayerInterface.build_sfx(self, play_after_build)
func play(from_position: float = 0.0):
if playing:
stop()
super.play(from_position)

View File

@@ -1,119 +0,0 @@
@tool
extends AudioStreamPlayer2D
# Wave Shape
var wave_type: int
# Envelope
var p_env_attack: float
var p_env_sustain: float
var p_env_punch: float
var p_env_decay: float
# Tone
var p_base_freq: float
var p_freq_limit: float
var p_freq_ramp: float
var p_freq_dramp: float
# Vibrato
var p_vib_strength: float
var p_vib_speed: float
# Tonal Change
var p_arp_mod: float
var p_arp_speed: float
# Square wve duty (proportion of time signal is high vs low)
var p_duty: float
var p_duty_ramp: float
# Repeat
var p_repeat_speed: float
# Flanger
var p_pha_offset: float
var p_pha_ramp: float
# Low-pass filter
var p_lpf_freq: float
var p_lpf_ramp: float
var p_lpf_resonance: float
# High-pass filter
var p_hpf_freq: float
var p_hpf_ramp: float
# Sample parameters
var sound_vol: float
var sample_rate: float
# Sfx Generation
var sfx_timer: SceneTreeTimer
##################################
# Inspector Properties
##################################
func _get_property_list() -> Array:
return SfxrStreamPlayerInterface.object_get_property_list()
func _get(property):
return SfxrStreamPlayerInterface.object_get(self, property)
func _set(property, value) -> bool:
return SfxrStreamPlayerInterface.object_set(self, property, value)
##################################
# Defaults
##################################
func _init():
SfxrStreamPlayerInterface.object_set_defaults(self)
func property_can_revert(property: String):
return SfxrStreamPlayerInterface.object_property_can_revert(property)
func property_get_revert(property: String):
return SfxrStreamPlayerInterface.object_property_get_revert(property)
##################################
# Presets
##################################
func random_preset() -> bool:
return SfxrStreamPlayerInterface.random_preset(self)
func preset_values(preset_key: int) -> bool:
return SfxrStreamPlayerInterface.preset_values(self, preset_key)
##################################
# Playback
##################################
func _on_sfx_timer_timeout(timer: SceneTreeTimer, play_after_build: bool):
SfxrStreamPlayerInterface._on_sfx_timer_timeout(self, timer, play_after_build)
func build_sfx(play_after_build: bool = false):
SfxrStreamPlayerInterface.build_sfx(self, play_after_build)
func play(from_position: float = 0.0):
if playing:
stop()
super.play(from_position)

View File

@@ -1,119 +0,0 @@
@tool
extends AudioStreamPlayer3D
# Wave Shape
var wave_type: int
# Envelope
var p_env_attack: float
var p_env_sustain: float
var p_env_punch: float
var p_env_decay: float
# Tone
var p_base_freq: float
var p_freq_limit: float
var p_freq_ramp: float
var p_freq_dramp: float
# Vibrato
var p_vib_strength: float
var p_vib_speed: float
# Tonal Change
var p_arp_mod: float
var p_arp_speed: float
# Square wve duty (proportion of time signal is high vs low)
var p_duty: float
var p_duty_ramp: float
# Repeat
var p_repeat_speed: float
# Flanger
var p_pha_offset: float
var p_pha_ramp: float
# Low-pass filter
var p_lpf_freq: float
var p_lpf_ramp: float
var p_lpf_resonance: float
# High-pass filter
var p_hpf_freq: float
var p_hpf_ramp: float
# Sample parameters
var sound_vol: float
var sample_rate: float
# Sfx Generation
var sfx_timer: SceneTreeTimer
##################################
# Inspector Properties
##################################
func _get_property_list() -> Array:
return SfxrStreamPlayerInterface.object_get_property_list()
func _get(property):
return SfxrStreamPlayerInterface.object_get(self, property)
func _set(property, value):
return SfxrStreamPlayerInterface.object_set(self, property, value)
##################################
# Defaults
##################################
func _init():
SfxrStreamPlayerInterface.object_set_defaults(self)
func property_can_revert(property: String):
return SfxrStreamPlayerInterface.object_property_can_revert(property)
func property_get_revert(property: String):
return SfxrStreamPlayerInterface.object_property_get_revert(property)
##################################
# Presets
##################################
func random_preset() -> bool:
return SfxrStreamPlayerInterface.random_preset(self)
func preset_values(preset_key: int) -> bool:
return SfxrStreamPlayerInterface.preset_values(self, preset_key)
##################################
# Playback
##################################
func _on_sfx_timer_timeout(timer: SceneTreeTimer, play_after_build: bool):
SfxrStreamPlayerInterface._on_sfx_timer_timeout(self, timer, play_after_build)
func build_sfx(play_after_build: bool = false):
SfxrStreamPlayerInterface.build_sfx(self, play_after_build)
func play(from_position: float = 0.0):
if playing:
stop()
super.play(from_position)

View File

@@ -1,477 +0,0 @@
extends Object
class_name SfxrStreamPlayerInterface
##################################
# Inspector Properties
##################################
const PROPERTY_MAP = {
# Sample params
"sample_params/sound_vol": {"name": "sound_vol", "hint_string": "0,1,0.000000001", "default": 0.25},
"sample_params/sample_rate": {"name": "sample_rate", "hint_string": "6000,44100,1", "default": 44100.0},
# Envelope
"envelope/attack_time": {"name": "p_env_attack", "hint_string": "0,1,0.000000001", "default": 0.0},
"envelope/sustain_time": {"name": "p_env_sustain", "hint_string": "0,1,0.000000001", "default": 0.6641},
"envelope/punch_time": {"name": "p_env_punch", "hint_string": "0,1,0.000000001", "default": 0.0},
"envelope/decay_time": {"name": "p_env_decay", "hint_string": "0,1,0.000000001", "default": 0.0},
# Frequency
"frequency/start_frequency": {"name": "p_base_freq", "hint_string": "0,1,0.000000001", "default": 0.35173364},
"frequency/min_freq_cutoff": {"name": "p_freq_limit", "hint_string": "0,1,0.000000001", "default": 0.0},
"frequency/slide": {"name": "p_freq_ramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
"frequency/delta_slide": {"name": "p_freq_dramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
# Vibrato
"vibrato/depth": {"name": "p_vib_strength", "hint_string": "0,1,0.000000001", "default": 0.0},
"vibrato/speed": {"name": "p_vib_speed", "hint_string": "0,1,0.000000001", "default": 0.0},
# Arpeggiation
"arpeggiation/frequency_mult": {"name": "p_arp_mod", "hint_string": "-1,1,0.000000001", "default": 0.0},
"arpeggiation/change_speed": {"name": "p_arp_speed", "hint_string": "0,1,0.000000001", "default": 0.0},
# Duty cycle
"duty_cycle/duty_cycle": {"name": "p_duty", "hint_string": "0,1,0.000000001", "default": 0.0},
"duty_cycle/sweep": {"name": "p_duty_ramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
# Retrigger
"retrigger/rate": {"name": "p_repeat_speed", "hint_string": "0,1,0.000000001", "default": 0.0},
# Flanger
"flanger/offset": {"name": "p_pha_offset", "hint_string": "-1,1,0.000000001", "default": 0.0},
"flanger/sweep": {"name": "p_pha_ramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
# Low-pass filter
"low_pass_filter/cutoff_frequency": {"name": "p_lpf_freq", "hint_string": "0,1,0.000000001", "default": 1.0},
"low_pass_filter/cutoff_sweep": {"name": "p_lpf_ramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
"low_pass_filter/resonance": {"name": "p_lpf_resonance", "hint_string": "0,1,0.000000001", "default": 0.0},
# High-pass filter
"high_pass_filter/cutoff_frequency": {"name": "p_hpf_freq", "hint_string": "0,1,0.000000001", "default": 0.0},
"high_pass_filter/cutoff_sweep": {"name": "p_hpf_ramp", "hint_string": "-1,1,0.000000001", "default": 0.0},
}
static func object_get_property_list() -> Array:
var presets = SfxrGlobals.PRESETS.keys()
presets.pop_front()
var props = []
props.append({
"name": "SfxrStreamPlayer",
"type": TYPE_NIL,
"usage": PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_SCRIPT_VARIABLE,
})
for preset in presets:
props.append({
"name": "generators/" + str(preset).to_lower(),
"type": TYPE_BOOL,
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE,
})
props.append({
"name": "wave/type",
"type": TYPE_INT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": ",".join(PackedStringArray(SfxrGlobals.WAVE_SHAPES.keys())),
})
for property in PROPERTY_MAP:
props.append({
"name": property,
"type": TYPE_FLOAT,
"hint": PROPERTY_HINT_RANGE,
"hint_string": PROPERTY_MAP[property]["hint_string"],
})
props.append_array([
{
"name": "actions/force_rebuild",
"type": TYPE_BOOL,
"usage": PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NO_INSTANCE_STATE,
},
])
return props
static func object_get(object: Node, property: String):
if property in PROPERTY_MAP:
return object[PROPERTY_MAP[property]["name"]]
elif property == "wave/type":
return object.wave_type
static func object_set(object: Node, property: String, value) -> bool:
var auto_build = Engine.is_editor_hint() and object.is_inside_tree()
if property in PROPERTY_MAP:
object[PROPERTY_MAP[property]["name"]] = value
if auto_build:
_schedule_build_sfx(object, true)
return true
elif property == "wave/type":
object.wave_type = value
if auto_build:
_schedule_build_sfx(object, true)
return true
elif property == "actions/force_rebuild":
if value and auto_build:
build_sfx(object, true)
return true
elif property == "sfxr_generator":
if not value:
value = 0
if preset_values(object, value) and auto_build:
build_sfx(object, true)
return true
elif property.begins_with("generators/"):
property = property.replace("generators/", "").to_upper()
if preset_values(object, SfxrGlobals.PRESETS.get(property, -1)) and auto_build:
build_sfx(object, true)
return true
return false
##################################
# Defaults
##################################
static func object_set_defaults(object: Node):
object.wave_type = SfxrGlobals.WAVE_SHAPES.SAWTOOTH
for property in PROPERTY_MAP:
object[PROPERTY_MAP[property]["name"]] = PROPERTY_MAP[property]["default"]
static func object_property_can_revert(property: String):
return property in PROPERTY_MAP
static func object_property_get_revert(property: String):
return PROPERTY_MAP[property]["default"]
##################################
# Helpers
##################################
static func frnd(rrange) -> float:
return randf() * rrange
static func rndr(from, to) -> float:
return randf() * (to - from) + from
static func rnd(rmax) -> float:
return floor(randf() * (rmax + 1))
##################################
# Presets
##################################
static func _presets_pickup(object: Node):
object_set_defaults(object)
object.wave_type = SfxrGlobals.WAVE_SHAPES.SAWTOOTH
object.p_base_freq = 0.4 + frnd(0.5)
object.p_env_attack = 0
object.p_env_sustain = frnd(0.1)
object.p_env_decay = 0.1 + frnd(0.4)
object.p_env_punch = 0.3 + frnd(0.3)
if rnd(1):
object.p_arp_speed = 0.5 + frnd(0.2)
object.p_arp_mod = 0.2 + frnd(0.4)
static func _presets_laser(object: Node):
object_set_defaults(object)
object.wave_type = rnd(2)
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SINE and rnd(1):
object.wave_type = rnd(1)
if rnd(2) == 0:
object.p_base_freq = 0.3 + frnd(0.6)
object.p_freq_limit = frnd(0.1)
object.p_freq_ramp = -0.35 - frnd(0.3)
else:
object.p_base_freq = 0.5 + frnd(0.5)
object.p_freq_limit = object.p_base_freq - 0.2 - frnd(0.6)
if object.p_freq_limit < 0.2:
object.p_freq_limit = 0.2
object.p_freq_ramp = -0.15 - frnd(0.2)
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SAWTOOTH:
object.p_duty = 1
if rnd(1):
object.p_duty = frnd(0.5)
object.p_duty_ramp = frnd(0.2)
else:
object.p_duty = 0.4 + frnd(0.5)
object.p_duty_ramp = -frnd(0.7)
object.p_env_attack = 0
object.p_env_sustain = 0.1 + frnd(0.2)
object.p_env_decay = frnd(0.4)
if rnd(1):
object.p_env_punch = frnd(0.3)
if rnd(2) == 0:
object.p_pha_offset = frnd(0.2)
object.p_pha_ramp = -frnd(0.2)
object.p_hpf_freq = frnd(0.3)
static func _presets_explosion(object: Node):
object_set_defaults(object)
object.wave_type = SfxrGlobals.WAVE_SHAPES.NOISE
if rnd(1):
object.p_base_freq = pow(0.1 + frnd(0.4), 2)
object.p_freq_ramp = -0.1 + frnd(0.4)
else:
object.p_base_freq = pow(0.2 + frnd(0.7), 2)
object.p_freq_ramp = -0.2 - frnd(0.2)
if rnd(4) == 0:
object.p_freq_ramp = 0
if rnd(2) == 0:
object.p_repeat_speed = 0.3 + frnd(0.5)
object.p_env_attack = 0
object.p_env_sustain = 0.1 + frnd(0.3)
object.p_env_decay = frnd(0.5)
if rnd(1):
object.p_pha_offset = -0.3 + frnd(0.9)
object.p_pha_ramp = -frnd(0.3)
object.p_env_punch = 0.2 + frnd(0.6)
if rnd(1):
object.p_vib_strength = frnd(0.7)
object.p_vib_speed = frnd(0.6)
if rnd(2) == 0:
object.p_arp_speed = 0.6 + frnd(0.3)
object.p_arp_mod = 0.8 - frnd(1.6)
static func _presets_powerup(object: Node):
object_set_defaults(object)
if rnd(1):
object.wave_type = SfxrGlobals.WAVE_SHAPES.SAWTOOTH
object.p_duty = 1
else:
object.p_duty = frnd(0.6)
object.p_base_freq = 0.2 + frnd(0.3)
if rnd(1):
object.p_freq_ramp = 0.1 + frnd(0.4)
object.p_repeat_speed = 0.4 + frnd(0.4)
else:
object.p_freq_ramp = 0.05 + frnd(0.2)
if rnd(1):
object.p_vib_strength = frnd(0.7)
object.p_vib_speed = frnd(0.6)
object.p_env_attack = 0
object.p_env_sustain = frnd(0.4)
object.p_env_decay = 0.1 + frnd(0.4)
static func _presets_hit(object: Node):
object_set_defaults(object)
object.wave_type = rnd(2)
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SINE:
object.wave_type = SfxrGlobals.WAVE_SHAPES.NOISE
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SQUARE:
object.p_duty = frnd(0.6)
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SAWTOOTH:
object.p_duty = 1
object.p_base_freq = 0.2 + frnd(0.6)
object.p_freq_ramp = -0.3 - frnd(0.4)
object.p_env_attack = 0
object.p_env_sustain = frnd(0.1)
object.p_env_decay = 0.1 + frnd(0.2)
if rnd(1):
object.p_hpf_freq = frnd(0.3)
static func _presets_jump(object: Node):
object_set_defaults(object)
object.wave_type = SfxrGlobals.WAVE_SHAPES.SQUARE
object.p_duty = frnd(0.6)
object.p_base_freq = 0.3 + frnd(0.3)
object.p_freq_ramp = 0.1 + frnd(0.2)
object.p_env_attack = 0
object.p_env_sustain = 0.1 + frnd(0.3)
object.p_env_decay = 0.1 + frnd(0.2)
if rnd(1):
object.p_hpf_freq = frnd(0.3)
if rnd(1):
object.p_lpf_freq = 1 - frnd(0.6)
static func _presets_blip(object: Node):
object_set_defaults(object)
object.wave_type = rnd(1)
if object.wave_type == SfxrGlobals.WAVE_SHAPES.SQUARE:
object.p_duty = frnd(0.6)
else:
object.p_duty = 1
object.p_base_freq = 0.2 + frnd(0.4)
object.p_env_attack = 0
object.p_env_sustain = 0.1 + frnd(0.1)
object.p_env_decay = frnd(0.2)
object.p_hpf_freq = 0.1
static func _presets_synth(object: Node):
object_set_defaults(object)
object.wave_type = rnd(1)
object.p_base_freq = [0.2723171360931539, 0.19255692561524382, 0.13615778746815113][rnd(2)]
object.p_env_attack = frnd(0.5) if rnd(4) > 3 else 0
object.p_env_sustain = frnd(1)
object.p_env_punch = frnd(1)
object.p_env_decay = frnd(0.9) + 0.1
object.p_arp_mod = [0, 0, 0, 0, -0.3162, 0.7454, 0.7454][rnd(6)]
object.p_arp_speed = frnd(0.5) + 0.4
object.p_duty = frnd(1)
object.p_duty_ramp = frnd(1) if rnd(2) == 2 else 0
object.p_lpf_freq = [1, frnd(1) * frnd(1)][rnd(1)]
object.p_lpf_ramp = rndr(-1, 1)
object.p_lpf_resonance = frnd(1)
object.p_hpf_freq = frnd(1) if rnd(3) == 3 else 0
object.p_hpf_ramp = frnd(1) if rnd(3) == 3 else 0
static func _presets_tone(object: Node):
object_set_defaults(object)
static func _presets_click(object: Node):
if rnd(1):
_presets_hit(object)
else:
_presets_explosion(object)
if rnd(1):
object.p_freq_ramp = -0.5 + frnd(1.0)
if rnd(1):
object.p_env_sustain = (frnd(0.4) + 0.2) * object.p_env_sustain
object.p_env_decay = (frnd(0.4) + 0.2) * object.p_env_decay
if rnd(3) == 0:
object.p_env_attack = frnd(0.3)
object.p_base_freq = 1 - frnd(0.25)
object.p_hpf_freq = 1 - frnd(0.1)
static func _presets_random(object: Node):
object_set_defaults(object)
object.wave_type = rnd(3)
if rnd(1):
object.p_base_freq = pow(frnd(2) - 1, 3) + 0.5
else:
object.p_base_freq = pow(frnd(1), 2)
object.p_freq_limit = 0
object.p_freq_ramp = pow(frnd(2) - 1, 5)
if object.p_base_freq > 0.7 and object.p_freq_ramp > 0.2:
object.p_freq_ramp = -object.p_freq_ramp
if object.p_base_freq < 0.2 and object.p_freq_ramp < -0.05:
object.p_freq_ramp = -object.p_freq_ramp
object.p_freq_dramp = pow(frnd(2) - 1, 3)
object.p_duty = frnd(2) - 1
object.p_duty_ramp = pow(frnd(2) - 1, 3)
object.p_vib_strength = pow(frnd(2) - 1, 3)
object.p_vib_speed = rndr(-1, 1)
object.p_env_attack = pow(rndr(-1, 1), 3)
object.p_env_sustain = pow(rndr(-1, 1), 2)
object.p_env_decay = rndr(-1, 1)
object.p_env_punch = pow(frnd(0.8), 2)
if object.p_env_attack + object.p_env_sustain + object.p_env_decay < 0.2:
object.p_env_sustain += 0.2 + frnd(0.3)
object.p_env_decay += 0.2 + frnd(0.3)
object.p_lpf_resonance = rndr(-1, 1)
object.p_lpf_freq = 1 - pow(frnd(1), 3)
object.p_lpf_ramp = pow(frnd(2) - 1, 3)
if object.p_lpf_freq < 0.1 and object.p_lpf_ramp < -0.05:
object.p_lpf_ramp = -object.p_lpf_ramp
object.p_hpf_freq = pow(frnd(1), 5)
object.p_hpf_ramp = pow(frnd(2) - 1, 5)
object.p_pha_offset = pow(frnd(2) - 1, 3)
object.p_pha_ramp = pow(frnd(2) - 1, 3)
object.p_repeat_speed = frnd(2) - 1
object.p_arp_speed = frnd(2) - 1
object.p_arp_mod = frnd(2) - 1
static func _presets_mutate(object: Node):
if rnd(1): object.p_base_freq += frnd(0.1) - 0.05
if rnd(1): object.p_freq_ramp += frnd(0.1) - 0.05
if rnd(1): object.p_freq_dramp += frnd(0.1) - 0.05
if rnd(1): object.p_duty += frnd(0.1) - 0.05
if rnd(1): object.p_duty_ramp += frnd(0.1) - 0.05
if rnd(1): object.p_vib_strength += frnd(0.1) - 0.05
if rnd(1): object.p_vib_speed += frnd(0.1) - 0.05
if rnd(1): object.p_env_attack += frnd(0.1) - 0.05
if rnd(1): object.p_env_sustain += frnd(0.1) - 0.05
if rnd(1): object.p_env_decay += frnd(0.1) - 0.05
if rnd(1): object.p_env_punch += frnd(0.1) - 0.05
if rnd(1): object.p_lpf_resonance += frnd(0.1) - 0.05
if rnd(1): object.p_lpf_freq += frnd(0.1) - 0.05
if rnd(1): object.p_lpf_ramp += frnd(0.1) - 0.05
if rnd(1): object.p_hpf_freq += frnd(0.1) - 0.05
if rnd(1): object.p_hpf_ramp += frnd(0.1) - 0.05
if rnd(1): object.p_pha_offset += frnd(0.1) - 0.05
if rnd(1): object.p_pha_ramp += frnd(0.1) - 0.05
if rnd(1): object.p_repeat_speed += frnd(0.1) - 0.05
if rnd(1): object.p_arp_speed += frnd(0.1) - 0.05
if rnd(1): object.p_arp_mod += frnd(0.1) - 0.05
static func random_preset(object: Node) -> bool:
return preset_values(object, (randi() % (len(SfxrGlobals.PRESETS) - 1)) + 1)
static func preset_values(object: Node, preset_key: int) -> bool:
if preset_key >= 0 and preset_key < len(SfxrGlobals.PRESETS):
var preset = SfxrGlobals.PRESETS.keys()[preset_key].to_lower()
match preset:
"pickup":
_presets_pickup(object)
return true
"laser":
_presets_laser(object)
return true
"explosion":
_presets_explosion(object)
return true
"powerup":
_presets_powerup(object)
return true
"hit":
_presets_hit(object)
return true
"jump":
_presets_jump(object)
return true
"click":
_presets_click(object)
return true
"blip":
_presets_blip(object)
return true
"synth":
_presets_synth(object)
return true
"random":
_presets_random(object)
return true
"tone":
_presets_tone(object)
return true
"mutate":
_presets_mutate(object)
return true
return false
##################################
# Playback
##################################
static func _schedule_build_sfx(object: Node, play_after_build: bool):
var timer: SceneTreeTimer = object.get_tree().create_timer(.5)
object.sfx_timer = timer
timer.timeout.connect(func(): object._on_sfx_timer_timeout(timer, play_after_build))
static func _on_sfx_timer_timeout(object: Node, timer: SceneTreeTimer, play_after_build: bool):
if timer == object.sfx_timer:
build_sfx(object, play_after_build)
static func build_sfx(object: Node, play_after_build: bool = false):
var sfxg = SfxrGenerator.new()
sfxg.build_sample(object)
if play_after_build:
object.play()
object.notify_property_list_changed()

View File

@@ -1,7 +0,0 @@
[plugin]
name="GodotSfxr"
description="Sfx Generator. Port of jsfxr (https://sfxr.me - by Eric Fredricksen) which is a port of sfxr (https://www.drpetter.se/project_sfxr.html - by DrPetter)."
author="Tomeyro"
version="1.0"
script="GodotSfxr.gd"

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
addons/tbloader/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dqv5atotjgx01"
path="res://.godot/imported/untitled_DefaultMaterial_Normal.png-1d66825270be8b0e737ff63c686f533c.ctex"
uid="uid://cbbpw5sol06i6"
path="res://.godot/imported/icon.png-7c6403be1be0a98a34b14bf837b41c44.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/Weapons/Bullet/untitled_DefaultMaterial_Normal.png"
dest_files=["res://.godot/imported/untitled_DefaultMaterial_Normal.png-1d66825270be8b0e737ff63c686f533c.ctex"]
source_file="res://addons/tbloader/icon.png"
dest_files=["res://.godot/imported/icon.png-7c6403be1be0a98a34b14bf837b41c44.ctex"]
[params]

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>TBLoader</title>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:title>TBLoader</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="matrix(.23996 0 0 .24633 -15.301 -26.547)" fill="none">
<path d="m97.213 109.57-30.357 8.4385-5.37e-4 -5.6e-4 8.3597 29.977 21.989 21.198v8.6e-4l9.36e-4 -5.5e-4 5.35e-4 5.5e-4v-8.6e-4l21.99-21.198 8.356-29.965 0.0192-0.0115zm0 25.412 0.0083 0.5401-0.01402 9e-3zm-0.0083 0.54822 0.0022 8.5e-4 -9.37e-4 0.94463z" stop-color="#000000" style="-inkscape-stroke:none;font-variation-settings:normal"/>
<path transform="translate(-6.7616,1.2332)" d="m103.97 109.62-29.045 8.0742 29.039 16.766 6e-3 -0.52539 8e-3 0.52539 29.039-16.766z" stop-color="#000000" stroke="#fb8080" stroke-miterlimit="3" stroke-width="3.3" style="-inkscape-stroke:none;font-variation-settings:normal;paint-order:normal"/>
<path d="m68.168 118.93 29.038 16.766 0.01581 32.214-21.055-20.297zm58.077 0-29.038 16.766-0.01581 32.214 21.055-20.297z" stop-color="#000000" stroke="#fb8080" stroke-miterlimit="3" stroke-width="3.3" style="-inkscape-stroke:none;font-variation-settings:normal;paint-order:normal"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b6bigon1m2gl"
path="res://.godot/imported/tbloader.svg-ac537690612434f49f9a80d3b536a819.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/tbloader/icons/tbloader.svg"
dest_files=["res://.godot/imported/tbloader.svg-ac537690612434f49f9a80d3b536a819.ctex"]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1,7 @@
[plugin]
name="TBLoader"
description="TrenchBroom map loader."
author="Codecat"
version="0.9.0"
script="src/plugin.gd"

View File

@@ -0,0 +1,64 @@
@tool
extends EditorPlugin
class_name TBPlugin
var map_control: Control = null
var editing_loader: WeakRef = weakref(null)
func _enter_tree():
set_icons(true)
map_control = create_map_control()
map_control.set_visible(false)
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, map_control)
func _exit_tree():
set_icons(false)
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, map_control)
map_control.queue_free()
map_control = null
func _handles(object):
return object is TBLoader
func _make_visible(visible: bool):
map_control.set_visible(visible)
func _edit(object):
editing_loader = weakref(object)
func create_map_control() -> Control:
var button_build_meshes = Button.new()
button_build_meshes.flat = true
button_build_meshes.text = "Build Meshes"
button_build_meshes.connect("pressed", Callable(self, "build_meshes"))
var button_build_csg = Button.new()
button_build_csg.flat = true
button_build_csg.text = "Build Combined CSG"
button_build_csg.connect("pressed", Callable(self, "build_combined_csg"))
var ret = HBoxContainer.new()
ret.add_child(button_build_meshes)
ret.add_child(button_build_csg)
return ret
func build_meshes():
var loader = editing_loader.get_ref()
loader.build_meshes()
func build_combined_csg():
var loader = editing_loader.get_ref()
loader.build_combined_csg()
func set_icons(on):
var editor_interface = get_editor_interface()
var base_control = editor_interface.get_base_control()
var theme = base_control.theme
if on:
var texture = ResourceLoader.load("res://addons/tbloader/icons/tbloader.svg")
theme.set_icon("TBLoader", "EditorIcons", texture)
else:
theme.clear_icon("TBLoader", "EditorIcons")

View File

@@ -0,0 +1,7 @@
[configuration]
entry_symbol = "tbloader_init"
[libraries]
windows.64 = "bin/tbloader.windows.x86_64.dll"
linux.64 = "bin/libtbloader.linux.x86_64.so"
macos.64 = "bin/libtbloader.macos.universal.dylib"

View File

@@ -0,0 +1,201 @@
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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 271 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 299 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 317 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 358 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 197 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 145 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 258 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 299 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 317 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 317 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 145 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 246 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 235 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 159 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 145 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 205 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 218 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 190 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 367 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 213 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 181 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 248 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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.

After

Width:  |  Height:  |  Size: 314 B

View File

@@ -0,0 +1,34 @@
[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/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
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

@@ -0,0 +1,59 @@
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btblackboard.png")
extends Node
class_name BTBlackboard
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
@export var data:Dictionary = {}
#------------------------------------------
# Variables privées
#------------------------------------------
var _execution_data:Dictionary = {}
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
# On copie le dico défini par l'utilisateur dans le dico privé
_execution_data.merge(data)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func get_delta() -> float:
return get_data("delta")
func has_data(key:Variant) -> bool:
return get_data(key) != null
func get_data(key:Variant, default_value:Variant = null) -> Variant:
var result:Variant = _execution_data.get(key, default_value)
return result.get_ref() if result is WeakRef else result
func set_data(key:Variant, value:Variant) -> Variant:
var old_value:Variant = _execution_data[key] if _execution_data.has(key) else null
_execution_data[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) -> Variant:
var old_value = _execution_data[key] if _execution_data.has(key) else null
_execution_data.erase(key)
return old_value.get_ref() if old_value is WeakRef else old_value
#------------------------------------------
# Fonctions privées
#------------------------------------------

View File

@@ -0,0 +1,116 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btnode.png")
extends Node
class_name BTNode
#------------------------------------------
# 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:
child_entered_tree.connect(_update_configuration_warnings_1)
child_exiting_tree.connect(_update_configuration_warnings_1)
tree_entered.connect(_update_configuration_warnings_0)
tree_exited.connect(_update_configuration_warnings_0)
child_entered_tree.connect(_update_cached_children)
child_exiting_tree.connect(_update_cached_children)
func _ready() -> void:
if _is_in_editor:
update_configuration_warnings()
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, 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 = get_children().map(_node_as_bt_node)
func _execute(actor:Node2D, blackboard:BTBlackboard) -> int:
if _is_in_editor:
return BTTickResult.FAILURE
_enter(blackboard);
_start(blackboard)
var result:int = tick(actor, blackboard)
if result != BTTickResult.RUNNING:
_stop(blackboard)
_exit(blackboard)
return result
func _node_as_bt_node(node:Node) -> BTNode:
return node as BTNode
func _enter(blackboard:BTBlackboard) -> void:
enter(blackboard)
pass
func _start(blackboard:BTBlackboard) -> void:
blackboard.get_data("running_nodes", []).append(self)
if not blackboard.get_data("previously_running_nodes", []).has(self):
start(blackboard)
func _stop(blackboard:BTBlackboard) -> void:
blackboard.get_data("running_nodes", []).erase(self)
stop(blackboard)
func _exit(blackboard:BTBlackboard) -> void:
exit(blackboard)
pass

View File

@@ -0,0 +1,162 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btroot.png")
extends BTNode
class_name BTRoot
enum BTRootProcessMode {
PROCESS,
PHYSIC_PROCESS
}
#------------------------------------------
# Signaux
#------------------------------------------
signal on_running(running_node_names:Array)
signal on_idle()
#------------------------------------------
# Exports
#------------------------------------------
@export var enabled:bool = true:
set(value):
enabled = value
set_process(enabled)
set_physics_process(enabled)
@export var root_process_mode:BTRootProcessMode = BTRootProcessMode.PHYSIC_PROCESS
@export var actor_path:NodePath :
set(value):
actor_path = value
_update_actor_from_path()
update_configuration_warnings()
@export var blackboard:BTBlackboard = null :
set(value):
blackboard = value
update_configuration_warnings()
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _blackboard:BTBlackboard
var _previous_running_nodes:Array[BTNode] = []
var _actor:Node2D
var _execution_blackboard:BTBlackboard
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():
enabled = false
# Init du blackboard: soit celui de l'utilisateur, soit un tout neuf
if blackboard != null and is_instance_valid(blackboard):
_blackboard= blackboard
else:
_blackboard = BTBlackboard.new()
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_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()
_blackboard.set_data("delta", delta)
_blackboard.set_data("previously_running_nodes", Array(_previous_running_nodes))
_blackboard.set_data("running_nodes", [])
_children[0]._execute(_actor, _blackboard)
var running_nodes:Array[BTNode] = _blackboard.get_data("running_nodes", [])
if _previous_running_nodes != running_nodes:
for n in _previous_running_nodes:
if not running_nodes.has(n):
n._stop( _blackboard)
if not running_nodes.is_empty():
var running_node_names:Array[String] = running_nodes.filter(func(n): return n.is_leaf()).map(func(n): return str(n.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

@@ -0,0 +1,52 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btcomposite.png")
extends BTNode
class_name BTComposite
#------------------------------------------
# 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

@@ -0,0 +1,52 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btparallel.png")
extends BTComposite
class_name BTParallel
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node2D, 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 runn ing : 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

@@ -0,0 +1,37 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandomselector.png")
extends BTSelector
class_name BTRandomSelector
#------------------------------------------
# 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

@@ -0,0 +1,54 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btselector.png")
extends BTComposite
class_name BTSelector
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var save_progression:bool = false
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _running_child_index:int = -1
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node2D, 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

@@ -0,0 +1,43 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btsequence.png")
extends BTComposite
class_name BTSequence
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var save_progression:bool = false
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func tick(actor:Node2D, blackboard:BTBlackboard) -> int:
for child in _children:
var result:int = child._execute(actor, blackboard)
if result != BTTickResult.SUCCESS:
return result
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View File

@@ -0,0 +1,52 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btdecorator.png")
extends BTNode
class_name BTDecorator
#------------------------------------------
# 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

@@ -0,0 +1,37 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btfailure.png")
extends BTDecorator
class_name BTFailure
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, blackboard:BTBlackboard) -> int:
_children[0]._execute(actor, blackboard)
return BTTickResult.FAILURE
#------------------------------------------
# Fonctions privées
#------------------------------------------

View File

@@ -0,0 +1,41 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btinverter.png")
extends BTDecorator
class_name BTInverter
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, 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

@@ -0,0 +1,51 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btlimiter.png")
extends BTDecorator
class_name BTLimiter
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export_range(0, 9999999, 1) var limit:int = 1
@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:Node2D, 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

@@ -0,0 +1,40 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrandom.png")
extends BTDecorator
class_name BTRandom
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export_range(0, 1) var probability:float = 0.5
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, 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

@@ -0,0 +1,56 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btrepeatuntil.png")
extends BTDecorator
class_name BTRepeatUntil
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export_enum("SUCCESS:0", "RUNNING:1", "FAILURE:2") var stop_condition:int = 0
@export_range(0, 999999) var max_iteration:int = 0
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, 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

@@ -0,0 +1,37 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btsuccess.png")
extends BTDecorator
class_name BTSuccess
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func tick(actor:Node2D, blackboard:BTBlackboard) -> int:
_children[0]._execute(actor, blackboard)
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------

View File

@@ -0,0 +1,32 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btaction.png")
extends BTLeaf
class_name BTAction
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View File

@@ -0,0 +1,58 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboarddelete.png")
extends BTLeaf
class_name BTActionBlackboardDelete
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@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:Node2D, 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

@@ -0,0 +1,85 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionblackboardset.png")
extends BTLeaf
class_name BTActionBlackboardSet
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var blackboard_key:String = "" :
set(value):
blackboard_key = value
update_configuration_warnings()
@export_multiline var expression:String = "" :
set(value):
if value != expression:
expression = value
_update_expression()
update_configuration_warnings()
@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:Node2D, 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

@@ -0,0 +1,100 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactioncallable.png")
extends BTLeaf
class_name BTActionCallable
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var method_owner_path:NodePath:
set(value):
method_owner_path = value
_update_method_owner_from_path()
update_configuration_warnings()
@export var method_name:String = "":
set(value):
method_name = value
update_configuration_warnings()
@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:Node2D, 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

@@ -0,0 +1,53 @@
@tool
@icon("res://addons/yet_another_behavior_tree/src/Assets/Icons/btactionwait.png")
extends BTLeaf
class_name BTActionWait
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var wait_time_ms:int = 1_000
@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:Node2D, 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
#------------------------------------------

Some files were not shown because too many files have changed in this diff Show More