diff --git a/addons/godot_projectile_engine/core/timing_scheduler/base/timing_scheduler_component.gd b/addons/godot_projectile_engine/core/timing_scheduler/base/timing_scheduler_component.gd index 8b76cd00..26a95a67 100644 --- a/addons/godot_projectile_engine/core/timing_scheduler/base/timing_scheduler_component.gd +++ b/addons/godot_projectile_engine/core/timing_scheduler/base/timing_scheduler_component.gd @@ -16,18 +16,19 @@ enum TimingMode { NO, ## No timed emited. } -@export var active : bool = true: +@export var active: bool = true: set(value): active = value if !value: clear_timing_timer() + @export var timing_mode: TimingMode = TimingMode.INSTANT @export var update_mode: UpdateMode = UpdateMode.INHERIT - var timing_timer: Timer +var request_stop: bool = false + -var request_stop : bool = false func start_next_timing_value() -> void: pass diff --git a/addons/godot_projectile_engine/core/timing_scheduler/cooldown/tsc_cooldown.gd b/addons/godot_projectile_engine/core/timing_scheduler/cooldown/tsc_cooldown.gd index ebb8e73c..05aa9772 100644 --- a/addons/godot_projectile_engine/core/timing_scheduler/cooldown/tsc_cooldown.gd +++ b/addons/godot_projectile_engine/core/timing_scheduler/cooldown/tsc_cooldown.gd @@ -2,8 +2,6 @@ extends TimingSchedulerComponent class_name TSCCooldown -## Cooldown timing scheduler component that waits for a fixed duration before completing - ## Duration of the cooldown in seconds @export var cooldown_duration : float = 1.0 diff --git a/addons/godot_projectile_engine/core/timing_scheduler/repeater/tsc_repeater.gd b/addons/godot_projectile_engine/core/timing_scheduler/repeater/tsc_repeater.gd index 0283bab3..82d47142 100644 --- a/addons/godot_projectile_engine/core/timing_scheduler/repeater/tsc_repeater.gd +++ b/addons/godot_projectile_engine/core/timing_scheduler/repeater/tsc_repeater.gd @@ -2,17 +2,20 @@ extends TimingSchedulerComponent class_name TSCRepeater -## Repeats a duration multiple times -## - repeat_count = 0: Complete immediately -## - repeat_count < 0: Infinite repetitions -## - repeat_count > 0: Finite repetitions ## Duration to repeat in seconds -@export var duration: float = 1.0 -## Repetition count (0=immediate, <0 infinite, >0 finite) -@export var repeat_count: int = -1 +@export var duration: float = 1.0 +@export var repeat_count: int = 1 +var current_count: int = 0 ## Current repetition count -var current_count: int = 0 ## Current repetition count +@export_group("Random") +@export var random_duration: Vector3 = Vector3.ZERO +@export var random_repeat_count: Vector3i = Vector3i.ZERO + + +func _ready() -> void: + if random_repeat_count != Vector3i.ZERO: + repeat_count = ProjectileEngine.get_random_int_value(random_repeat_count) ## Override stop_tsc to reset counter and call parent implementation func stop_tsc() -> void: @@ -35,7 +38,7 @@ func start_next_timing_value() -> void: # Reset counter and start first repetition current_count = 0 - timing_timer.start(duration) + start_timing_timer() ## Handles timer timeout events func on_timing_timer_timeout() -> void: @@ -47,13 +50,18 @@ func on_timing_timer_timeout() -> void: else: # Infinite mode - always restart timer tsc_timed.emit() - timing_timer.start(duration) + start_timing_timer() else: # Finite mode - increment count and check if complete current_count += 1 if current_count < repeat_count: tsc_timed.emit() - timing_timer.start(duration) + start_timing_timer() else: tsc_completed.emit() - + +func start_timing_timer() -> void: + if random_duration != Vector3.ZERO: + duration = ProjectileEngine.get_random_float_value(random_duration) + timing_timer.start(duration) + pass diff --git a/addons/godot_projectile_engine/core/timing_scheduler/timing_set/tsc_timing_set.gd b/addons/godot_projectile_engine/core/timing_scheduler/timing_set/tsc_timing_set.gd index 798914c4..4e80b311 100644 --- a/addons/godot_projectile_engine/core/timing_scheduler/timing_set/tsc_timing_set.gd +++ b/addons/godot_projectile_engine/core/timing_scheduler/timing_set/tsc_timing_set.gd @@ -7,12 +7,12 @@ class_name TSCTimingSet ## TimingSet Resource containing timing intervals and playback parameters for sequenced or randomized execution. -@export var timing_set: TimingSet +@export var timing_set: TimingSet -var _timing_set_index: int = -1 # Current index in timing entries -var _current_repeat_count: int = 0 # Number of completed cycles -var _current_interval: float = 0.0 # Current interval duration -var _shuffled_entries: Array[float] = [] # Shuffled entries for RANDOM mode +var _timing_set_index: int = -1 # Current index in timing entries +var _current_repeat_count: int = 0 # Number of completed cycles +var _current_interval: float = 0.0 # Current interval duration +var _shuffled_entries: Array[float] = [] # Shuffled entries for RANDOM mode func _validate_property(property: Dictionary) -> void: @@ -91,7 +91,7 @@ func get_next_timing_value() -> float: _interval_value = timing_set.entries[_timing_set_index] if _timing_set_index >= timing_set.entries.size() - 1: _current_repeat_count += 1 - _timing_set_index = -1 # Reset index for next cycle + _timing_set_index = -1 # Reset index for next cycle TimingSet.PlaybackMode.RANDOM: # Initialize shuffled list at start of cycle diff --git a/experiments/experiment_timing_scheduler/experiment_timing_scheduler_2.tscn b/experiments/experiment_timing_scheduler/experiment_timing_scheduler_2.tscn new file mode 100644 index 00000000..70cdbc5a --- /dev/null +++ b/experiments/experiment_timing_scheduler/experiment_timing_scheduler_2.tscn @@ -0,0 +1,75 @@ +[gd_scene load_steps=13 format=3 uid="uid://dgigvgl8qnxi1"] + +[ext_resource type="Script" uid="uid://dn7rm61wq3t3s" path="res://addons/godot_projectile_engine/core/projectile_environment/projectile_environment.gd" id="1_uirft"] +[ext_resource type="Script" uid="uid://cnqgcej10tinn" path="res://addons/godot_projectile_engine/core/projectile_spawner/projectile_spawner.gd" id="2_1y1yv"] +[ext_resource type="Script" uid="uid://dqlixqba72p5f" path="res://addons/godot_projectile_engine/core/projectile_template/projectile_template_simple_2d/projectile_template_simple_2d.gd" id="3_88bgx"] +[ext_resource type="Texture2D" uid="uid://xej5ti53m73n" path="res://addons/godot_projectile_engine/examples/assets/projectile/projectile_circle_1.png" id="4_db7b4"] +[ext_resource type="Script" uid="uid://cs3yq53jlx0po" path="res://addons/godot_projectile_engine/core/projectile_spawner/spawn_marker/projectile_spawn_maker_2d.gd" id="5_hfar3"] +[ext_resource type="Script" uid="uid://bc73oiea731jc" path="res://addons/godot_projectile_engine/core/pattern_composer/pattern_composer.gd" id="6_hk3kg"] +[ext_resource type="Script" uid="uid://co24jiat0y46s" path="res://addons/godot_projectile_engine/core/pattern_composer/component/PCCSingle2D.gd" id="7_1p6o2"] +[ext_resource type="Script" uid="uid://b8nclaklcf4uu" path="res://addons/godot_projectile_engine/core/timing_scheduler/timing_scheduler.gd" id="8_mrk8b"] +[ext_resource type="Script" uid="uid://sjpvs4m6jk71" path="res://addons/godot_projectile_engine/core/timing_scheduler/repeater/tsc_repeater.gd" id="12_u88oo"] + +[sub_resource type="Gradient" id="Gradient_td4cq"] +offsets = PackedFloat32Array(0) +colors = PackedColorArray(0.0705882, 0.0705882, 0.121569, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_uirft"] +gradient = SubResource("Gradient_td4cq") + +[sub_resource type="Resource" id="Resource_un40f"] +script = ExtResource("3_88bgx") +texture = ExtResource("4_db7b4") +metadata/_custom_type_script = "uid://dqlixqba72p5f" + +[node name="ExperimentTimingScheduler1" type="Node2D"] + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(0, 1.9073486e-06) +scale = Vector2(59.75, 39.625) +texture = SubResource("GradientTexture2D_uirft") + +[node name="ProjectileEnvironment2D" type="Node2D" parent="."] +script = ExtResource("1_uirft") +metadata/_custom_type_script = "uid://dn7rm61wq3t3s" + +[node name="Camera2D" type="Camera2D" parent="."] + +[node name="ProjectileSpawner2D" type="Node2D" parent="." node_paths=PackedStringArray("timing_scheduler")] +script = ExtResource("2_1y1yv") +projectile_composer_name = "simple" +projectile_template_2d = SubResource("Resource_un40f") +timing_scheduler = NodePath("../TimingScheduler") +metadata/_custom_type_script = "uid://cnqgcej10tinn" + +[node name="ProjectileSpawner2D2" type="Node2D" parent="." node_paths=PackedStringArray("timing_scheduler")] +script = ExtResource("2_1y1yv") +projectile_composer_name = "simple" +projectile_template_2d = SubResource("Resource_un40f") +timing_scheduler = NodePath("../TimingScheduler") +metadata/_custom_type_script = "uid://cnqgcej10tinn" + +[node name="ProjectileSpawnMarker2D" type="Marker2D" parent="ProjectileSpawner2D2"] +script = ExtResource("5_hfar3") +init_direction = Vector2(-1, 0) +metadata/_custom_type_script = "uid://cs3yq53jlx0po" + +[node name="PatternComposer2D" type="Node" parent="."] +script = ExtResource("6_hk3kg") +composer_name = "simple" +metadata/_custom_type_script = "uid://bc73oiea731jc" + +[node name="PCCSingle2D" type="Node" parent="PatternComposer2D"] +script = ExtResource("7_1p6o2") +rotation_speed = 17.0 +rotation_process_mode = 1 +metadata/_custom_type_script = "uid://co24jiat0y46s" + +[node name="TimingScheduler" type="Node" parent="."] +script = ExtResource("8_mrk8b") +autostart = true +metadata/_custom_type_script = "uid://b8nclaklcf4uu" + +[node name="TSCRepeater" type="Node" parent="TimingScheduler"] +script = ExtResource("12_u88oo") +metadata/_custom_type_script = "uid://sjpvs4m6jk71"