diff --git a/godot/prefabs/player/player.gd b/godot/prefabs/player/player.gd new file mode 100644 index 0000000..eea81d0 --- /dev/null +++ b/godot/prefabs/player/player.gd @@ -0,0 +1,13 @@ +class_name Player +extends GridPosition + +@export var gatherer: Gatherer + +static func is_player(node: Node) -> bool: + return node is Player || node.get_parent() is Player + +func _ready() -> void: + gatherer.gathered.connect(_on_gathered) + +func _on_gathered(item: String, count: int): + print("gathered: ", count, " x ", item) diff --git a/godot/prefabs/player/player.gd.uid b/godot/prefabs/player/player.gd.uid new file mode 100644 index 0000000..b19ffc9 --- /dev/null +++ b/godot/prefabs/player/player.gd.uid @@ -0,0 +1 @@ +uid://cvviym6gdlod8 diff --git a/godot/prefabs/player/player.tscn b/godot/prefabs/player/player.tscn index e38f81f..7d1abd8 100644 --- a/godot/prefabs/player/player.tscn +++ b/godot/prefabs/player/player.tscn @@ -1,29 +1,27 @@ -[gd_scene load_steps=3 format=3 uid="uid://drs6h7ks4r2ta"] +[gd_scene load_steps=4 format=3 uid="uid://drs6h7ks4r2ta"] [ext_resource type="Texture2D" uid="uid://doscvutq8uqmd" path="res://sprites/sheet.png" id="1_72ieh"] +[ext_resource type="Script" uid="uid://cvviym6gdlod8" path="res://prefabs/player/player.gd" id="1_wv1mm"] [ext_resource type="Script" uid="uid://sxo578w2yds2" path="res://prefabs/player/player_input.gd" id="2_rdx4y"] -[node name="Player" type="GridPosition"] +[node name="Player" type="GridPosition" node_paths=PackedStringArray("gatherer")] +script = ExtResource("1_wv1mm") +gatherer = NodePath("Gatherer") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_72ieh") -centered = false hframes = 8 vframes = 8 frame = 1 [node name="Camera2D" type="Camera2D" parent="."] -position = Vector2(16, 16) zoom = Vector2(2, 2) -[node name="Gatherer" type="Gatherer" parent="." node_paths=PackedStringArray("grid", "actor")] -grid = NodePath("..") -actor = NodePath("../TurnActor") +[node name="Gatherer" type="Gatherer" parent="."] [node name="Mover" type="Mover" parent="."] [node name="TurnActor" type="TurnActor" parent="."] -position = Vector2(-1, 0) [node name="ActionDecider" type="Node2D" parent="." node_paths=PackedStringArray("grid", "mover", "actor")] script = ExtResource("2_rdx4y") diff --git a/godot/prefabs/tiles/blueberry.tscn b/godot/prefabs/tiles/blueberry.tscn new file mode 100644 index 0000000..bf60705 --- /dev/null +++ b/godot/prefabs/tiles/blueberry.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=3 format=3 uid="uid://8xuvjmyjkpeo"] + +[ext_resource type="Texture2D" uid="uid://doscvutq8uqmd" path="res://sprites/sheet.png" id="1_gjkx7"] +[ext_resource type="Script" uid="uid://jd6ce3f7e1bh" path="res://prefabs/tiles/gatherable_animation.gd" id="1_jqgth"] + +[node name="Blueberry" type="GridPosition" node_paths=PackedStringArray("gatherable", "picked", "not_picked")] +script = ExtResource("1_jqgth") +gatherable = NodePath("Gatherable") +picked = NodePath("Picked") +not_picked = NodePath("Not Picked") + +[node name="Not Picked" type="Sprite2D" parent="."] +texture = ExtResource("1_gjkx7") +hframes = 8 +vframes = 8 +frame = 16 + +[node name="Picked" type="Sprite2D" parent="."] +visible = false +texture = ExtResource("1_gjkx7") +hframes = 8 +vframes = 8 +frame = 17 + +[node name="Gatherable" type="Gatherable" parent="." node_paths=PackedStringArray("grid")] +grid = NodePath("..") diff --git a/godot/prefabs/tiles/cowberry.tscn b/godot/prefabs/tiles/cowberry.tscn new file mode 100644 index 0000000..b73fa94 --- /dev/null +++ b/godot/prefabs/tiles/cowberry.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=3 format=3 uid="uid://l72f05nek0y4"] + +[ext_resource type="Texture2D" uid="uid://doscvutq8uqmd" path="res://sprites/sheet.png" id="1_e3ld6"] +[ext_resource type="Script" uid="uid://jd6ce3f7e1bh" path="res://prefabs/tiles/gatherable_animation.gd" id="2_kod7n"] + +[node name="Blueberry" type="GridPosition" node_paths=PackedStringArray("gatherable", "picked", "not_picked")] +script = ExtResource("2_kod7n") +gatherable = NodePath("Gatherable") +picked = NodePath("Picked") +not_picked = NodePath("Not Picked") + +[node name="Not Picked" type="Sprite2D" parent="."] +texture = ExtResource("1_e3ld6") +hframes = 8 +vframes = 8 +frame = 20 + +[node name="Picked" type="Sprite2D" parent="."] +visible = false +texture = ExtResource("1_e3ld6") +hframes = 8 +vframes = 8 +frame = 17 + +[node name="Gatherable" type="Gatherable" parent="." node_paths=PackedStringArray("grid")] +grid = NodePath("..") +item = "Cowberry" diff --git a/godot/prefabs/tiles/gatherable_animation.gd b/godot/prefabs/tiles/gatherable_animation.gd new file mode 100644 index 0000000..19e1048 --- /dev/null +++ b/godot/prefabs/tiles/gatherable_animation.gd @@ -0,0 +1,16 @@ +extends Node + +@export var gatherable: Gatherable +@export var picked: CanvasItem +@export var not_picked: CanvasItem + +func _ready() -> void: + update_visibility(gatherable.get_is_picked()) + gatherable.picked_state_changed.connect(_on_gatherable_state_changed) + +func _on_gatherable_state_changed(is_picked): + update_visibility(is_picked) + +func update_visibility(is_picked: bool): + picked.visible = is_picked + not_picked.visible = not is_picked diff --git a/godot/prefabs/tiles/gatherable_animation.gd.uid b/godot/prefabs/tiles/gatherable_animation.gd.uid new file mode 100644 index 0000000..0388cf2 --- /dev/null +++ b/godot/prefabs/tiles/gatherable_animation.gd.uid @@ -0,0 +1 @@ +uid://jd6ce3f7e1bh diff --git a/godot/scenes/overworld.tscn b/godot/scenes/overworld.tscn index d5d4333..4591630 100644 --- a/godot/scenes/overworld.tscn +++ b/godot/scenes/overworld.tscn @@ -15,9 +15,8 @@ tile_map_data = PackedByteArray("AAD8//z/AQAAAAQAAAD8//3/AQAAAAQAAAD8//7/AQAAAAQ tile_set = ExtResource("1_m1b5j") [node name="Foreground" type="TileMapLayer" parent="Root"] -tile_map_data = PackedByteArray("AAD/////AQAAAAMAAAAEAAEAAQAAAAIAAAADAAEAAQAAAAIAAAADAAIAAQAAAAIAAAADAAMAAQAAAAIAAAACAAMAAQAAAAIAAAAFAAMAAQABAAIAAAAGAAMAAQABAAIAAAD8//3/AQABAAMAAAD9//3/AQABAAMAAAD9//7/AQABAAMAAAD9/wAAAQABAAMAAAD9/wEAAQABAAMAAAD8/wEAAQABAAMAAAAEAPv/AQACAAMAAAAGAP3/AQACAAMAAAAHAP7/AQACAAMAAAAIAP7/AQACAAMAAAAJAP7/AQACAAMAAAAGAPn/AQACAAMAAAAGAPr/AQACAAMAAAAGAPv/AQACAAMAAAAHAPv/AQACAAMAAAAIAPv/AQACAAMAAAAIAPz/AQACAAMAAAAJAPz/AQACAAMAAAAKAPz/AQACAAMAAAAKAPv/AQACAAMAAAAJAPv/AQACAAMAAAAIAPr/AQACAAMAAAAHAPr/AQACAAMAAAAHAPn/AQACAAMAAAD3//v/AQABAAMAAAD3//z/AQABAAMAAAD3//3/AQABAAMAAAD3//7/AQABAAMAAAD3////AQABAAMAAAD3/wAAAQABAAMAAAD3/wEAAQABAAMAAAD3/wIAAQABAAMAAAD4//v/AQABAAMAAAD4//z/AQABAAMAAAD4//3/AQABAAMAAAD4//7/AQABAAMAAAD4////AQABAAMAAAD4/wAAAQABAAMAAAD4/wEAAQABAAMAAAD4/wIAAQABAAMAAAD3/wMAAQABAAMAAAD3/wQAAQABAAMAAAD3/wUAAQABAAMAAAD4/wMAAQABAAMAAAD4/wQAAQABAAMAAAD4/wUAAQABAAMAAAD5/wUAAQABAAMAAAD6/wUAAQABAAMAAAD7/wUAAQABAAMAAAD8/wUAAQABAAMAAAD9/wUAAQABAAMAAAD+/wUAAQABAAMAAAD//wUAAQABAAMAAAAAAAUAAQABAAMAAAABAAUAAQABAAMAAAACAAUAAQABAAMAAAADAAUAAQABAAMAAAAEAAUAAQABAAMAAAAFAAUAAQABAAMAAAAGAAUAAQABAAMAAAAHAAUAAQABAAMAAAAIAAUAAQABAAMAAAAJAAUAAQABAAMAAAD5//v/AQABAAMAAAD6//v/AQABAAMAAAD7//v/AQABAAMAAAD8//v/AQABAAMAAAD9//v/AQABAAMAAAD+//v/AQABAAMAAAD///v/AQABAAMAAAAAAPv/AQABAAMAAAABAPv/AQABAAMAAAACAPv/AQABAAMAAAADAPv/AQABAAMAAAAJAP//AQABAAMAAAAJAAAAAQABAAMAAAAJAAEAAQABAAMAAAAJAAIAAQABAAMAAAAJAAMAAQABAAMAAAAJAAQAAQABAAMAAAD7/wEAAQABAAMAAAD7//3/AQABAAMAAAD6//3/AQABAAMAAAD6/wEAAQABAAMAAAD6//7/AQABAAMAAAD6/wAAAQABAAMAAAA=") +tile_map_data = PackedByteArray("AAD/////AQAAAAMAAAD8//3/AQABAAMAAAD9//3/AQABAAMAAAD9//7/AQABAAMAAAD9/wAAAQABAAMAAAD9/wEAAQABAAMAAAD8/wEAAQABAAMAAAAEAPv/AQACAAMAAAAGAP3/AQACAAMAAAAHAP7/AQACAAMAAAAIAP7/AQACAAMAAAAJAP7/AQACAAMAAAAGAPn/AQACAAMAAAAGAPr/AQACAAMAAAAGAPv/AQACAAMAAAAHAPv/AQACAAMAAAAIAPv/AQACAAMAAAAIAPz/AQACAAMAAAAJAPz/AQACAAMAAAAKAPz/AQACAAMAAAAKAPv/AQACAAMAAAAJAPv/AQACAAMAAAAIAPr/AQACAAMAAAAHAPr/AQACAAMAAAAHAPn/AQACAAMAAAD3//v/AQABAAMAAAD3//z/AQABAAMAAAD3//3/AQABAAMAAAD3//7/AQABAAMAAAD3////AQABAAMAAAD3/wAAAQABAAMAAAD3/wEAAQABAAMAAAD3/wIAAQABAAMAAAD4//v/AQABAAMAAAD4//z/AQABAAMAAAD4//3/AQABAAMAAAD4//7/AQABAAMAAAD4////AQABAAMAAAD4/wAAAQABAAMAAAD4/wEAAQABAAMAAAD4/wIAAQABAAMAAAD3/wMAAQABAAMAAAD3/wQAAQABAAMAAAD3/wUAAQABAAMAAAD4/wMAAQABAAMAAAD4/wQAAQABAAMAAAD4/wUAAQABAAMAAAD5/wUAAQABAAMAAAD6/wUAAQABAAMAAAD7/wUAAQABAAMAAAD8/wUAAQABAAMAAAD9/wUAAQABAAMAAAD+/wUAAQABAAMAAAD//wUAAQABAAMAAAAAAAUAAQABAAMAAAABAAUAAQABAAMAAAACAAUAAQABAAMAAAADAAUAAQABAAMAAAAEAAUAAQABAAMAAAAFAAUAAQABAAMAAAAGAAUAAQABAAMAAAAHAAUAAQABAAMAAAAIAAUAAQABAAMAAAAJAAUAAQABAAMAAAD5//v/AQABAAMAAAD6//v/AQABAAMAAAD7//v/AQABAAMAAAD8//v/AQABAAMAAAD9//v/AQABAAMAAAD+//v/AQABAAMAAAD///v/AQABAAMAAAAAAPv/AQABAAMAAAABAPv/AQABAAMAAAACAPv/AQABAAMAAAADAPv/AQABAAMAAAAJAP//AQABAAMAAAAJAAAAAQABAAMAAAAJAAEAAQABAAMAAAAJAAIAAQABAAMAAAAJAAMAAQABAAMAAAAJAAQAAQABAAMAAAD7/wEAAQABAAMAAAD7//3/AQABAAMAAAD6//3/AQABAAMAAAD6/wEAAQABAAMAAAD6//7/AQABAAMAAAD6/wAAAQABAAMAAAD6/wQAAAAAAAAAAgD5/wQAAAAAAAAAAgD5/wMAAAAAAAAAAgAEAAEAAAAAAAAAAQADAAEAAAAAAAAAAQADAAIAAAAAAAAAAQADAAMAAAAAAAAAAQACAAMAAAAAAAAAAQA=") tile_set = ExtResource("2_u2ss0") [node name="Player" parent="Root" instance=ExtResource("3_u2ss0")] - -[node name="Camera2D" type="Camera2D" parent="Root"] +position = Vector2(16, 16) diff --git a/godot/sprites/sheet.aseprite b/godot/sprites/sheet.aseprite index e304de2..0846ede 100644 Binary files a/godot/sprites/sheet.aseprite and b/godot/sprites/sheet.aseprite differ diff --git a/godot/sprites/sheet.png b/godot/sprites/sheet.png index c0f4ce9..6373967 100644 Binary files a/godot/sprites/sheet.png and b/godot/sprites/sheet.png differ diff --git a/godot/tilesets/foreground_tileset.tres b/godot/tilesets/foreground_tileset.tres index b8f7a9e..129dfc2 100644 --- a/godot/tilesets/foreground_tileset.tres +++ b/godot/tilesets/foreground_tileset.tres @@ -1,24 +1,26 @@ -[gd_resource type="TileSet" load_steps=3 format=3 uid="uid://bxwohuw2p43k1"] +[gd_resource type="TileSet" load_steps=6 format=3 uid="uid://bxwohuw2p43k1"] [ext_resource type="Texture2D" uid="uid://doscvutq8uqmd" path="res://sprites/sheet.png" id="1_oe62d"] +[ext_resource type="PackedScene" uid="uid://8xuvjmyjkpeo" path="res://prefabs/tiles/blueberry.tscn" id="1_rc83b"] +[ext_resource type="PackedScene" uid="uid://l72f05nek0y4" path="res://prefabs/tiles/cowberry.tscn" id="2_w3v7n"] + +[sub_resource type="TileSetScenesCollectionSource" id="TileSetScenesCollectionSource_w3v7n"] +resource_name = "Entities" +scenes/1/scene = ExtResource("1_rc83b") +scenes/2/scene = ExtResource("2_w3v7n") [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_rc83b"] texture = ExtResource("1_oe62d") texture_region_size = Vector2i(32, 32) -0:3/0 = 0 -0:3/0/custom_data_0 = true -0:2/0 = 0 -0:2/0/custom_data_1 = true -1:2/0 = 0 1:3/0 = 0 1:3/0/custom_data_0 = true 2:3/0 = 0 2:3/0/custom_data_0 = true +0:3/0 = 0 [resource] tile_size = Vector2i(32, 32) custom_data_layer_0/name = "has_collision" custom_data_layer_0/type = 1 -custom_data_layer_1/name = "is_berry" -custom_data_layer_1/type = 1 sources/1 = SubResource("TileSetAtlasSource_rc83b") +sources/0 = SubResource("TileSetScenesCollectionSource_w3v7n") diff --git a/rust/src/gathering.rs b/rust/src/gathering.rs new file mode 100644 index 0000000..30cefac --- /dev/null +++ b/rust/src/gathering.rs @@ -0,0 +1,124 @@ +use godot::{classes::*, obj::WithUserSignals, prelude::*}; + +use crate::{ + grid::*, + turn::*, + utils::{find_by_type_in_children, find_in_parents}, +}; + +#[derive(GodotConvert, Var, Export, Clone, Copy, Default, Debug, PartialEq, Eq)] +#[godot(via = GString)] +pub enum ItemKind { + #[default] + Blueberry, + Cowberry, +} + +#[derive(Debug, GodotClass)] +#[class(init, base=Node)] +pub struct Gatherer { + #[export] + #[init(val = 0)] + radius: i32, + + base: Base, +} + +#[godot_api] +impl INode for Gatherer {} + +#[godot_api] +impl Gatherer { + #[func] + pub fn gather(&mut self, item: ItemKind, count: i32) { + self.signals().gathered().emit(&item.to_godot(), count); + } + + #[signal] + fn gathered(item: GString, count: i32); +} + +#[derive(Debug, GodotClass)] +#[class(init, base=Node)] +pub struct Gatherable { + #[export] + grid: Option>, + #[export] + item: ItemKind, + #[export] + #[init(val = 1)] + count: i32, + #[export] + #[init(val = true)] + pick_automatically: bool, + + #[var(get = get_is_picked, set = set_is_picked)] + _is_picked: bool, + + base: Base, +} + +#[godot_api] +impl INode for Gatherable {} + +#[godot_api] +impl Gatherable { + #[func] + pub fn get_is_picked(&self) -> bool { + self._is_picked + } + + #[func] + pub fn set_is_picked(&mut self, value: bool) { + let old = self._is_picked; + self._is_picked = value; + if old != value { + self.signals().picked_state_changed().emit(value); + } + } + + #[func] + fn on_turn_end(&mut self, actor: Option>, _action: GString) { + if self.get_is_picked() { + return; + } + let actor = match actor { + Some(actor) => actor, + None => return, + }; + let actor_grid = match find_in_parents::(actor.clone()) { + Some(grid) => grid, + None => return, + }; + let gatherer = match find_by_type_in_children::(actor_grid.clone()) { + Some(gatherer) => gatherer, + None => return, + }; + let my_coords = self + .grid + .as_ref() + .expect("Getting Grid from EnterTrigger") + .bind() + .get_coords(); + let coords = actor_grid.bind().get_coords(); + if my_coords.distance_squared_to(coords) <= (gatherer.bind().get_radius() as i64).pow(2) { + self.pick_for_gatherer(gatherer); + } + } + + fn pick_for_gatherer(&mut self, mut gatherer: Gd) { + gatherer.bind_mut().gather(self.item, self.count); + let item = self.item.to_godot().clone(); + let count = self.count; + if self.pick_automatically { + self.set_is_picked(true); + } + self.signals().gathered().emit(&item, count); + } + + #[signal] + fn picked_state_changed(is_picked: bool); + + #[signal] + fn gathered(item: GString, count: i32); +} diff --git a/rust/src/overworld.rs b/rust/src/grid.rs similarity index 67% rename from rust/src/overworld.rs rename to rust/src/grid.rs index e102014..2cb00b6 100644 --- a/rust/src/overworld.rs +++ b/rust/src/grid.rs @@ -1,6 +1,6 @@ -use godot::{classes::*, prelude::*}; +use godot::{classes::*, obj::WithUserSignals, prelude::*}; -use crate::{turn::*, utils::find_in_parents}; +use crate::utils::find_in_parents; #[derive(Debug, GodotClass)] #[class(init, base=Node)] @@ -78,6 +78,10 @@ pub struct GridPosition { #[init(val = Vector2::splat(32.0))] grid_size: Vector2, + #[export] + #[init(val = Vector2::splat(0.5))] + grid_anchor: Vector2, + base: Base, } @@ -85,85 +89,29 @@ pub struct GridPosition { impl GridPosition { #[func] pub fn get_coords(&self) -> Vector2i { - (self.base().get_global_position() / self.grid_size) + self.world_to_coords(self.base().get_global_position()) + } + + #[func] + pub fn set_coords(&mut self, coords: Vector2i) { + let old = self.get_coords(); + let pos = self.coords_to_world(coords); + self.base_mut().set_global_position(pos); + self.signals().coords_set().emit(old, coords); + } + + pub fn coords_to_world(&self, coords: Vector2i) -> Vector2 { + (coords.cast_float() + self.grid_anchor) * self.grid_size + } + + pub fn world_to_coords(&self, pos: Vector2) -> Vector2i { + ((pos / self.grid_size) - self.grid_anchor) .round() .cast_int() } - #[func] - pub fn set_coords(&mut self, pos: Vector2i) { - let grid_size = self.grid_size; - self.base_mut() - .set_global_position(pos.cast_float() * grid_size); - } -} - -#[derive(GodotConvert, Var, Export, Clone, Copy, Default, Debug, PartialEq, Eq)] -#[godot(via = GString)] -pub enum ItemKind { - #[default] - Blueberry, -} - -#[derive(Debug, GodotClass)] -#[class(init, base=Node)] -pub struct Gatherer { - #[export] - grid: Option>, - #[export] - actor: Option>, - - #[export] - #[init(val = 0)] - radius: i32, - - level: Option>, - - base: Base, -} - -#[godot_api] -impl INode for Gatherer { - fn ready(&mut self) { - self.level = find_in_parents(self.to_gd()); - self.actor - .as_ref() - .expect("getting Actor") - .signals() - .turn_ended() - .connect_other(self, |this, action| this.on_turn_end(action)); - } -} - -#[godot_api] -impl Gatherer { - fn on_turn_end(&self, _action: GString) -> Option<()> { - let coords = self.grid.clone()?.bind().get_coords(); - if let Some((item, count)) = self.try_gather_tile(coords) { - godot_print!("Gathered {count} x {:?}", item); - } - Some(()) - } - - fn try_gather_tile(&self, coords: Vector2i) -> Option<(ItemKind, i32)> { - let mut fg = self.level.clone()?.bind().get_fg(); - // TODO: This is a horrible way to handle this - if get_custom_data_bool(&fg, coords, "is_berry") { - let source_id = fg.get_cell_source_id(coords); - let alternative_tile = fg.get_cell_alternative_tile(coords); - let new_atlas_coords = fg.get_cell_atlas_coords(coords) + Vector2i::RIGHT; - fg.set_cell_ex(coords) - .source_id(source_id) - .alternative_tile(alternative_tile) - .atlas_coords(new_atlas_coords) - .done(); - return Some((ItemKind::Blueberry, 1)); - } - None - } - #[signal] - fn gathered(item: ItemKind, count: i32); + fn coords_set(old: Vector2i, new: Vector2i); } #[derive(Debug, GodotClass)] @@ -190,6 +138,10 @@ impl INode for Mover { fn ready(&mut self) { self.grid = find_in_parents(self.to_gd()); self.target_coords = self.get_grid().bind().get_coords(); + self.get_grid() + .signals() + .coords_set() + .connect_other(self, |this, _old, new| this.on_grid_coords_set(new)); } fn process(&mut self, delta: f64) { @@ -216,12 +168,12 @@ impl Mover { #[func] pub fn get_grid(&self) -> Gd { - self.grid.clone().unwrap() + self.grid.clone().expect("Getting Grid for Mover") } #[func] pub fn get_target_pos(&self) -> Vector2 { - self.target_coords.cast_float() * self.get_grid().bind().grid_size + self.get_grid().bind().coords_to_world(self.target_coords) } #[func] @@ -240,7 +192,7 @@ impl Mover { #[func] pub fn try_move(&mut self, dir: Vector2i) -> bool { - let start_coords = self.target_coords; + let start_coords = self.get_grid().bind().get_coords(); let target_coords = start_coords + dir; if !self.can_move(dir) { @@ -253,6 +205,26 @@ impl Mover { true } + #[func] + pub fn try_move_instant(&mut self, dir: Vector2i) -> bool { + if !self.try_move(dir) { + return false; + } + let start_coords = self.get_grid().bind().get_coords(); + self.get_grid().bind_mut().set_coords(start_coords + dir); + true + } + + fn on_grid_coords_set(&mut self, coords: Vector2i) { + // Warning! + // Calling self.get_grid().set_coords() would cause infinite recursion. + if self.is_moving { + self.is_moving = false; + self.target_coords = coords; + self.signals().finished_moving().emit(coords); + } + } + #[signal] fn started_moving(from_coords: Vector2i, dir: Vector2i); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 0f73da5..983f022 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -2,7 +2,8 @@ use godot::prelude::*; pub struct VelhoExtension; -mod overworld; +mod gathering; +mod grid; mod turn; mod utils; diff --git a/rust/src/turn.rs b/rust/src/turn.rs index 94307ad..d39f8d0 100644 --- a/rust/src/turn.rs +++ b/rust/src/turn.rs @@ -54,8 +54,12 @@ impl TurnManager { fn start_round(&mut self) { self.unregister_deleted(); + self.current_actor = None; self.round_queue = self.new_round(); - self.start_next_turn(); + if !self.round_queue.is_empty() { + self.base_mut().propagate_call_ex("on_round_start").done(); + self.start_next_turn(); + } } fn start_next_turn(&mut self) { @@ -77,7 +81,12 @@ impl TurnManager { } } - fn on_actor_turn_end(&mut self, _action: GString) { + fn on_actor_turn_end(&mut self, action: GString) { + let actor = self.current_actor.clone(); + self.base_mut() + .propagate_call_ex("on_turn_end") + .args(&varray![actor, action]) + .done(); self.start_next_turn(); } } diff --git a/rust/src/utils.rs b/rust/src/utils.rs index 48cc39c..8181570 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -15,29 +15,33 @@ where None } -// /// Try to find a child of type `T` with the name `T::class_name()` -// pub fn find_by_class_name_in_children(parent: Gd) -> Option> -// where -// T: Inherits, -// U: Inherits, -// { -// parent -// .upcast::() -// .try_get_node_as::(&T::class_name().to_string()) -// } +/// Try to find a child of type `T` with the name `T::class_name()` +pub fn find_by_class_name_in_children(parent: Gd) -> Option> +where + T: Inherits, + U: Inherits, +{ + parent + .upcast::() + .try_get_node_as::(&T::class_name().to_string()) +} -// /// Try to find a child of type `T` by iterating over children. -// /// -// /// Returns only the first result. -// pub fn find_by_type_in_children(parent: Gd) -> Option> -// where -// T: Inherits, -// U: Inherits, -// { -// for child in parent.upcast::().get_children().iter_shared() { -// if let Ok(result) = child.try_cast::() { -// return Some(result); -// } -// } -// None -// } +/// Try to find a child of type `T` by iterating over children. +/// It first checks for a child with the name of `T::class_name()` before iterating. +/// +/// Returns only the first result. +pub fn find_by_type_in_children(parent: Gd) -> Option> +where + T: Inherits, + U: Inherits, +{ + if let Some(found) = find_by_class_name_in_children::(parent.clone()) { + return Some(found); + } + for child in parent.upcast::().get_children().iter_shared() { + if let Ok(result) = child.try_cast::() { + return Some(result); + } + } + None +}