From 471d425b231e8e45f1e19a50927873d5c8f7a8cf Mon Sep 17 00:00:00 2001 From: adtpdn Date: Mon, 4 Nov 2024 17:25:09 +0800 Subject: [PATCH] Update --- .vscode/settings.json | 3 + addons/enhanced_gridmap/enhanced_gridmap.gd | 17 + .../enhanced_gridmap/enhanced_gridmap_dock.gd | 25 +- .../enhanced_gridmap/meshlibrary/default.tres | 45 +- assets/models/pboard/AdjacentRect.tres | 4 + assets/models/pboard/HighlightRect.tres | 4 + assets/models/pboard/SelectRect.tres | 4 + assets/models/tiles/tile_diamond.tres | 17 +- assets/textures/Adjacent.png | Bin 0 -> 1950 bytes assets/textures/Adjacent.png.import | 34 + assets/textures/Hilight.png | Bin 0 -> 1742 bytes assets/textures/Hilight.png.import | 34 + assets/textures/Selected.png | Bin 0 -> 1741 bytes assets/textures/Selected.png.import | 34 + .../item_tiles.png | Bin 0 -> 4060 bytes .../item_tiles.png.import | 34 + .../tile_coin.tres | 7 + .../tile_diamond.tres | 7 + .../tile_heart.tres | 7 + .../tile_null.tres | 4 + .../tile_star.tres | 7 + .../tiles_atlas.tres | 4 + .../tiles_hologram.png | Bin 0 -> 7210 bytes .../tiles_hologram.png.import | 34 + .../tiles_null.png | Bin 0 -> 1800 bytes .../tiles_null.png.import | 34 + scenes/mai4284.tmp | 186 +++ scenes/main.gd | 429 ++++--- scenes/main.tscn | 878 +++++++++++++- scenes/player.gd | 1051 +++++++++++------ 30 files changed, 2319 insertions(+), 584 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 assets/models/pboard/AdjacentRect.tres create mode 100644 assets/models/pboard/HighlightRect.tres create mode 100644 assets/models/pboard/SelectRect.tres create mode 100644 assets/textures/Adjacent.png create mode 100644 assets/textures/Adjacent.png.import create mode 100644 assets/textures/Hilight.png create mode 100644 assets/textures/Hilight.png.import create mode 100644 assets/textures/Selected.png create mode 100644 assets/textures/Selected.png.import create mode 100644 assets/textures/player_board_and_blue_print/item_tiles.png create mode 100644 assets/textures/player_board_and_blue_print/item_tiles.png.import create mode 100644 assets/textures/player_board_and_blue_print/tile_coin.tres create mode 100644 assets/textures/player_board_and_blue_print/tile_diamond.tres create mode 100644 assets/textures/player_board_and_blue_print/tile_heart.tres create mode 100644 assets/textures/player_board_and_blue_print/tile_null.tres create mode 100644 assets/textures/player_board_and_blue_print/tile_star.tres create mode 100644 assets/textures/player_board_and_blue_print/tiles_atlas.tres create mode 100644 assets/textures/player_board_and_blue_print/tiles_hologram.png create mode 100644 assets/textures/player_board_and_blue_print/tiles_hologram.png.import create mode 100644 assets/textures/player_board_and_blue_print/tiles_null.png create mode 100644 assets/textures/player_board_and_blue_print/tiles_null.png.import create mode 100644 scenes/mai4284.tmp diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5563753 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "godotTools.editorPath.godot4": "c:\\Users\\danchie\\Documents\\Godot_v4.3\\Godot_v4.3-stable_win64.exe" +} \ No newline at end of file diff --git a/addons/enhanced_gridmap/enhanced_gridmap.gd b/addons/enhanced_gridmap/enhanced_gridmap.gd index 59faad9..7c220ec 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap.gd @@ -32,6 +32,7 @@ enum Direction { var diagonal_movement: bool = false + class NeighborInfo: var position: Vector2i var direction: Direction @@ -430,6 +431,22 @@ func _on_mesh_library_changed(): validate_item_indices() if auto_generate: generate_grid() + _update_cell_option_buttons() + +func _update_cell_option_buttons(): + if not mesh_library: + return + + var item_list = mesh_library.get_item_list() + + for x in range(columns): + for z in range(rows): + var position = Vector3i(x, 0, z) + var cell_item = get_cell_item(position) + if cell_item != -1 and cell_item < item_list.size(): + set_cell_item(position, cell_item) + else: + set_cell_item(position, 0) func _set(property, value): if property == "mesh_library": diff --git a/addons/enhanced_gridmap/enhanced_gridmap_dock.gd b/addons/enhanced_gridmap/enhanced_gridmap_dock.gd index 5c89657..731c69f 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap_dock.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap_dock.gd @@ -152,6 +152,7 @@ func set_enhanced_gridmap(gridmap: EnhancedGridMap): if enhanced_gridmap: if enhanced_gridmap.grid_updated.is_connected(_on_grid_updated): enhanced_gridmap.grid_updated.disconnect(_on_grid_updated) + enhanced_gridmap = gridmap if enhanced_gridmap: @@ -193,7 +194,7 @@ func _update_grid_ui(): var item_list = enhanced_gridmap.mesh_library.get_item_list() var current_floor = floor_spin.value as int - + for z in range(enhanced_gridmap.rows): var row_container = HBoxContainer.new() row_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL @@ -204,7 +205,7 @@ func _update_grid_ui(): var cell_container = VBoxContainer.new() cell_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL cell_container.size_flags_vertical = Control.SIZE_EXPAND_FILL - + var coord_label = Label.new() coord_label.text = "(%d,%d,%d)" % [x, current_floor, z] coord_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER @@ -216,9 +217,14 @@ func _update_grid_ui(): option.set_meta("grid_position", Vector3i(x, current_floor, z)) for i in range(item_list.size()): option.add_item(enhanced_gridmap.mesh_library.get_item_name(item_list[i]), i) + + # Ensure the selected item in the OptionButton corresponds to the current cell item var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, current_floor, z)) - if cell_item != -1: # Changed from INVALID_CELL_ITEM to -1 + if cell_item != -1 and cell_item < option.get_item_count(): option.select(cell_item) + else: + option.select(0)# Select the first item if the cell is empty + option.item_selected.connect(_on_cell_item_selected.bind(option)) option.size_flags_horizontal = Control.SIZE_EXPAND_FILL option.size_flags_vertical = Control.SIZE_EXPAND_FILL @@ -239,10 +245,11 @@ func _update_grid_ui(): 16: rotation_option.select(2) 22: rotation_option.select(3) rotation_option.item_selected.connect(_on_cell_rotation_changed.bind(rotation_option)) - + cell_container.add_child(rotation_option) row_container.add_child(cell_container) cell_options.append(option) + enhanced_gridmap._update_cell_option_buttons() func _update_astar_ui(): start_x_spin.max_value = enhanced_gridmap.columns - 1 @@ -273,6 +280,9 @@ func _on_floors_count_changed(value): func _on_floor_changed(value): if enhanced_gridmap: _update_grid_ui() + _update_astar_ui() + _update_item_state_ui() + enhanced_gridmap.update_grid_data() func _on_auto_generate_toggled(button_pressed): if enhanced_gridmap: @@ -321,7 +331,8 @@ func _on_fill_pressed(): func _on_cell_item_selected(index: int, option: OptionButton): var position = option.get_meta("grid_position") if enhanced_gridmap: - enhanced_gridmap.set_cell_item(position, index) + if index >= 0 and index < enhanced_gridmap.mesh_library.get_item_list().size(): + enhanced_gridmap.set_cell_item(position, index) func _on_find_path_pressed(): if enhanced_gridmap: @@ -360,12 +371,14 @@ func _on_non_walkable_item_changed(value): func _on_grid_updated(): update_ui() + enhanced_gridmap._update_cell_option_buttons() func _on_cell_rotation_changed(index: int, option: OptionButton): var position = option.get_meta("grid_position") var rotation_value = option.get_item_id(index) if enhanced_gridmap: - enhanced_gridmap.set_cell_rotation(position, rotation_value) + if index >= 0 and index < 4: + enhanced_gridmap.set_cell_rotation(position, rotation_value) func _on_swap_items_pressed(): if enhanced_gridmap: diff --git a/addons/enhanced_gridmap/meshlibrary/default.tres b/addons/enhanced_gridmap/meshlibrary/default.tres index c8c096f..94b5d2d 100644 --- a/addons/enhanced_gridmap/meshlibrary/default.tres +++ b/addons/enhanced_gridmap/meshlibrary/default.tres @@ -1,14 +1,53 @@ -[gd_resource type="MeshLibrary" load_steps=14 format=4 uid="uid://54tpx8cmksfc"] +[gd_resource type="MeshLibrary" load_steps=17 format=4 uid="uid://54tpx8cmksfc"] [ext_resource type="ArrayMesh" uid="uid://dqguomxd16u0i" path="res://assets/models/meshes/start.res" id="1_xdwel"] [ext_resource type="ArrayMesh" uid="uid://dspusnbkr74hg" path="res://assets/models/meshes/hover.res" id="2_5gp4i"] -[ext_resource type="ArrayMesh" uid="uid://dr80txgr61irt" path="res://assets/models/tiles/tile_diamond.tres" id="3_gqbid"] [ext_resource type="Material" uid="uid://bsyh0x4cy5qyr" path="res://assets/models/meshes/end.tres" id="3_qi66w"] +[ext_resource type="Texture2D" uid="uid://dpkx1a780pvwv" path="res://assets/textures/tile_diamond.png" id="3_xej11"] [ext_resource type="ArrayMesh" uid="uid://d4himvyb81in8" path="res://assets/models/meshes/non-walkable.res" id="4_h83ju"] [ext_resource type="ArrayMesh" uid="uid://bgvropltcot0q" path="res://assets/models/meshes/normal.res" id="5_san4u"] [ext_resource type="ArrayMesh" uid="uid://36tgon3b60db" path="res://assets/models/tiles/tile_heart.tres" id="6_r6sve"] [ext_resource type="ArrayMesh" uid="uid://b5ta7tcw0iscd" path="res://assets/models/tiles/tile_coin.tres" id="9_44311"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2vf4e"] +resource_name = "boost" +transparency = 1 +cull_mode = 2 +albedo_color = Color(0.91, 0.91, 0.91, 0.45098) +albedo_texture = ExtResource("3_xej11") + +[sub_resource type="ArrayMesh" id="ArrayMesh_0hihf"] +_surfaces = [{ +"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), +"format": 34896613377, +"index_count": 36, +"index_data": PackedByteArray("BwAEAAUABwAGAAQABQACAAMABQAEAAIAAAAEAAYAAAACAAQABQABAAcABQADAAEAAgABAAMAAgAAAAEAAQAGAAcAAQAAAAYA"), +"name": "boost", +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 8, +"vertex_data": PackedByteArray("AAD/////AAAAAP7/AAAAAP///////wAA///+/wAAAAD//wAA//8AAP//AAAAAAAAAAAAAP//AAAAAAAAAAAAAA==") +}] +blend_shape_mode = 0 + +[sub_resource type="ArrayMesh" id="ArrayMesh_3eode"] +resource_name = "tile_diamond" +_surfaces = [{ +"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), +"attribute_data": PackedByteArray("sPss5W0hot47+9DosPv6720hXCE7+6/6sPvl75Heot6r9qfksPu0+pHeXCHM5KfkSvvl78X6sfqr9kDkSvu0+sX6tuTM5EDkSvss5c7ksfrU+tDoSvv6787ktuTU+q/6"), +"format": 34896613399, +"index_count": 36, +"index_data": PackedByteArray("FgANABAAFgATAA0AEQAIAAsAEQAOAAgAAAAMABIAAAAGAAwADwADABUADwAJAAMABwAEAAoABwABAAQABQAUABcABQACABQA"), +"material": SubResource("StandardMaterial3D_2vf4e"), +"name": "tile_coin_diamond", +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 24, +"vertex_data": PackedByteArray("AAD//////78AAP//////vwAA/////6oqAAD+/wAAAAAAAP7/AAD/vwAA/v8AAKoq/////////7//////////v//////////////+/wAAAAD///7/AAD/v////v8AAP////8AAP///7///wAA////P///AAD///////8AAAAAAAD//wAAAAD/P///AAAAAP//AAAAAP///78AAAAA////PwAAAAD//6oqAAAAAAAAAAAAAAAAAAD/PwAAAAAAAKoq/////////39U1VTV/7//v////39U1VTV/////////3//v/9//7//v////3//v/9//////wAA/3//v/9//7//vwAA/3//v/9//////wAA/39U1VTV/7//vwAA/39U1VTV") +}] +blend_shape_mode = 0 +shadow_mesh = SubResource("ArrayMesh_0hihf") + [sub_resource type="PlaneMesh" id="PlaneMesh_ti6kf"] material = ExtResource("3_qi66w") size = Vector2(1, 1) @@ -111,7 +150,7 @@ item/9/shapes = [] item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/9/navigation_layers = 1 item/10/name = "tile_diamond" -item/10/mesh = ExtResource("3_gqbid") +item/10/mesh = SubResource("ArrayMesh_3eode") item/10/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.9, 0) item/10/shapes = [] item/10/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) diff --git a/assets/models/pboard/AdjacentRect.tres b/assets/models/pboard/AdjacentRect.tres new file mode 100644 index 0000000..5f52899 --- /dev/null +++ b/assets/models/pboard/AdjacentRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://dasaeaytvhll0"] + +[resource] +load_path = "res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.ctex" diff --git a/assets/models/pboard/HighlightRect.tres b/assets/models/pboard/HighlightRect.tres new file mode 100644 index 0000000..bbc1198 --- /dev/null +++ b/assets/models/pboard/HighlightRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://c2bj21abtgda1"] + +[resource] +load_path = "res://.godot/imported/Hilight.png-1eaa7d98891b6551494fa706d4935a8a.ctex" diff --git a/assets/models/pboard/SelectRect.tres b/assets/models/pboard/SelectRect.tres new file mode 100644 index 0000000..d196917 --- /dev/null +++ b/assets/models/pboard/SelectRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://0wjk16jlgfq"] + +[resource] +load_path = "res://.godot/imported/Selected.png-8654749fa19cfb113e47fc569bbeed01.ctex" diff --git a/assets/models/tiles/tile_diamond.tres b/assets/models/tiles/tile_diamond.tres index b593302..8960223 100644 --- a/assets/models/tiles/tile_diamond.tres +++ b/assets/models/tiles/tile_diamond.tres @@ -1,4 +1,4 @@ -[gd_resource type="ArrayMesh" load_steps=4 format=4 uid="uid://dr80txgr61irt"] +[gd_resource type="ArrayMesh" load_steps=3 format=4 uid="uid://dr80txgr61irt"] [ext_resource type="Texture2D" uid="uid://dpkx1a780pvwv" path="res://assets/textures/tile_diamond.png" id="1_fck33"] @@ -9,20 +9,6 @@ cull_mode = 2 albedo_color = Color(0.91, 0.91, 0.91, 0.45098) albedo_texture = ExtResource("1_fck33") -[sub_resource type="ArrayMesh" id="ArrayMesh_vxvvp"] -_surfaces = [{ -"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), -"format": 34896613377, -"index_count": 36, -"index_data": PackedByteArray("BwAEAAUABwAGAAQABQACAAMABQAEAAIAAAAEAAYAAAACAAQABQABAAcABQADAAEAAgABAAMAAgAAAAEAAQAGAAcAAQAAAAYA"), -"name": "boost", -"primitive": 3, -"uv_scale": Vector4(0, 0, 0, 0), -"vertex_count": 8, -"vertex_data": PackedByteArray("AAD/////AAAAAP7/AAAAAP///////wAA///+/wAAAAD//wAA//8AAP//AAAAAAAAAAAAAP//AAAAAAAAAAAAAA==") -}] -blend_shape_mode = 0 - [resource] resource_name = "tile_diamond" _surfaces = [{ @@ -39,4 +25,3 @@ _surfaces = [{ "vertex_data": PackedByteArray("AAD//////78AAP//////vwAA/////6oqAAD+/wAAAAAAAP7/AAD/vwAA/v8AAKoq/////////7//////////v//////////////+/wAAAAD///7/AAD/v////v8AAP////8AAP///7///wAA////P///AAD///////8AAAAAAAD//wAAAAD/P///AAAAAP//AAAAAP///78AAAAA////PwAAAAD//6oqAAAAAAAAAAAAAAAAAAD/PwAAAAAAAKoq/////////39U1VTV/7//v////39U1VTV/////////3//v/9//7//v////3//v/9//////wAA/3//v/9//7//vwAA/3//v/9//////wAA/39U1VTV/7//vwAA/39U1VTV") }] blend_shape_mode = 0 -shadow_mesh = SubResource("ArrayMesh_vxvvp") diff --git a/assets/textures/Adjacent.png b/assets/textures/Adjacent.png new file mode 100644 index 0000000000000000000000000000000000000000..6193129c4f1f00bd9743f79896f6407d3017de8b GIT binary patch literal 1950 zcmb_dO>Epm6yDIPlvJr&sTT?Y%Pk0KXFdM^QB6p8Lv|%Ljgl1!w~WW*T`Oykv7PK@ zPYCD%P8En7m)Z$?|tvR zZ)VKfdI;yQi|{(vptOy~B*uYS zqG%E#%a?W`jZr}kL}$&tgh^{G<2xy3OS>TRT#-%UR8mHAo;Eq}j2pE&mMl~%MPn@C znT;^^c{h7@>Kj%iIdeq?D;mNEQjDgoJF@90`UPw`7!RQh?uWtNG}J`cY67l+;=7>W z8lU9kKfykA0-i<$atHr!>PwvPGZXHRab=il*7<>JjK&UAbW^lOGk#S!N`*>tv|1Q^3&UV{fW~rlxB{en*4n*^Q-mU{LNdP o8*cCYcie{_wVe1j{o$*Z-`sz$b3J^cR-B;qrIqUb;@0bb0b;9T`~Uy| literal 0 HcmV?d00001 diff --git a/assets/textures/Adjacent.png.import b/assets/textures/Adjacent.png.import new file mode 100644 index 0000000..ca2b319 --- /dev/null +++ b/assets/textures/Adjacent.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://68x88jj25yxg" +path="res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/Adjacent.png" +dest_files=["res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/Hilight.png b/assets/textures/Hilight.png new file mode 100644 index 0000000000000000000000000000000000000000..041b6e3696ffbd3ecf150699f53b0e6302464021 GIT binary patch literal 1742 zcmbVNPl()99F7I;w%Q^hJ+z>Y?7_Bcl9$XRnLImoca!bzXlJ`jM>>Lqee>SSOxQ_Y zOtL$(1InU!@Fa+y>p?*;;>nBDQVsW0=dQ`y$V8Irub_r34; z{rQglc~Kh7HCO2b-EX0vcWRYWUU}7%YS}zMFs&a%NNWlti~>D2P^%A zo$s&KNq>VlR6hMOIMqXfAY>T^y|5Fds8^N;yhx1mX-x(LNVZXy7jlE3QC$NrPZ%&& zOCfsE0Jfv*7Ici_i@<=otwCGU3kuW`v{1nTqn|9SCDcbX@65=Scq_~8EQ^t*b-P`) zTTpq@(sajhG-zmsp$LSMZbupJDN#B*X7E@_k|53k9)X+@H~D5(mW9%x3t>E=jnYw= zM8LEjjx}9{xl02eB@D2xXm-3w)sP-C(92Q5TUJBCpLD~ z5{45KX|}W_+!zI9S9Dt6j+s_tDc?*8TiOybXLE02^TAh%jYl_zsba3DcZiJ_;%4!n%FlLSZMksLUhu^!q6aT z$m3))uY!F4@IX*b1jl`O1&dN_;DTcNc1fXj5h^9qbd-|bG!5G-TFfA0wsT1!&Lr+k zv*xO(U?iqPY`?@5J5K>E6$=WcqV|hM2^-KR7G*H6{GqOuAQfre9-XE0?9I`r6M#Ye zAWZUeQI<(w5RA&B>0p<5?8)+If49v9=_9ISXg%eA*2M{1Xo=YEr4Y4;=}+<2qt)*% zn?qUC>US;N|EYcy9MZ;7i-}gN$+(b@9eRux)_3qan&CpNY?%lps2ih-JPRzYKc$v3U$qg51?UqG3%xj{Xoguj*GnPV#s%x)R+u>4AK&e9Z0I}OhE@mlw1V5=${@p+ z25U_;*hZGmojc1e^=wKI;{vk1I7)K6=Ws(_n~uwAkzA2aZ=0}63cc{#T(wo$-WEd7CYZ4OeC#tb8nXOdH#F*^q zjWF>^H-Bbo4|ZXJ9Zm+a$^)I3^`@lRl3~l*8DQD~jG%Smhe3ZDYVbfCLKR!l?}O5+ z@nHe~6YL{9AXyBl&tVK(SWJ@^$4(+?S4c!MYM821rsr#wN+Tmd7}14%{o;AHR;}og zrBm^OG?ZJf+qEPwV1jVXbvPOyAq;)n(x8k3Q{w~R$-FMBh_|4s^MUSplIdY21tWLq zewUz5Sq0_((Sh&@q8#_+0nPJG6Dho@VOs6JD)E*AO&%DEr6TBQ9-gRqE(__IgwZr> zsmiB}ngR@<>mF~KhQ_Nv4R{CwnOC7M1qMPI!b(~B!(y^m!knhLKR!#B@Jr)S6tctm zu^}qYg~Oq;Ah6Gkr^5r{aVX2<{oOXEqz|c*k@cJeMHgmxxkY1lm_igEq(6r{4_AM< zY>s42t3R-C|EKzKa8Mg2ElgXj$d&$xWm6iZM*MfyhHFy|Y#&a$VmX|&WBM^^=s2O& z8Ew}K#?^V+>iac!xw-lJ?>E1iy9^$6fBJCs`ti@Moqp?`=YO8Lur))rKHZ%;;l8q( zKYg{fcssxH+F!FbuDQ_@yHDNN*qRl-xb^sNcV7Hx_m{7gzZ-WtzkdA58?)?X=8=1k zZYDrc`K?#~0X1PJ Aw@q2&=BB$hx8dIaChaWd)X97Dd+;*NfE; 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 O0000JC1Vlihe1M2S zieCaKAcQ0&KoZiE%k^Himznwg?>oD9dw08cdod6m*xc^y%)HP0^fs%U@FU$c4SXg* zQGsJGoCX7*4TKcfpc%x)Fa>f7U}C?4X_`>EzHaI;6a$K)h71 zK_Y6%n<>^m$flWsY*dwj_qoVAY~?`;3`ZyZ-tJK`=`fdkuVs$MLlJJiH22N2-sjkA zek2M2At|w7+lb?WI20zRHYLp%>u-hv!`DzoTU#0Vg_(zxMv5m!231@uaEVV46y)N& zAe^FE1p1^_%>~2lv5L?69^6g&PC7$lJL$#7~o2xDv-L!~sQK^|&k_6o}E({Oaz zjTkp%Evx1_xUXRNzQyOuzFLc$mQ1pAeY9&w`L4)bg@cMt#b}_a8opWbI~?i!vUDN2 zz%<7;C)yxF7D|G#LMG-<_#P(vz63Q4TvPrm9_lz7oyi?T&Z@Cb$A9@QhoOhyH|#jX zbt2vkFB|y2RGWw!%3nlZz=z$TH_;Q@fdUAmNahA87{gaj?PXKzgZr{noYff ztEt&5=Kw{?@r8m-ozEea2;&gvnV4xi8VgIF#e-evqFZl}XE;?iZm#?VR4oZLL3~mQ z=GsrgJ9tWJNs+S@w^cucXru>kw?7GW4BIN3Xs-96>7Wwa@=XS!^*a9X zVI(&e<8TnY@p`=1@eo$wx7?f^Q=La(iv3V@>3ih&XZsdlf}QakCD(N5U$66B=T@#c1DChCNf_cwlh~XM87)U41$VfgG{juZpIDE*5j6Ew$fk{3xiZiQJO?fLN!zTDf-t0oX$>ECxWPI za-gTZ0>LRhJbz~eCX{OhAvTs*mEi(k8k`8w2p{N}hZ~B10fo#mQ#LD77E(=ol(HC( zFFF&Gv_s%l1JbJ%;=u&uh@=N$N{t&AoiiO&c|5*+GlMP#&F%eIwWSLymdvNB$$XbY zNdM{e-m6$jyi9de766gN76~U-cI5h}9XBEoa)8MD~ zsj$yNg)$8l>Qq#jlSl(MT*Sdmn`oLLN;-)m1eIzarHJ?(XPbxluG0|J%dpYjho*{c zP#jy(xqBTNyPMEwbfP)AZ4?3xBdF79!<|1m3UTJIu}B0jzSWGYPMm z2VfUn_4TLBk|JvGM1h!QY830Fu-;ZuX)~pGn@*~LLRZ^jU{a_S^*elcc)N**Ug(Ev z&!)iG_FzNvUl`9YGOqXm(gg%*CrJvZaz_?%gyW#$Aub7tkMz!(z=vu@!!7U$wDEIa z4H|a(v7vSsp5FZ}bjA0iW5J=!%4rZp%%V9JtF*!QM;%as` z`7C5nB1E~xOy}i9w%OPY9~o4m(9Y;0Y@u}Py1bRZ$Kbm5D&nI?5NK}2_KpTTy7el= zjlR6==473apr@YOgO;W~8a;|JWmx<-aM7*QXgQ(&qC@8)pf-<@`tx}6H@(Cgp zc9}?)r|?!Rghfw%3?rw#$rC6JJ1kKq)0Yc5?OCJ=fv+$gd6FSM!lB&Q#;}rRxw0#)%B| zo+}8X>=G%1wm3!cqj5$;28xOzI4M~=aJM+`9<ew%^?_qLB>iwiHYB=jKu)c92- zQXP_E@`qxVM}8F<;ZJJ25)XPtQz z$JU=}#AX;0>vDK-RQd7rdOoS1w20`5_u)5h+=MrGK9{GY z3t2+VE~e#`pbV_u(u?1}u!;Mp)DR&jtv2IiB1Oqk;!tb}n64yDFLj;bD-u&-mUL37 zr5U*5TP^4fjuIT2<2;^*-SJhF=pZF0A@N~YiYe*@1nh3&k;L)k^RZ;+9ZWd{(-eu% zd%IU)YwJ5>2Nk(gEFV6C(2uX!jemdK3>PC*rzwz$@;LJ_Eg=b`6j73V;>CUh)-^`tyq9H`xvukQknLnxl+23JJ`o@LAUCMA&11 znODU|;h17mar3huqcs>JG7;8V(t!w(kjVHcIbKSRONCBV+tY30vKzb5)>~LwG2Sw- z*u=4}uTY}ne34o7N}v=AeBd9%2QCta;YQfT@{NraQ#T5^`4DWzRIv<1MB4G#CInMN z#!ccBlUv1czR0Nn?G0^V%&B5Wzk;tV>Oo8Qcx=x2#HiR-joJ3kGo}&5i9zv@IDxpt z2?8HKJ*S5eJaffF}nNo7AnC{b0!Z4of zCvoayDz5uMFLt#hF+Lcd1Rdo%nW`0HgiK}y$SCGoDAf_AG`|;FizxBwqx5u6(OIa5_7AsMqjE4Ds#_m?JLj~Ysjr)g{J>u>nO%jaX=#wTHRbF0Hl(2-?VV{Pj)tZDiKi8u*!re4MPsW^`Wnd7qq z{VZ4fY)LB)Kdczbo@pKPd?7vO99xU;-n&jp;e}^U!j2t%NG1w5=0ei8u@bm^f=}$Dk%TkPkB@>70LNXN_C7T~-Q}x5mA$;(0 zsGy4JDRZl^WpfWEv&K}+?#KJ@bz#Cp7j`v7t+ad?o!cNbYe=C z7tv@6>pt#=~kpFnVFS;8aEMf8ca}h@c;jG+l!d##CjFY1rEFD#GDDq-YAX zEUFB=b+SSj4|NP3DG{hEN*<4!Z+<6zT?Q#-FfvUX)!81@+~wdzgS6<;%OtxeR7JcEiQ2_z;Orq4eI`x7i;4!*BD z)P?;C8H=N-f>@t{i8nzUG3mlOp;h|a4|ZudsHUh$ZkoXgNUGqAOxgUhr9TOltFkvH zYbZ*}%Bs_68hRDW40hI&8c|5T#abnT-#uE);o&m@bReQ~4Dl)?Uo=@>Fio#4lgnDP zBovJ-i{vzI{1~Mah;BvtW_kq!$r9L|^-#ucbfvE`B!QGqX&fg%I#wgVGSakQTi)nG zGMutX!I^o#VVw>oJ=SO)RtEl>nF2Daiz9S(ia3?|&#KD+aO0C~&9*gF`{b#nZeuHDRIhV%C3 z^8;1PF^g5k+I{9}lma_Jp9J_%pNqqHKLh`~SvkKSZG>qEn5rMa@;eZm+6<%WHQ4-L zXThp!*hyAEri_zt`-?u}5rd+|m!j#Rza#k3HfW{Z5$6n!;EjS&!g&ZKqKKLcrV^t_^SqyjY1CXNvY6TpDYvJ%- zKsgLBs1kPwz@_@o%W$B-@<=!*pMYBbEr`~?f@I&%*zoMnxyGkSAJMPV+^osc8<~AU zq*iT$=lm1U{j0wsy7Ijd=Z`5tU6XEsuGL^-<5%DgE|=tS|&YzTxMh_rdpKCK9)6BBUtUW%~i3^-a(XC%-va* zVQAON(b&Ej4Yw^s@YT2TUOK7`5-s;o>B&@;+a+_KUajfZJ-(N@ifzqJ#i5-2A! zT(e^Pt>PUzYVSeJdkz>&%E_`MiDPGqp{8>&Ynm%P_QsZsKgOnTq!i7&i_kbT2KUS^ z_&#c-s$BqM7=a1}TZtbPKfWE#IcGp)%IAqIaug@=;XkqI?(fmgg$9Xp&?KC6|4-m> z(KFH3l*EZoe<|APOR#5p0td|KL10rWjA#uSW*&;3);DslIV29s$u%>9NZ=%NS1yu+ z2?k$GD42w5d|9c7sf*T%7*ry*KBg<>N!Z;zDA&7C)1@HMSb}<=AISrvaC@f>odGTo zRQ9)O9(xFmd8b>&2L%=`6yBnPj>8x3`XgKwW%69_#A=+p^e#Aysoq5l)rpV8-G$0j z531TUgqllHU+RNCy&rz11OB3l{OgW|n3x!An(_cLbuWROHCbjOp){G@n{4|qk+%pe zh6Re~4TB4rfyZ>dU<_r;3@d;eyMio>7IAS)30G1QuTnb^7P5x=~hP zOmtWTKCX%xnD^615STR+C){x_>~@ztLyX@keiEr7A&FF`Q?;5L=xVP-Q>_bX9Xlds zXxM6lFs7Ri7oUuT<6t=A*)vUISW1z0NS9-rs+@F{BY286?k2`zR8|a~9pqey64p?R zPOTd5;%)?t)Q|;bHNYr?kj-3RV=cSr@++Ce$yEFPM&yGr8;8NtGt<$rDPtWu6PQNMP%YJx zWe;79-&$jMLKVe8k?9a6%qTof9jGOfbn1VfzX$$d6*@7crkQb)XYhD7!#t-P%X?8> zB8n7YId&%p+cNlAB4tR05JRPO9)e-XVKb8sQx2B;n%gibtYFWsBD881=-s{tV-qM( zi85L_hEgrJ6C*Xudf5@nJI ztfxdrg7b)jWc}J&QyIWV6AUwCT`OHrG6%y59#2MS3;otTQvx45>pSJ#G-EeUQ#K>vJ(P(txP0~S_CA?oAzfA?)vU^9c4VS@oYuUrAb?>?i4mb!c>QY#t$USt7;@Uo zHe_Z}!5cUI7~7Yx9Ka_@B1Ncf$uiN(^^U9SiHN3y7@x0Le8QV6QtyGE38~fzrT?IdD!tTt1eiFqJwoDbHc2*QU@q;| zJzQz_2$CgC1b|NU~P;XN=MrRbS+ zGu13MWDP52vE|2-k$T7VOJH_)K@%#j3#VkjMHP3EDRwhGqewSydUPu|6r+JYG3{>| zXfdN0S8Y@?6}^A{7dq}OESlF;o2cuIR%_N#+I$Jjs<&CnD2Kyw3|!SO(8X_KEVP9P zM98TMXcdQ%n)DR3w=3g?dMOx?V1EnO3Z4<<;1eDX4jTzXMP&3JeeEN( zF1!x|znCx z>tnb-{2lB~E3C*@JdQd04)j!?foUr)8o7XJ#WK1%*n-ZLUnlppVb`KdQSyTa;hHdw z&O%Jv#s>yUrSzon5iUI;rC32&j^Oe2K_eQkzH>~wGn7C|VNFBfePZpGAn85=_R4c% za~(zkG52xPcTn#W{Y^-=e+1i}SK;XXXke437C_7F|3S~>D^arbd3al18^JtN8hc8B z;T;o?M0*$B{qChW<7hz-Jd*@-M4)N7N)RspJk(Sa6W;v}Je_ayeHU%58{HFc zqZevsXN1Dnw+d)~-$G4Dks88ypm)Pgtho3lRDEeS>aINt+DS(u@x=zLJhC>gBj>?2U(to<~-JmPq7`PK0D zyhg&jj=sqY5t{N1cp^(-2GhZ#G7bi1*5ZHdE7tS14vxACxQ;sljzea`=;%Y=<1aw( z2_s*s;5+XeMBiD3=$iKtxZ)!CFFl{F|-%Y?M781rnK#|_`iS!jCt8K?{#T}RA?5$S}Hj1QF{ zg(1Ghxk4Ws*gJ?9U&(lCEmE$75i2?xzOGeB7BS6|E$&moTu?VR|Ppb$MKdMEhersq2*&QF-*q zC_Ck3M(1%jDkmcN{K&j)z>5h-l1y3EiVS4i_Pyyv3?+IWY}*&m4Nsvrp8>6Z74+aX zIlPef+VrU0K85r~Qqd^3-F++E6YAiYI2rK`A0V;2VMHfWvl2iR4xa-(VRhgqxUAF6 z5jP*&wo%eMQ82u|H~1aW#~?;X*!9@RTyA6fm{%sCPG4%o9=vV`OaF;sj46~&<|v<# zsmLH23o|X;4Dcn-aajuGbq$6ann+f}0M+y_R*ZJb9FQi6X%To(TQdri5e*gD1QbJ9 zgQT~fQdUGXpY<%4c=q+wLl4IO1Z#jwkz--$L@`5@EDa4dT8>Kwuxf{F=OQW|A||UWR68z5&!@I07*qoM6N<$g41k$rvLx| literal 0 HcmV?d00001 diff --git a/assets/textures/player_board_and_blue_print/tiles_hologram.png.import b/assets/textures/player_board_and_blue_print/tiles_hologram.png.import new file mode 100644 index 0000000..e37b676 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tiles_hologram.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ncohgicoismp" +path="res://.godot/imported/tiles_hologram.png-f24488bf20b1c49c03f0b2f505381964.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/player_board_and_blue_print/tiles_hologram.png" +dest_files=["res://.godot/imported/tiles_hologram.png-f24488bf20b1c49c03f0b2f505381964.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/player_board_and_blue_print/tiles_null.png b/assets/textures/player_board_and_blue_print/tiles_null.png new file mode 100644 index 0000000000000000000000000000000000000000..504337cb335acbf163909fc057995d1fbc5c9fd3 GIT binary patch literal 1800 zcmbVNOKclO7yYv2RF8qv|Jd^%-XBiJIn4S zcEW)wz#$SRNC5>ZTD1r+MJht7QVx}>Rvf6rv-7~tP$;w~GnyV3*GGfz_It(e;T^dyaoORF9`!<@U1GhfYg=gP z-G@S<&Ofcfq(7N`1`%EjW6FyxT(3F;9SZdi)E!Kwm@gGs$+8pjub*C$C5tBHiAWY? zofIouqjN6H&y5wx+!TpZdEjZOzm5b!mHAkzS1Y!M>Iu2Qi^Mv3tjbaY;!h>yWFRO_ zW^+=CyG)9NqYBXsD8=GoEehh$cv6Bui>V-{YPte61focfORbMA)Ld$!@$_&@OWY;o zvhO=cRcp0cxTc4>TT-=nJgx$$LZ}FY;?3GVt}C|Jy~dDc9&s(lx410@jJU|B{e&!> zHbba7ZCcxFrAZ`Atz$>k!XOB#0i>jjbEe%&L!1(oRalkTz9+C+8|#$0&%H9g19f}* zHUW{^Y__ejsh4WCE#dh?Ga`&uLN-Nvg;|HGlpvG4RV-q*s<^~d$1cfIJCi8IE8G>r!kxDMc_x+0x!klW zVk6CcX#`ugh_9#NG@C^k+w-waSSFp2MQXy9MUhD(kWo!jFw}|)V@98XO^B6fB+5Wk zkHyTG&}h^Pr8$`n8X$PTc@`)qg5w`&pco}Yqq;(3rl}aZ5m$;tj|nzPA*H%5wAR?3 zbuDomab-Pg;ED=Ht&iz37$pjf_L&L*22rpMfmXurX*UC(g-lajBG9EYm8g^N-ByzWv9#rq- z-@`L^cfYl2Hf?Qi|L>mtpYB`9A!Tfrn3%Gv9K@pr^Qc)Gbz{{Ud+TP`8e9y-VA-C; z;-)>znJuVYF{zc#Vn$5)sN@L!b~8cTn4@cH?_0YH&RfB*mh literal 0 HcmV?d00001 diff --git a/assets/textures/player_board_and_blue_print/tiles_null.png.import b/assets/textures/player_board_and_blue_print/tiles_null.png.import new file mode 100644 index 0000000..92e92f8 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tiles_null.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://mg6lr51n2yn7" +path="res://.godot/imported/tiles_null.png-6f85709d461b04e0754de2baef7b18ef.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/player_board_and_blue_print/tiles_null.png" +dest_files=["res://.godot/imported/tiles_null.png-6f85709d461b04e0754de2baef7b18ef.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/scenes/mai4284.tmp b/scenes/mai4284.tmp new file mode 100644 index 0000000..8088b44 --- /dev/null +++ b/scenes/mai4284.tmp @@ -0,0 +1,186 @@ +[gd_scene load_steps=7 format=3 uid="uid://dxn87yj8qnfpp"] + +[ext_resource type="MeshLibrary" uid="uid://54tpx8cmksfc" path="res://addons/enhanced_gridmap/meshlibrary/default.tres" id="1_110wo"] +[ext_resource type="Script" path="res://scenes/main.gd" id="1_xcpe3"] +[ext_resource type="Script" path="res://addons/enhanced_gridmap/enhanced_gridmap.gd" id="2_hbe1v"] +[ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://assets/main-environment.tres" id="4_ky38j"] +[ext_resource type="StyleBox" uid="uid://dlw1ogamn741n" path="res://assets/styles/box_flat.tres" id="5_dvx6y"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cewu"] + +[node name="Main" type="Node3D"] +script = ExtResource("1_xcpe3") +turn_based_mode = false + +[node name="EnhancedGridMap" type="GridMap" parent="."] +mesh_library = ExtResource("1_110wo") +cell_size = Vector3(1, 1, 1) +data = { +"cells": PackedInt32Array(9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 8, 0, 9, 9, 0, 9, 7, 0, 9, 6, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 65536, 0, 7, 65536, 1, 10, 65536, 2, 9, 65536, 3, 9, 65536, 4, 8, 65536, 5, 7, 65536, 6, 9, 65536, 7, 9, 65536, 8, 10, 65536, 9, 8, 65537, 0, 9, 65537, 1, 8, 65537, 2, 10, 65537, 3, 9, 65537, 4, 7, 65537, 5, 10, 65537, 6, 9, 65537, 7, 9, 65537, 8, 10, 65537, 9, 10, 65538, 0, 7, 65538, 1, 10, 65538, 2, 9, 65538, 3, 8, 65538, 4, 9, 65538, 5, 10, 65538, 6, 9, 65538, 7, 8, 65538, 8, 9, 65538, 9, 10, 65539, 0, 9, 65539, 1, 10, 65539, 2, 9, 65539, 3, 10, 65539, 4, 9, 65539, 5, 9, 65539, 6, 10, 65539, 7, 10, 65539, 8, 9, 65539, 9, 9, 65540, 0, 7, 65540, 1, 7, 65540, 2, 7, 65540, 3, 10, 65540, 4, 9, 65540, 5, 7, 65540, 6, 9, 65540, 7, 9, 65540, 8, 7, 65540, 9, 8, 65541, 0, 8, 65541, 1, 7, 65541, 2, 7, 65541, 3, 10, 65541, 4, 10, 65541, 5, 8, 65541, 6, 7, 65541, 7, 7, 65541, 8, 8, 65541, 9, 9, 65542, 0, 10, 65542, 1, 10, 65542, 2, 9, 65542, 3, 7, 65542, 4, 8, 65542, 5, 9, 65542, 6, 10, 65542, 7, 9, 65542, 8, 10, 65542, 9, 9, 65543, 0, 7, 65543, 1, 8, 65543, 2, 10, 65543, 3, 8, 65543, 4, 7, 65543, 5, 10, 65543, 6, 10, 65543, 7, 7, 65543, 8, 10, 65543, 9, 8, 65544, 0, 9, 65544, 1, 9, 65544, 2, 8, 65544, 3, 8, 65544, 4, 8, 65544, 5, 7, 65544, 6, 8, 65544, 7, 9, 65544, 8, 10, 65544, 9, 10, 65545, 0, 10, 65545, 1, 8, 65545, 2, 10, 65545, 3, 8, 65545, 4, 8, 65545, 5, 7, 65545, 6, 9, 65545, 7, 9, 65545, 8, 9, 65545, 9, 9) +} +script = ExtResource("2_hbe1v") +floors = 2 +non_walkable_items = Array[int]([4, 5]) +metadata/_editor_floor_ = Vector3(0, 1, 0) + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 5, 15, 12.36) +environment = ExtResource("4_ky38j") +fov = 35.5 + +[node name="Camera3D200" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 5, 30, 5) +visible = false +environment = ExtResource("4_ky38j") +fov = 35.5 + +[node name="Panel" type="Panel" parent="."] +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -77.0 +offset_top = 6.0 +offset_right = 77.0 +offset_bottom = 59.0 +grow_horizontal = 2 +theme_override_styles/panel = ExtResource("5_dvx6y") + +[node name="PlayerboardUI" type="GridContainer" parent="."] +custom_minimum_size = Vector2(200, 200) +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 30.0 +offset_top = -230.0 +offset_right = 230.0 +offset_bottom = -30.0 +grow_vertical = 0 +columns = 5 + +[node name="ActionMenu" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -145.0 +offset_top = -218.0 +grow_horizontal = 0 +grow_vertical = 0 + +[node name="ActionButtonContainer" type="VBoxContainer" parent="ActionMenu"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="MoveButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Move" + +[node name="GrabButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Grab" + +[node name="PutButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Put" + +[node name="RandomizeButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Randomize" + +[node name="ArrangeButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Arrange" + +[node name="NetworkInfo" type="VBoxContainer" parent="."] +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -58.0 +offset_top = 7.0 +offset_right = 58.0 +offset_bottom = 57.0 +grow_horizontal = 2 + +[node name="NetworkSideDisplay" type="Label" parent="NetworkInfo"] +layout_mode = 2 +text = "Network Side" +horizontal_alignment = 1 + +[node name="UniquePeerID" type="Label" parent="NetworkInfo"] +layout_mode = 2 +text = "Unique Peer ID" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Menu" type="VBoxContainer" parent="."] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -85.0 +offset_top = -33.0 +offset_right = 85.0 +offset_bottom = 33.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 20 + +[node name="Host" type="Button" parent="Menu"] +layout_mode = 2 +theme_override_styles/focus = ExtResource("5_dvx6y") +theme_override_styles/disabled_mirrored = ExtResource("5_dvx6y") +theme_override_styles/disabled = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed = ExtResource("5_dvx6y") +theme_override_styles/hover_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover = ExtResource("5_dvx6y") +theme_override_styles/pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/pressed = ExtResource("5_dvx6y") +theme_override_styles/normal_mirrored = ExtResource("5_dvx6y") +theme_override_styles/normal = ExtResource("5_dvx6y") +text = "Host" + +[node name="Join" type="Button" parent="Menu"] +layout_mode = 2 +theme_override_styles/focus = ExtResource("5_dvx6y") +theme_override_styles/disabled_mirrored = ExtResource("5_dvx6y") +theme_override_styles/disabled = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed = ExtResource("5_dvx6y") +theme_override_styles/hover_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover = ExtResource("5_dvx6y") +theme_override_styles/pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/pressed = ExtResource("5_dvx6y") +theme_override_styles/normal_mirrored = ExtResource("5_dvx6y") +theme_override_styles/normal = ExtResource("5_dvx6y") +text = "Join" + +[node name="MessageInput" type="LineEdit" parent="."] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -210.0 +offset_top = -46.0 +offset_right = 210.0 +offset_bottom = -15.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_styles/focus = SubResource("StyleBoxFlat_1cewu") +theme_override_styles/normal = ExtResource("5_dvx6y") +placeholder_text = "Chat" +alignment = 1 + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = ExtResource("4_ky38j") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[connection signal="pressed" from="Menu/Host" to="." method="_on_host_pressed"] +[connection signal="pressed" from="Menu/Join" to="." method="_on_join_pressed"] +[connection signal="text_submitted" from="MessageInput" to="." method="_on_message_input_text_submitted"] diff --git a/scenes/main.gd b/scenes/main.gd index a4110b7..a9543d4 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -10,18 +10,15 @@ var player_scene = preload("res://scenes/player.tscn") var current_turn_index = 0 @export var players = [] var game_started = false -var max_message_input_char = 51 var max_players = 4 var bots = [] -@export var turn_based_mode: bool = true # Toggle between turn-based and realtime modes -var bot_move_timer: float = 0.0 # Timer for bot movement in realtime mode -const BOT_MOVE_INTERVAL: float = 2.0 # Time between bot movements in realtime mode +@export var turn_based_mode: bool = true +var bot_move_timer: float = 0.0 +const BOT_MOVE_INTERVAL: float = 2.0 -# Bot movement state tracking -var moving_bots = {} # Dictionary to track which bots are currently moving +var moving_bots = {} -# Action State Management enum ActionState { NONE, MOVING, @@ -33,7 +30,6 @@ enum ActionState { var current_action_state = ActionState.NONE -# UI References @onready var action_menu = $ActionMenu @onready var move_button = $ActionMenu/ActionButtonContainer/MoveButton @onready var grab_button = $ActionMenu/ActionButtonContainer/GrabButton @@ -42,6 +38,14 @@ var current_action_state = ActionState.NONE @onready var arrange_button = $ActionMenu/ActionButtonContainer/ArrangeButton @onready var playerboard_ui = $PlayerboardUI +const item_tex = [ + preload("res://assets/textures/player_board_and_blue_print/tile_null.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_heart.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_diamond.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_star.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_coin.tres") +] + func _ready(): multiplayer_peer.peer_connected.connect(_on_peer_connected) multiplayer_peer.peer_disconnected.connect(_on_peer_disconnected) @@ -49,87 +53,132 @@ func _ready(): setup_playerboard_ui() func _process(delta): - if multiplayer.is_server(): - if game_started: - if turn_based_mode: - rpc("sync_turn_index", current_turn_index) - else: - # Handle realtime bot movement - bot_move_timer += delta - if bot_move_timer >= BOT_MOVE_INTERVAL: - bot_move_timer = 0.0 - for bot_id in bots: - if not moving_bots.get(bot_id, false): # Only move if bot isn't already moving - move_bot(bot_id) + if multiplayer.is_server() and game_started: + if turn_based_mode: + rpc("sync_turn_index", current_turn_index) + else: + bot_move_timer += delta + if bot_move_timer >= BOT_MOVE_INTERVAL: + bot_move_timer = 0.0 + var current_bots = bots.duplicate() + for bot_id in current_bots: + if not moving_bots.get(bot_id, false): + move_bot(bot_id) func setup_action_buttons(): move_button.pressed.connect(func(): set_action_state(ActionState.MOVING)) grab_button.pressed.connect(func(): set_action_state(ActionState.GRABBING)) - put_button.pressed.connect(func(): set_action_state(ActionState.PUTTING)) + put_button.pressed.connect(func(): + if local_player_character: + local_player_character.handle_put_action() + set_action_state(ActionState.PUTTING) + ) randomize_button.pressed.connect(func(): set_action_state(ActionState.RANDOMIZING)) - arrange_button.pressed.connect(func(): set_action_state(ActionState.ARRANGING)) + arrange_button.pressed.connect(func(): + if local_player_character and local_player_character.action_points >= 2: + set_action_state(ActionState.ARRANGING) + ) func setup_playerboard_ui(): - # Clear existing children for child in playerboard_ui.get_children(): child.queue_free() - # Setup grid playerboard_ui.columns = 5 - # Create slots for i in range(25): var slot = TextureRect.new() - slot.custom_minimum_size = Vector2(40, 40) + + var highlight_rect = TextureRect.new() + var hr_tex = load("res://assets/models/pboard/HighlightRect.tres") + + var select_rect = TextureRect.new() + var sr_tex = load("res://assets/models/pboard/SelectRect.tres") + + var adjacent_rect = TextureRect.new() + var ar_tex = load("res://assets/models/pboard/AdjacentRect.tres") + + slot.custom_minimum_size = Vector2(36, 36) slot.gui_input.connect(func(event): _on_playerboard_slot_clicked(event, i)) - # Add a colored rectangle as background - var style = StyleBoxFlat.new() - style.bg_color = Color(0.2, 0.2, 0.2, 1.0) - style.border_color = Color(0.4, 0.4, 0.4, 1.0) - slot.add_theme_stylebox_override("panel", style) - playerboard_ui.add_child(slot) + slot.texture = item_tex[0] + playerboard_ui.add_child(slot, true) + + highlight_rect.texture = hr_tex + highlight_rect.size = Vector2(36, 36) + select_rect.texture = sr_tex + select_rect.size = Vector2(36, 36) + adjacent_rect.texture = ar_tex + adjacent_rect.size = Vector2(36, 36) + + slot.add_child(highlight_rect) + slot.add_child(select_rect) + slot.add_child(adjacent_rect) + + slot.get_child(0).hide() + slot.get_child(1).hide() + slot.get_child(2).hide() func set_action_state(new_state): - if not local_player_character: + if not local_player_character or not local_player_character.is_multiplayer_authority() or current_action_state == new_state or local_player_character.action_points <= 0: return - - current_action_state = new_state - # Clear previous highlights + current_action_state = new_state local_player_character.clear_highlights() + local_player_character.clear_playerboard_highlights() match new_state: ActionState.MOVING: local_player_character.highlight_movement_range() ActionState.GRABBING: local_player_character.highlight_adjacent_cells() + if local_player_character.has_item_at_current_position(): + local_player_character.highlighted_cells.append(local_player_character.current_position) + local_player_character.enhanced_gridmap.set_cell_item( + Vector3i(local_player_character.current_position.x, 0, local_player_character.current_position.y), + local_player_character.enhanced_gridmap.hover_item + ) ActionState.PUTTING: - local_player_character.highlight_empty_adjacent_cells() + local_player_character.highlight_occupied_playerboard_slots() ActionState.RANDOMIZING: local_player_character.highlight_random_valid_cells() ActionState.ARRANGING: show_arrangement_ui() + local_player_character.highlight_occupied_playerboard_slots() func update_button_states(): - if not local_player_character: + if not local_player_character or local_player_character.is_in_group("Bots"): + move_button.visible = false + grab_button.visible = false + put_button.visible = false + randomize_button.visible = false + arrange_button.visible = false return - - var can_move = not local_player_character.is_player_moving and not local_player_character.has_performed_action - var can_grab = local_player_character.has_item_at_current_position() - var can_put = local_player_character.has_items_in_playerboard() and not local_player_character.has_item_at_current_position() - var can_randomize = not local_player_character.has_performed_action - var can_arrange = local_player_character.has_items_in_playerboard() - move_button.disabled = not can_move - grab_button.disabled = not can_grab - put_button.disabled = not can_put - randomize_button.disabled = not can_randomize - arrange_button.disabled = not can_arrange + move_button.visible = true + grab_button.visible = true + put_button.visible = true + randomize_button.visible = true + arrange_button.visible = true + + move_button.disabled = local_player_character.is_player_moving or local_player_character.has_performed_action + grab_button.disabled = not local_player_character.has_item_at_current_position() + put_button.disabled = not (local_player_character.has_items_in_playerboard() and not local_player_character.has_item_at_current_position()) + randomize_button.disabled = local_player_character.has_performed_action + arrange_button.disabled = not local_player_character.has_items_in_playerboard() + + func _on_playerboard_slot_clicked(event, slot_index): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: - if current_action_state == ActionState.ARRANGING and local_player_character: - local_player_character.arrange_playerboard_item(slot_index) + if not local_player_character: + return + + match current_action_state: + ActionState.ARRANGING: + local_player_character.arrange_playerboard_item(slot_index) + ActionState.GRABBING: + local_player_character.handle_playerboard_slot_selected(slot_index) + ActionState.PUTTING: + local_player_character.handle_put_slot_selected(slot_index) func update_playerboard_ui(): if not local_player_character: @@ -138,14 +187,20 @@ func update_playerboard_ui(): for i in range(25): var slot = playerboard_ui.get_child(i) var item = local_player_character.playerboard[i] - if item != -1: - # Update slot appearance based on item - slot.modulate = Color(1, 1, 1, 1) - # You can set different colors or textures based on item type - slot.self_modulate = Color(0.5 + (item * 0.1), 0.7, 0.3, 1.0) - else: - slot.modulate = Color(0.5, 0.5, 0.5, 0.5) - slot.self_modulate = Color(1, 1, 1, 1) + + slot.texture = item_tex[0] + + match item: + 7: slot.texture = item_tex[1] + 8: slot.texture = item_tex[2] + 9: slot.texture = item_tex[3] + 10: slot.texture = item_tex[4] + +func update_playerboard_highlights(highlighted_slots: Array): + for i in range(playerboard_ui.get_child_count()): + var slot = playerboard_ui.get_child(i) + if slot.get_child_count() > 1: + slot.get_child(1).visible = highlighted_slots.has(i) func show_arrangement_ui(): if playerboard_ui: @@ -162,7 +217,6 @@ func _on_host_pressed(): add_player_character(1) players.append(1) - # Add bots to fill remaining slots for i in range(2, max_players + 1): add_bot(i) @@ -194,8 +248,15 @@ func add_player_character(peer_id): connected_peer_ids.append(peer_id) var player_character = player_scene.instantiate() player_character.set_multiplayer_authority(peer_id) + + if multiplayer.is_server() and bots.size() > 0: + var bot_to_replace = get_node_or_null(str(bots[0])) + if bot_to_replace: + player_character.current_position = bot_to_replace.current_position + add_child(player_character) player_character.add_to_group("Players", true) + if peer_id == multiplayer.get_unique_id(): local_player_character = player_character update_button_states() @@ -209,7 +270,7 @@ func add_bot(bot_id): @rpc("call_local") func create_bot(bot_id): var bot_character = player_scene.instantiate() - bot_character.set_multiplayer_authority(1) # Set server as authority for bots + bot_character.set_multiplayer_authority(1) bot_character.name = str(bot_id) add_child(bot_character) bot_character.add_to_group("Players", true) @@ -224,17 +285,17 @@ func replace_bot_with_player(player_id): var bot_id = bots.pop_front() players.erase(bot_id) players.append(player_id) - moving_bots.erase(bot_id) # Remove bot from moving tracking + moving_bots.erase(bot_id) rpc("remove_bot", bot_id) rpc("sync_players", players) @rpc("call_local") func remove_bot(bot_id): - var bot_node = get_node(str(bot_id)) + var bot_node = get_node_or_null(str(bot_id)) if bot_node: bot_node.queue_free() -func get_next_available_bot_id(): +func get_next_available_bot_id() -> int: for i in range(2, max_players + 1): if not i in players: return i @@ -256,7 +317,6 @@ func sync_game_state(current_players, current_bots, is_game_started, is_turn_bas game_started = is_game_started turn_based_mode = is_turn_based - # Create bot characters for existing bots for bot_id in bots: if not has_node(str(bot_id)): create_bot(bot_id) @@ -288,9 +348,7 @@ func sync_players(new_players): func next_turn(): if multiplayer.is_server() and turn_based_mode: - current_turn_index += 1 - if current_turn_index >= players.size(): - current_turn_index = 0 + current_turn_index = (current_turn_index + 1) % players.size() rpc("set_current_turn", players[current_turn_index]) if players[current_turn_index] in bots: move_bot(players[current_turn_index]) @@ -311,124 +369,145 @@ func set_current_turn(player_id): if not turn_based_mode: return - var players = get_tree().get_nodes_in_group("Players") - for player in players: - player.is_my_turn = (player.name == str(player_id)) - if player.is_my_turn: + for player in get_tree().get_nodes_in_group("Players"): + if player.name == str(player_id): + player.is_my_turn = true + player.action_points = 2 + player.has_moved_this_turn = false + player.has_performed_action = false player.start_turn() + else: + player.is_my_turn = false func end_current_turn(): if multiplayer.is_server(): next_turn() rpc("sync_turn_index", current_turn_index) -func _on_message_input_text_submitted(new_text): - if new_text.length() > max_message_input_char: - new_text = new_text.substr(0, max_message_input_char) + " ... " - local_player_character.rpc("display_message", new_text) - $MessageInput.text = "" - $MessageInput.release_focus() - func move_bot(bot_id): - if multiplayer.is_server(): - if moving_bots.get(bot_id, false): - return - - var bot = get_node(str(bot_id)) - if bot and (turn_based_mode or not bot.is_player_moving): - moving_bots[bot_id] = true - - var best_move = evaluate_bot_move(bot) - - match best_move.action: - "grab": - if bot.grab_item(): - bot.has_performed_action = true - moving_bots[bot_id] = false - # Don't end turn, allow movement after grab - move_bot(bot_id) # Try to move after grabbing - "put": - if bot.put_item(): - bot.has_performed_action = true - moving_bots[bot_id] = false - # Don't end turn, allow movement after put - move_bot(bot_id) # Try to move after putting - "move": - if bot.has_performed_action: - var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(best_move.position)) - if path.size() > 1: - path.pop_front() - var trimmed_path = path.slice(0, bot.movement_range) - bot.rotate_towards_target(best_move.position) - bot.move_bot_along_path(trimmed_path, bot_id) - else: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() - else: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() - _: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() + if not multiplayer.is_server() or moving_bots.get(bot_id, false): + return + + var bot = get_node_or_null(str(bot_id)) + if not is_instance_valid(bot) or bot.is_player_moving: + moving_bots.erase(bot_id) + return + + if bot.action_points <= 0: + if turn_based_mode: + moving_bots[bot_id] = false + end_current_turn() + else: + bot.action_points = 2 + bot.has_moved_this_turn = false + bot.has_performed_action = false + moving_bots[bot_id] = false + await get_tree().create_timer(0.5).timeout + move_bot(bot_id) + return + + moving_bots[bot_id] = true + await get_tree().create_timer(0.5).timeout + + if not is_instance_valid(bot): + moving_bots.erase(bot_id) + return + + var best_move = evaluate_bot_move(bot) + execute_bot_move(bot, bot_id, best_move) -func bot_movement_completed(bot_id): - if multiplayer.is_server(): - moving_bots[bot_id] = false +func execute_bot_move(bot, bot_id, move): + match move.action: + "arrange": + if bot.action_points >= 2: + bot.arrange_playerboard_item(bot.find_best_arrangement_slot()) + bot.action_points -= 2 + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + "grab", "put": + var success = bot.grab_item(move.position) if move.action == "grab" else bot.put_item(move.position) + if success: + bot.action_points -= 1 + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + "move": + if is_instance_valid(bot) and bot.action_points >= 1: + var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(move.position)) + if path.size() > 1: + path.pop_front() + var trimmed_path = path.slice(0, bot.movement_range) + bot.rotate_towards_target(move.position) + bot.move_bot_along_path(trimmed_path, bot_id) + bot.action_points -= 1 + else: + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + else: + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + _: + moving_bots[bot_id] = false + if turn_based_mode: + end_current_turn() + else: + move_bot(bot_id) func evaluate_bot_move(bot: Node) -> Dictionary: - var best_move = { - "action": "none", - "position": bot.current_position, - "value": -1 - } + if not is_instance_valid(bot) or bot.action_points <= 0: + return { "action": "none", "position": Vector2i.ZERO, "value": -1 } + + var moves = [] - # If no action performed yet, prioritize grab/put - if not bot.has_performed_action: - # Check current position for grabbing - var current_cell = Vector3i(bot.current_position.x, 1, bot.current_position.y) - var current_item = bot.enhanced_gridmap.get_cell_item(current_cell) + if bot.action_points >= 2 and bot.check_playerboard_arrangement(bot): + moves.append({ "action": "arrange", "position": bot.current_position, "value": 20 }) + + if bot.action_points >= 1: + var put_position = bot.find_best_put_position(bot) + if put_position != Vector2i(-1, -1): + moves.append({ "action": "put", "position": put_position, "value": 18 }) + + if bot.action_points >= 1 and not bot.playerboard_is_full(): + var grab_position = bot.find_best_grab_position() + if grab_position != Vector2i(-1, -1): + moves.append({ "action": "grab", "position": grab_position, "value": 15 }) + + if bot.action_points >= 1 and not bot.has_moved_this_turn: + var random_pos = bot.find_random_valid_position_in_range() + if random_pos != bot.current_position: + moves.append({ "action": "move", "position": random_pos, "value": 5 }) + + moves.sort_custom(func(a, b): return a.value > b.value) + return moves[0] if moves.size() > 0 else { "action": "none", "position": bot.current_position, "value": 0 } + +func bot_movement_completed(bot_id): + if not multiplayer.is_server(): + return - # Evaluate grabbing current item if it matches goals - if current_item != -1 and current_item in bot.goals and bot.playerboard.find(-1) != -1: - return { - "action": "grab", - "position": bot.current_position, - "value": 10 - } - - # Evaluate putting item from playerboard - for goal in bot.goals: - var item_index = bot.playerboard.find(goal) - if item_index != -1 and current_item == -1: - return { - "action": "put", - "position": bot.current_position, - "value": 15 - } + moving_bots[bot_id] = false + var bot = get_node_or_null(str(bot_id)) + + if not is_instance_valid(bot): + moving_bots.erase(bot_id) + return + + if bot.action_points > 0 or not turn_based_mode: + await get_tree().create_timer(0.5).timeout + if is_instance_valid(bot): + move_bot(bot_id) else: - # Bot has performed action, look for movement - var neighbors = bot.enhanced_gridmap.get_neighbors(bot.current_position, 1) - for neighbor in neighbors: - if not neighbor.is_walkable: - continue - - if not bot.is_within_movement_range(neighbor.position): - continue - - var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) - var item = bot.enhanced_gridmap.get_cell_item(cell) - - # Evaluate position for next turn - if item in bot.goals or item == -1: - var value = 8 - if value > best_move.value: - best_move = { - "action": "move", - "position": neighbor.position, - "value": value - } - - return best_move + end_current_turn() diff --git a/scenes/main.tscn b/scenes/main.tscn index 74c42f5..f63cdfc 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,29 +1,38 @@ -[gd_scene load_steps=7 format=3 uid="uid://dxn87yj8qnfpp"] +[gd_scene load_steps=14 format=3 uid="uid://dxn87yj8qnfpp"] [ext_resource type="MeshLibrary" uid="uid://54tpx8cmksfc" path="res://addons/enhanced_gridmap/meshlibrary/default.tres" id="1_110wo"] [ext_resource type="Script" path="res://scenes/main.gd" id="1_xcpe3"] [ext_resource type="Script" path="res://addons/enhanced_gridmap/enhanced_gridmap.gd" id="2_hbe1v"] [ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://assets/main-environment.tres" id="4_ky38j"] [ext_resource type="StyleBox" uid="uid://dlw1ogamn741n" path="res://assets/styles/box_flat.tres" id="5_dvx6y"] +[ext_resource type="Texture2D" uid="uid://2yrc6rl4dmd8" path="res://assets/textures/player_board_and_blue_print/tile_null.tres" id="6_2vy7d"] +[ext_resource type="Texture2D" uid="uid://cwxgdi7b4ps40" path="res://assets/textures/Hilight.png" id="7_2nq2l"] +[ext_resource type="Texture2D" uid="uid://c2bj21abtgda1" path="res://assets/models/pboard/HighlightRect.tres" id="7_vv0nt"] +[ext_resource type="Texture2D" uid="uid://0wjk16jlgfq" path="res://assets/models/pboard/SelectRect.tres" id="8_8meci"] +[ext_resource type="Texture2D" uid="uid://dojnv8o6we4ey" path="res://assets/textures/Selected.png" id="8_b18m4"] +[ext_resource type="Texture2D" uid="uid://68x88jj25yxg" path="res://assets/textures/Adjacent.png" id="9_6gcb6"] +[ext_resource type="Texture2D" uid="uid://dasaeaytvhll0" path="res://assets/models/pboard/AdjacentRect.tres" id="9_aspsw"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cewu"] [node name="Main" type="Node3D"] script = ExtResource("1_xcpe3") +turn_based_mode = false [node name="EnhancedGridMap" type="GridMap" parent="."] mesh_library = ExtResource("1_110wo") cell_size = Vector3(1, 1, 1) data = { -"cells": PackedInt32Array(9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 8, 0, 9, 9, 0, 9, 7, 0, 9, 6, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 65536, 0, 7, 65536, 1, 10, 65536, 2, 9, 65536, 3, 9, 65536, 4, 8, 65536, 5, 7, 65536, 6, 9, 65536, 7, 9, 65536, 8, 10, 65536, 9, 8, 65537, 0, 9, 65537, 1, 8, 65537, 2, 10, 65537, 3, 9, 65537, 4, 7, 65537, 5, 10, 65537, 6, 9, 65537, 7, 9, 65537, 8, 10, 65537, 9, 10, 65538, 0, 7, 65538, 1, 10, 65538, 2, 9, 65538, 3, 8, 65538, 4, 9, 65538, 5, 10, 65538, 6, 9, 65538, 7, 8, 65538, 8, 9, 65538, 9, 10, 65539, 0, 9, 65539, 1, 10, 65539, 2, 9, 65539, 3, 10, 65539, 4, 9, 65539, 5, 9, 65539, 6, 10, 65539, 7, 10, 65539, 8, 9, 65539, 9, 9, 65540, 0, 7, 65540, 1, 7, 65540, 2, 7, 65540, 3, 10, 65540, 4, 9, 65540, 5, 7, 65540, 6, 9, 65540, 7, 9, 65540, 8, 7, 65540, 9, 8, 65541, 0, 8, 65541, 1, 7, 65541, 2, 7, 65541, 3, 10, 65541, 4, 10, 65541, 5, 8, 65541, 6, 7, 65541, 7, 7, 65541, 8, 8, 65541, 9, 9, 65542, 0, 10, 65542, 1, 10, 65542, 2, 9, 65542, 3, 7, 65542, 4, 8, 65542, 5, 9, 65542, 6, 10, 65542, 7, 9, 65542, 8, 10, 65542, 9, 9, 65543, 0, 7, 65543, 1, 8, 65543, 2, 10, 65543, 3, 8, 65543, 4, 7, 65543, 5, 10, 65543, 6, 10, 65543, 7, 7, 65543, 8, 10, 65543, 9, 8, 65544, 0, 9, 65544, 1, 9, 65544, 2, 8, 65544, 3, 8, 65544, 4, 8, 65544, 5, 7, 65544, 6, 8, 65544, 7, 9, 65544, 8, 10, 65544, 9, 10, 65545, 0, 10, 65545, 1, 8, 65545, 2, 10, 65545, 3, 8, 65545, 4, 8, 65545, 5, 7, 65545, 6, 9, 65545, 7, 9, 65545, 8, 9, 65545, 9, 9) +"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 1, 11, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 2, 10, 0, 2, 11, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 3, 10, 0, 3, 11, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 4, 10, 0, 4, 11, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 11, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 6, 10, 0, 6, 11, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 7, 10, 0, 7, 11, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 8, 10, 0, 8, 11, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 6, 0, 9, 7, 0, 9, 8, 0, 9, 9, 0, 9, 10, 0, 9, 11, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 10, 6, 0, 10, 7, 0, 10, 8, 0, 10, 9, 0, 10, 10, 0, 10, 11, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 11, 6, 0, 11, 7, 0, 11, 8, 0, 11, 9, 0, 11, 10, 0, 11, 11, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 12, 6, 0, 12, 7, 0, 12, 8, 0, 12, 9, 0, 12, 10, 0, 12, 11, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 13, 6, 0, 13, 7, 0, 13, 8, 0, 13, 9, 0, 13, 10, 0, 13, 11, 0, 65537, 1, 9, 65537, 2, 9, 65537, 3, 10, 65537, 4, 7, 65537, 5, 10, 65537, 6, 7, 65537, 7, 7, 65537, 8, 8, 65537, 9, 7, 65537, 10, 10, 65537, 11, 8, 65538, 1, 8, 65538, 2, 8, 65538, 3, 10, 65538, 4, 8, 65538, 5, 10, 65538, 6, 8, 65538, 7, 9, 65538, 8, 9, 65538, 9, 7, 65538, 10, 7, 65538, 11, 9, 65539, 0, 8, 65539, 1, 9, 65539, 2, 7, 65539, 3, 10, 65539, 4, 9, 65539, 5, 7, 65539, 6, 8, 65539, 7, 9, 65539, 8, 7, 65539, 9, 7, 65539, 10, 7, 65539, 11, 9, 65540, 0, 9, 65540, 1, 9, 65540, 2, 10, 65540, 3, 8, 65540, 4, 9, 65540, 5, 10, 65540, 6, 7, 65540, 7, 10, 65540, 8, 9, 65540, 9, 10, 65540, 10, 9, 65540, 11, 10, 65541, 0, 8, 65541, 1, 8, 65541, 2, 8, 65541, 3, 10, 65541, 4, 7, 65541, 5, 9, 65541, 6, 8, 65541, 7, 10, 65541, 8, 9, 65541, 9, 8, 65541, 10, 10, 65541, 11, 9, 65542, 0, 7, 65542, 1, 8, 65542, 2, 9, 65542, 3, 10, 65542, 4, 9, 65542, 5, 10, 65542, 6, 10, 65542, 7, 7, 65542, 8, 7, 65542, 9, 10, 65542, 10, 7, 65542, 11, 7, 65543, 0, 9, 65543, 1, 8, 65543, 2, 10, 65543, 3, 7, 65543, 4, 7, 65543, 5, 10, 65543, 6, 9, 65543, 7, 8, 65543, 8, 9, 65543, 9, 7, 65543, 10, 7, 65543, 11, 9, 65544, 0, 7, 65544, 1, 7, 65544, 2, 10, 65544, 3, 10, 65544, 4, 7, 65544, 5, 7, 65544, 6, 9, 65544, 7, 10, 65544, 8, 7, 65544, 9, 7, 65544, 10, 8, 65544, 11, 9, 65545, 0, 9, 65545, 1, 10, 65545, 2, 9, 65545, 3, 9, 65545, 4, 9, 65545, 5, 9, 65545, 6, 9, 65545, 7, 9, 65545, 8, 10, 65545, 9, 7, 65545, 10, 7, 65545, 11, 9, 65546, 0, 8, 65546, 1, 8, 65546, 2, 7, 65546, 3, 10, 65546, 4, 7, 65546, 5, 9, 65546, 6, 9, 65546, 7, 9, 65546, 8, 7, 65546, 9, 9, 65546, 10, 10, 65546, 11, 10, 65547, 0, 10, 65547, 1, 8, 65547, 2, 7, 65547, 3, 8, 65547, 4, 10, 65547, 5, 7, 65547, 6, 10, 65547, 7, 7, 65547, 8, 10, 65547, 9, 8, 65547, 10, 7, 65547, 11, 8, 65548, 0, 7, 65548, 1, 9, 65548, 2, 10, 65548, 3, 9, 65548, 4, 7, 65548, 5, 9, 65548, 6, 8, 65548, 7, 10, 65548, 8, 10, 65548, 9, 8, 65548, 10, 9, 65548, 11, 9, 65538, 0, 10, 65537, 0, 7) } script = ExtResource("2_hbe1v") +columns = 14 +rows = 12 floors = 2 -non_walkable_items = Array[int]([4, 5]) metadata/_editor_floor_ = Vector3(0, 1, 0) [node name="Camera3D" type="Camera3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 5, 15, 12.36) +transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 6.75, 21, 16.5) environment = ExtResource("4_ky38j") fov = 35.5 @@ -45,17 +54,868 @@ grow_horizontal = 2 theme_override_styles/panel = ExtResource("5_dvx6y") [node name="PlayerboardUI" type="GridContainer" parent="."] -custom_minimum_size = Vector2(200, 200) +clip_contents = true anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 -offset_left = 30.0 -offset_top = -230.0 -offset_right = 230.0 -offset_bottom = -30.0 +offset_left = 40.0 +offset_top = -232.0 +offset_right = 236.0 +offset_bottom = -36.0 grow_vertical = 0 +size_flags_horizontal = 3 columns = 5 +[node name="Slot1" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_vv0nt") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_8meci") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_aspsw") + +[node name="Slot2" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot3" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot4" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot5" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot6" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot7" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot8" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot9" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot10" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot11" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot12" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot13" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot14" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot15" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot16" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot17" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot18" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot19" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot20" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot21" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot22" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot23" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot24" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot25" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + [node name="ActionMenu" type="Control" parent="."] layout_mode = 3 anchors_preset = 3 diff --git a/scenes/player.gd b/scenes/player.gd index 5b4691c..4643142 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -8,21 +8,20 @@ var is_player_moving: bool = false @export var cell_size: Vector3 = Vector3(2, 2, 2) @export var cell_offset: Vector3 = Vector3(0, 0, 0) -@export var center_x: bool = false -@export var center_y: bool = false -@export var center_z: bool = false +@export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] +@export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] -# Goals & Playerboard Data -@export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] # 9 length array for goals -@export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # 25 length array for holding items -var has_performed_action: bool = false # Track if grab/put action has been done +var has_performed_action: bool = false +var selected_gridmap_position = Vector2i(-1, -1) +var selected_playerboard_slot = -1 +var targeted_playerboard_slot = -1 +var action_points: int = 2 -# Player Rotation Config var target_rotation: float = 0.0 -var rotation_speed: float = 10.0 # Adjust this to control rotation speed +var rotation_speed: float = 10.0 -@export var movement_range: int = 1 # How many blocks can be moved at once -@export var use_diagonal_movement: bool = false: # Allow diagonal movement +@export var movement_range: int = 1 +@export var use_diagonal_movement: bool = false: set(value): use_diagonal_movement = value if enhanced_gridmap: @@ -33,6 +32,7 @@ var rotation_speed: float = 10.0 # Adjust this to control rotation speed is_my_turn = value if is_my_turn and is_multiplayer_authority(): rpc("display_message", "It's your turn!") + @export var has_moved_this_turn = false @onready var main_scene = get_tree().current_scene @@ -50,7 +50,7 @@ func _ready(): push_error("Main scene not found") if not enhanced_gridmap: - push_error("EnhancedGridMap node not found. Please set the correct path in the inspector.") + push_error("EnhancedGridMap node not found") return enhanced_gridmap.initialize_astar() @@ -59,14 +59,10 @@ func _ready(): current_position = find_valid_starting_position() update_player_position(current_position) - # Only set up input processing if this is not a bot if not is_in_group("Bots"): set_process_unhandled_input(is_multiplayer_authority()) - # Initialize random goals - initialize_random_goals() - - # Initialize playerboard with -1 (empty slots) + append_random_goals() playerboard.resize(25) playerboard.fill(-1) @@ -74,21 +70,7 @@ func _physics_process(_delta): if is_multiplayer_authority(): rpc("remote_set_position", global_position) -func _process(_delta): - # Skip processing for bots - if is_in_group("Bots"): - return - - if is_multiplayer_authority(): - if Input.is_action_just_pressed("grab_item"): - if grab_item(): - rpc("display_message", "Item grabbed!") - elif Input.is_action_just_pressed("put_item"): - if put_item(): - rpc("display_message", "Item placed!") - func _unhandled_input(event): - # First check if this is a bot if is_in_group("Bots"): return @@ -105,70 +87,85 @@ func _unhandled_input(event): if click_position != Vector2i(-1, -1): handle_grid_click(click_position) +func _on_slot_gui_input(event, slot_index, slot_ui) -> int: + if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: + var main = get_node("/root/Main") + if main.current_action_state == main.ActionState.ARRANGING: + if selected_playerboard_slot == -1: + select_playerboard_slot(slot_index) + return slot_index + else: + if selected_playerboard_slot == slot_index: + deselect_playerboard_slot() + return slot_index + elif can_move_to_target_playerboard_slot(): + target_playerboard_slot(slot_index) + main.emit_signal("can_move_item", true) + return slot_index + else: + return -1 + return -1 + func handle_grid_click(grid_position: Vector2i): var main = get_node("/root/Main") + if not main: + return + match main.current_action_state: main.ActionState.MOVING: if grid_position in highlighted_cells: move_player_to_clicked_position(grid_position) main.ActionState.GRABBING: - if grid_position in highlighted_cells: - grab_item_at_position(grid_position) + if grid_position in highlighted_cells or grid_position == current_position: + grab_item(grid_position) main.ActionState.PUTTING: - if grid_position in highlighted_cells: - put_item_at_position(grid_position) + if grid_position in highlighted_cells and selected_playerboard_slot != -1: + put_item(grid_position) main.ActionState.RANDOMIZING: if grid_position in highlighted_cells: - randomize_item_at_position(grid_position) + main.randomize_item_at_position(grid_position) + +func is_position_occupied(pos: Vector2i) -> bool: + for player in get_tree().get_nodes_in_group("Players"): + if player != self and player.current_position == pos: + return true + return false func find_valid_starting_position() -> Vector2i: var rng = RandomNumberGenerator.new() rng.randomize() - + var max_attempts = 100 var attempts = 0 - + while attempts < max_attempts: - current_position = Vector2i(0, rng.randi_range(0, 9)) - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(current_position.x, 0, current_position.y)) - - if cell_item not in enhanced_gridmap.non_walkable_items: - return current_position - + var x = rng.randi_range(0, enhanced_gridmap.columns - 1) + var y = rng.randi_range(0, enhanced_gridmap.rows - 1) + var pos = Vector2i(x, y) + if not is_position_occupied(pos): + return pos attempts += 1 - - return Vector2i(0, 0) + + return Vector2i.ZERO func find_random_valid_position_in_range() -> Vector2i: var rng = RandomNumberGenerator.new() rng.randomize() - var max_attempts = 100 - var attempts = 0 + var valid_positions = [] - while attempts < max_attempts: - var range_x = min(enhanced_gridmap.columns - 1, movement_range) - var range_y = min(enhanced_gridmap.rows - 1, movement_range) - - var offset_x = rng.randi_range(-range_x, range_x) - var offset_y = rng.randi_range(-range_y, range_y) - - var random_position = Vector2i( - clamp(current_position.x + offset_x, 0, enhanced_gridmap.columns - 1), - clamp(current_position.y + offset_y, 0, enhanced_gridmap.rows - 1) - ) - - if not is_within_movement_range(random_position): - attempts += 1 - continue - - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(random_position.x, 0, random_position.y)) - - if cell_item not in enhanced_gridmap.non_walkable_items and random_position != current_position: - return random_position - - attempts += 1 + for x in range(max(0, current_position.x - movement_range), + min(enhanced_gridmap.columns, current_position.x + movement_range + 1)): + for z in range(max(0, current_position.y - movement_range), + min(enhanced_gridmap.rows, current_position.y + movement_range + 1)): + var pos = Vector2i(x, z) + if pos != current_position and is_within_movement_range(pos): + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(pos): + valid_positions.append(pos) + if valid_positions.size() > 0: + return valid_positions[rng.randi() % valid_positions.size()] return current_position func raycast_to_grid(from: Vector3, to: Vector3) -> Vector2i: @@ -189,55 +186,47 @@ func raycast_to_grid(from: Vector3, to: Vector3) -> Vector2i: return Vector2i(-1, -1) func is_within_movement_range(target_position: Vector2i) -> bool: - var distance = 0 + var distance: int if use_diagonal_movement: - # For diagonal movement, use max of x and y differences - distance = max(abs(target_position.x - current_position.x), - abs(target_position.y - current_position.y)) + distance = max(abs(target_position.x - current_position.x), abs(target_position.y - current_position.y)) else: - # For orthogonal movement, use Manhattan distance - distance = abs(target_position.x - current_position.x) + \ - abs(target_position.y - current_position.y) + distance = abs(target_position.x - current_position.x) + abs(target_position.y - current_position.y) return distance <= movement_range func move_player_to_clicked_position(grid_position: Vector2i): - if not is_multiplayer_authority(): + if not is_multiplayer_authority() or is_player_moving or action_points <= 0: return - if is_player_moving: - return - var main = get_node("/root/Main") - - # Check if we're in the correct action state - if main.current_action_state != main.ActionState.MOVING: + if not main or main.current_action_state != main.ActionState.MOVING or not grid_position in highlighted_cells: return - - # Validate the clicked position is highlighted - if not grid_position in highlighted_cells: - return - - # Check if movement is valid + if not is_within_movement_range(grid_position): - print("Movement out of range") return - + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(grid_position.x, 0, grid_position.y)) - - if cell_item in enhanced_gridmap.non_walkable_items: - print("Cannot move to non-walkable cell") + if cell_item in enhanced_gridmap.non_walkable_items or is_position_occupied(grid_position): return - + rotate_towards_target(grid_position) - + var path = enhanced_gridmap.find_path(Vector2(current_position), Vector2(grid_position)) - - if path.size() > 1: + if path.size() <= 1: + return + + var valid_path = true + for point in path.slice(1): + if is_position_occupied(Vector2i(point.x, point.y)): + valid_path = false + break + + if valid_path: path.pop_front() rpc("start_movement_along_path", path) - clear_highlights() # Clear highlights after movement starts + action_points -= 1 + clear_highlights() else: - print("No valid path found") + print("Path is blocked by other players") @rpc("any_peer", "call_local") func start_movement_along_path(path: Array): @@ -245,19 +234,17 @@ func start_movement_along_path(path: Array): var tween = create_tween() tween.set_trans(Tween.TRANS_CUBIC) tween.set_ease(Tween.EASE_IN_OUT) - + for point in path: - var target_position = grid_to_world(Vector2i(point.x, point.y)) - tween.tween_property(self, "position", target_position, 0.5) - + tween.tween_property(self, "position", grid_to_world(Vector2i(point.x, point.y)), 0.5) + tween.tween_callback(func(): current_position = Vector2i(path[-1].x, path[-1].y) is_player_moving = false enhanced_gridmap.clear_path_visualization() - has_moved_this_turn = true - var main = get_node("/root/Main") + has_moved_this_turn = path.size() <= movement_range - # Reset the action state + var main = get_node("/root/Main") main.set_action_state(main.ActionState.NONE) if main.turn_based_mode: @@ -265,61 +252,21 @@ func start_movement_along_path(path: Array): _after_action_completed() ) -func move_bot_along_path(path: Array, bot_id: int): - if not is_multiplayer_authority(): - return - - rpc("start_bot_movement_along_path", path, bot_id) - -@rpc("any_peer", "call_local") -func start_bot_movement_along_path(path: Array, bot_id: int): - is_player_moving = true - var tween = create_tween() - tween.set_trans(Tween.TRANS_CUBIC) - tween.set_ease(Tween.EASE_IN_OUT) - - for point in path: - var target_position = grid_to_world(Vector2i(point.x, point.y)) - tween.tween_property(self, "position", target_position, 0.5) - - tween.tween_callback(func(): - current_position = Vector2i(path[-1].x, path[-1].y) - is_player_moving = false - enhanced_gridmap.clear_path_visualization() - has_moved_this_turn = true - var main = get_node("/root/Main") - if main.turn_based_mode: - end_turn() - # Notify main that bot movement is complete - if multiplayer.is_server(): - main.bot_movement_completed(bot_id) - ) - func update_player_position(grid_position: Vector2i): position = grid_to_world(grid_position) func grid_to_world(grid_position: Vector2i) -> Vector3: var world_position = Vector3( - grid_position.x * cell_size.x, + grid_position.x * cell_size.x + cell_size.x * 0.5, cell_size.y, - grid_position.y * cell_size.z - ) - - world_position.x += cell_size.x * 0.5 - world_position.z += cell_size.z * 0.5 - - if center_x: - world_position.x += cell_size.x * 0.5 - if center_y: - world_position.y += cell_size.y * 0.5 - if center_z: - world_position.z += cell_size.z * 0.5 - - return world_position + cell_offset + grid_position.y * cell_size.z + cell_size.z * 0.5 + ) + cell_offset + return world_position func start_turn(): + action_points = 2 has_moved_this_turn = false - has_performed_action = false # Reset action flag at start of turn + has_performed_action = false is_my_turn = true if is_multiplayer_authority(): rpc("display_message", "It's your turn!") @@ -344,155 +291,594 @@ func display_message(message): $Bubble.hide() $Bubble/Message.hide() -func initialize_random_goals(): +func initialize_random_goals(_size:int, min_value:int, max_value:int, null_count:float) -> Array[int]: goals.clear() var rng = RandomNumberGenerator.new() rng.randomize() - for i in range(9): - goals.append(rng.randi_range(7, 10)) + var result : Array[int] = [] + var null_val = 0 + var max_nulls = 3 + + const SPECIAL_VALUES = {1: 7, 2: 8, 3: 9, 4: 10} + + for i in range(_size): + if null_val < max_nulls and rng.randf() < null_count: + result.append(-1) + null_val += 1 + else: + var val = rng.randi_range(min_value, max_value) + result.append(val if not val in SPECIAL_VALUES else SPECIAL_VALUES[val]) + + return result + +func append_random_goals(): + goals.append_array(initialize_random_goals(9, 7, 10, 1.0)) if is_multiplayer_authority(): rpc("sync_goals", goals) -func grab_item() -> bool: - if not enhanced_gridmap: +func grab_item(grid_position: Vector2i = current_position) -> bool: + if not enhanced_gridmap or action_points <= 0: return false - - var current_cell = Vector3i(current_position.x, 1, current_position.y) - var item = enhanced_gridmap.get_cell_item(current_cell) - if item == -1: # No item to grab - return false - - var empty_slot = playerboard.find(-1) - if empty_slot == -1: # No empty slots - return false - - playerboard[empty_slot] = item - enhanced_gridmap.set_cell_item(current_cell, -1) - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true # Set action flag - _after_action_completed() - return true - -func grab_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.GRABBING: - return false - var cell = Vector3i(grid_position.x, 1, grid_position.y) var item = enhanced_gridmap.get_cell_item(cell) + if grid_position != current_position: + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + var is_adjacent = false + for neighbor in neighbors: + if neighbor.position == grid_position: + is_adjacent = true + break + if not is_adjacent: + return false + if item == -1: return false - - var empty_slot = playerboard.find(-1) - if empty_slot == -1: - return false - - playerboard[empty_slot] = item - enhanced_gridmap.set_cell_item(cell, -1) + if is_in_group("Bots"): + var empty_slot = playerboard.find(-1) + if empty_slot == -1: + return false + + if is_multiplayer_authority(): + playerboard[empty_slot] = item + rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) + rpc("sync_playerboard", playerboard) + + has_performed_action = true + consume_action_points(1) + clear_playerboard_highlights() + _after_action_completed() + return true + else: + var main = get_node("/root/Main") + if main: + selected_gridmap_position = grid_position + clear_highlights() + clear_playerboard_highlights() + + for i in range(playerboard.size()): + if playerboard[i] == -1: + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() + highlighted_cells.append(i) + return true + + return false + +func put_item(grid_position: Vector2i = current_position) -> bool: + if not enhanced_gridmap or action_points <= 0 or selected_playerboard_slot == -1: + return false + + var cell = Vector3i(grid_position.x, 1, grid_position.y) + if enhanced_gridmap.get_cell_item(cell) != -1: + return false + + # Check if position is adjacent or current position + if grid_position != current_position: + var is_adjacent = false + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.position == grid_position: + is_adjacent = true + break + if not is_adjacent: + return false + + var item = playerboard[selected_playerboard_slot] if is_multiplayer_authority(): + rpc("sync_grid_item", cell.x, cell.y, cell.z, item) + playerboard[selected_playerboard_slot] = -1 rpc("sync_playerboard", playerboard) has_performed_action = true + consume_action_points(1) clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state + clear_playerboard_highlights() + selected_playerboard_slot = -1 + + var main = get_node("/root/Main") + if main: + main.set_action_state(main.ActionState.NONE) _after_action_completed() return true - -func put_item() -> bool: - if not enhanced_gridmap: - return false +func handle_put_action(): + var main = get_node("/root/Main") + if not main or action_points < 1: + return + clear_highlights() + clear_playerboard_highlights() + + # Highlight non-empty slots in playerboard + for i in range(playerboard.size()): + if playerboard[i] != -1: # Highlight occupied slots + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() # Show highlight for occupied slots + highlighted_cells.append(i) + +func handle_playerboard_slot_selected(slot_index: int): + var main = get_node("/root/Main") + if not main: + return + + if main.current_action_state == main.ActionState.PUTTING: + if playerboard[slot_index] != -1: # If slot has an item + selected_playerboard_slot = slot_index + clear_highlights() + highlight_empty_adjacent_cells() # Highlight valid put locations + elif main.current_action_state == main.ActionState.GRABBING: + if slot_index in highlighted_cells and playerboard[slot_index] == -1: + var cell = Vector3i(selected_gridmap_position.x, 1, selected_gridmap_position.y) + var item = enhanced_gridmap.get_cell_item(cell) + + if item != -1: + if is_multiplayer_authority(): + playerboard[slot_index] = item + rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) + rpc("sync_playerboard", playerboard) + + has_performed_action = true + consume_action_points(1) + clear_highlights() + clear_playerboard_highlights() + selected_gridmap_position = Vector2i(-1, -1) + main.set_action_state(main.ActionState.NONE) + _after_action_completed() + +# We also need to add handle_put_slot_selected: +func handle_put_slot_selected(slot_index: int): + var main = get_node("/root/Main") + if not main or main.current_action_state != main.ActionState.PUTTING: + return + + if slot_index in highlighted_cells and playerboard[slot_index] in goals: + selected_playerboard_slot = slot_index + clear_highlights() + highlight_empty_adjacent_cells() + +#func arrange_playerboard_item(slot_index: int): + #if action_points < 2 or playerboard[slot_index] == -1: + #return +# + #var selected_item = playerboard[slot_index] + #var adjacent_slots = get_adjacent_playerboard_slots(slot_index) +# + #var main = get_node("/root/Main") + #if not main or not main.playerboard_ui: + #return +# + #var selected_slot_ui = main.playerboard_ui.get_child(slot_index) + #if selected_slot_ui.get_child_count() > 1: + #selected_slot_ui.get_child(1).show() +# + #for adj_slot in adjacent_slots: + #if playerboard[adj_slot] == -1 or is_valid_arrangement_slot(slot_index, adj_slot): + #var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + #if adj_slot_ui.get_child_count() > 2: + #adj_slot_ui.get_child(2).show() +# + #main.update_playerboard_highlights(adjacent_slots) +# + #var target_slot = await _on_slot_gui_input(null, slot_index, selected_slot_ui) + # + #if selected_slot_ui.get_child_count() > 1: + #selected_slot_ui.get_child(1).hide() + # + #for adj_slot in adjacent_slots: + #var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + #if adj_slot_ui.get_child_count() > 2: + #adj_slot_ui.get_child(2).hide() +# + #if target_slot != -1 and (playerboard[target_slot] == -1 or is_valid_arrangement_slot(slot_index, target_slot)): + #var temp_item = playerboard[target_slot] + #playerboard[target_slot] = selected_item + #playerboard[slot_index] = temp_item +# + #if is_multiplayer_authority(): + #rpc("sync_playerboard", playerboard) + #consume_action_points(2) + #has_performed_action = true + #_after_action_completed() + #main.update_playerboard_ui() + +func arrange_playerboard_item(slot_index: int): + if action_points < 2 or playerboard[slot_index] == -1: + return + + var selected_item = playerboard[slot_index] + var adjacent_slots = get_adjacent_playerboard_slots(slot_index) + + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + # Store the selected slot + selected_playerboard_slot = slot_index + + # Highlight selected slot + var selected_slot_ui = main.playerboard_ui.get_child(slot_index) + if selected_slot_ui.get_child_count() > 1: + selected_slot_ui.get_child(1).show() + + # Highlight valid adjacent slots + for adj_slot in adjacent_slots: + if playerboard[adj_slot] == -1: # Only highlight empty adjacent slots + var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + if adj_slot_ui.get_child_count() > 2: + adj_slot_ui.get_child(2).show() + highlighted_cells.append(adj_slot) + + # Connect to slot click signals + for i in range(playerboard.size()): + var slot = main.playerboard_ui.get_child(i) + if not slot.gui_input.is_connected(_on_slot_clicked): + slot.gui_input.connect(_on_slot_clicked.bind(i)) + +func _on_slot_clicked(event: InputEvent, slot_index: int): + if not event is InputEventMouseButton or not event.pressed or event.button_index != MOUSE_BUTTON_LEFT: + return + + var main = get_node("/root/Main") + if not main or main.current_action_state != main.ActionState.ARRANGING: + return + + if selected_playerboard_slot == -1 or slot_index == selected_playerboard_slot: + return + + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + if slot_index in adjacent_slots and playerboard[slot_index] == -1: + # Move item to empty target slot + var selected_item = playerboard[selected_playerboard_slot] + playerboard[slot_index] = selected_item + playerboard[selected_playerboard_slot] = -1 + + if is_multiplayer_authority(): + rpc("sync_playerboard", playerboard) + consume_action_points(2) + has_performed_action = true + + # Clear highlights + clear_highlights() + clear_playerboard_highlights() + + # Reset selection + selected_playerboard_slot = -1 + + # Update the visual representation + main.update_playerboard_ui() + main.set_action_state(main.ActionState.NONE) + + +func check_playerboard_arrangement(bot: Node) -> bool: + var goal_indices = [] # Store indices of non-empty goals + var goal_items = [] # Store the actual goal items + + # Get all valid goals (non -1) + for i in range(goals.size()): + if goals[i] != -1: + goal_indices.append(i) + goal_items.append(goals[i]) + + # Check if current arrangement matches goals + var current_items = [] + for i in range(playerboard.size()): + if playerboard[i] in goal_items: + current_items.append(playerboard[i]) + + # Compare current order with goal order + for i in range(min(current_items.size(), goal_items.size())): + if current_items[i] != goal_items[i]: + return true + + return false + +func is_valid_arrangement_slot(from_slot: int, to_slot: int) -> bool: + var from_row = from_slot / 5 + var from_col = from_slot % 5 + var to_row = to_slot / 5 + var to_col = to_slot % 5 + + var row_diff = abs(from_row - to_row) + var col_diff = abs(from_col - to_col) + + return (row_diff == 1 and col_diff == 0) or (row_diff == 0 and col_diff == 1) + +func get_adjacent_playerboard_slots(slot_index) -> Array: + var adjacent = [] + var row = slot_index / 5 + var col = slot_index % 5 + + if row > 0: adjacent.append(slot_index - 5) + if row < 4: adjacent.append(slot_index + 5) + if col > 0: adjacent.append(slot_index - 1) + if col < 4: adjacent.append(slot_index + 1) + + return adjacent + +func find_best_arrangement_slot() -> int: + for i in range(playerboard.size()): + if playerboard[i] != -1: + var neighbors = get_adjacent_playerboard_slots(i) + for adj_slot in neighbors: + if playerboard[adj_slot] == -1 and playerboard[i] in goals: + return adj_slot + return playerboard.find(-1) + +func find_best_put_position(bot: Node) -> Vector2i: + # Find the first empty cell adjacent to a matching item in the playerboard + for i in range(playerboard.size()): + if playerboard[i] in goals: + var neighbors = enhanced_gridmap.get_neighbors(current_position, 1) + for neighbor in neighbors: + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if enhanced_gridmap.get_cell_item(cell) == -1: + return neighbor.position + return Vector2i(-1, -1) + +func find_best_grab_position() -> Vector2i: + # Find the first matching item in the grid or adjacent cells + var current_cell = Vector3i(current_position.x, 1, current_position.y) + if enhanced_gridmap.get_cell_item(current_cell) in goals: + return current_position + + var neighbors = enhanced_gridmap.get_neighbors(current_position, 1) + for neighbor in neighbors: + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if enhanced_gridmap.get_cell_item(cell) in goals: + return neighbor.position + + return Vector2i(-1, -1) + +func has_item_at_current_position() -> bool: + var current_cell = Vector3i(current_position.x, 1, current_position.y) + return enhanced_gridmap.get_cell_item(current_cell) != -1 + +func has_items_in_playerboard() -> bool: + return playerboard.any(func(item): return item != -1) + +func playerboard_is_full() -> bool: + return playerboard.find(-1) == -1 + +func highlight_movement_range(): + if is_in_group("Bots"): + return + + for x in range(enhanced_gridmap.columns): + for z in range(enhanced_gridmap.rows): + var test_pos = Vector2i(x, z) + if is_within_movement_range(test_pos): + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(test_pos): + highlighted_cells.append(test_pos) + enhanced_gridmap.set_cell_item(Vector3i(x, 0, z), enhanced_gridmap.hover_item) + +func highlight_adjacent_cells(): + if is_in_group("Bots"): + return + var current_cell = Vector3i(current_position.x, 1, current_position.y) if enhanced_gridmap.get_cell_item(current_cell) != -1: - return false # Cell is occupied - - var item_to_put = -1 - var item_index = -1 + highlighted_cells.append(current_position) + enhanced_gridmap.set_cell_item(Vector3i(current_position.x, 0, current_position.y), enhanced_gridmap.hover_item) - for goal in goals: - var index = playerboard.find(goal) - if index != -1: - item_to_put = goal - item_index = index - break - - if item_to_put == -1: - return false - - enhanced_gridmap.set_cell_item(current_cell, item_to_put) - playerboard[item_index] = -1 - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true # Set action flag - _after_action_completed() - return true + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.is_walkable: + var cell_pos = neighbor.position + if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) != -1: + highlighted_cells.append(cell_pos) + enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) -func put_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.PUTTING: - return false + +func highlight_empty_adjacent_cells(): + if is_in_group("Bots"): + return - var cell = Vector3i(grid_position.x, 1, grid_position.y) - if enhanced_gridmap.get_cell_item(cell) != -1: - return false - - var item_to_put = -1 - var item_index = -1 - - for goal in goals: - var index = playerboard.find(goal) - if index != -1: - item_to_put = goal - item_index = index - break - - if item_to_put == -1: - return false - - enhanced_gridmap.set_cell_item(cell, item_to_put) - playerboard[item_index] = -1 - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true + # Clear previous highlights clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state - _after_action_completed() - return true + + # Highlight current position if empty + var current_cell = Vector3i(current_position.x, 1, current_position.y) + if enhanced_gridmap.get_cell_item(current_cell) == -1: + highlighted_cells.append(current_position) + enhanced_gridmap.set_cell_item(Vector3i(current_position.x, 0, current_position.y), + enhanced_gridmap.hover_item) + + # Highlight empty adjacent cells + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.is_walkable: + var cell_pos = neighbor.position + var cell = Vector3i(cell_pos.x, 1, cell_pos.y) + if enhanced_gridmap.get_cell_item(cell) == -1: # Check if cell is empty + highlighted_cells.append(cell_pos) + enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), + enhanced_gridmap.hover_item) + +func highlight_random_valid_cells(): + if is_in_group("Bots"): + return + + var valid_cells = [] + for x in range(enhanced_gridmap.columns): + for z in range(enhanced_gridmap.rows): + var cell_pos = Vector2i(x, z) + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): + valid_cells.append(cell_pos) -func randomize_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.RANDOMIZING: - return false - - var cell = Vector3i(grid_position.x, 1, grid_position.y) - if enhanced_gridmap.get_cell_item(cell) != -1: - return false - var rng = RandomNumberGenerator.new() rng.randomize() + for _i in range(min(5, valid_cells.size())): + var index = rng.randi() % valid_cells.size() + var cell = valid_cells[index] + highlighted_cells.append(cell) + enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) + valid_cells.remove_at(index) + +func highlight_occupied_playerboard_slots(): + if is_in_group("Bots"): + return + + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + # First reset all slots to normal + for i in range(playerboard.size()): + var slot = main.playerboard_ui.get_child(i) + for child in slot.get_children(): + child.hide() - # Assuming items are numbered 1-10 - var random_item = rng.randi_range(7, 10) - enhanced_gridmap.set_cell_item(cell, random_item) + # Highlight occupied slots that match goals + for i in range(playerboard.size()): + if playerboard[i] in goals: + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() # Show highlight for matching items + highlighted_cells.append(i) # Add to highlighted cells for tracking + + # Update the UI to reflect changes + main.update_playerboard_ui() + +func clear_highlights(): + if not enhanced_gridmap: + return + + for cell in highlighted_cells: + if cell is Vector2i: + enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.normal_items[0]) - has_performed_action = true - clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state - _after_action_completed() - return true + highlighted_cells.clear() + + var main = get_node("/root/Main") + if main and main.playerboard_ui: + for i in range(main.playerboard_ui.get_child_count()): + var slot = main.playerboard_ui.get_child(i) + for child in slot.get_children(): + child.hide() + +func clear_playerboard_highlights(): + var main = get_node("/root/Main") + if main and main.playerboard_ui: + for i in range(main.playerboard_ui.get_child_count()): + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: slot.get_child(0).hide() + if slot.get_child_count() > 1: slot.get_child(1).hide() + if slot.get_child_count() > 2: slot.get_child(2).hide() + + highlighted_cells.clear() + +func rotate_towards_target(target_pos: Vector2i): + var direction = Vector2(target_pos.x - current_position.x, target_pos.y - current_position.y).normalized() + target_rotation = atan2(direction.x, direction.y) + + if is_multiplayer_authority(): + rpc("sync_rotation", target_rotation) + + var tween = create_tween() + tween.tween_property(self, "rotation:y", target_rotation, 0.2) + +# We also need to add these supporting functions: +func select_playerboard_slot(slot_index: int): + selected_playerboard_slot = slot_index + _update_playerboard_slot_visual(slot_index) + _highlight_adjacent_playerboard_slots() + +func deselect_playerboard_slot(): + var old_selected = selected_playerboard_slot + selected_playerboard_slot = -1 + if old_selected != -1: + _update_playerboard_slot_visual(old_selected) + untarget_playerboard_slot() + _highlight_adjacent_playerboard_slots() + +func target_playerboard_slot(slot_index: int): + if targeted_playerboard_slot != -1: + untarget_playerboard_slot() + targeted_playerboard_slot = slot_index + _update_playerboard_slot_visual(slot_index) + +func untarget_playerboard_slot(): + if targeted_playerboard_slot != -1: + var old_targeted = targeted_playerboard_slot + targeted_playerboard_slot = -1 + _update_playerboard_slot_visual(old_targeted) + +func can_move_to_target_playerboard_slot() -> bool: + if selected_playerboard_slot == -1 or targeted_playerboard_slot == -1 or selected_playerboard_slot == targeted_playerboard_slot: + return false + + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + return adjacent_slots.has(targeted_playerboard_slot) + +func _update_playerboard_slot_visual(slot_index: int): + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + var slot = main.playerboard_ui.get_child(slot_index) + if slot: + if slot.get_child_count() > 0: + slot.get_child(0).visible = slot_index == selected_playerboard_slot + if slot.get_child_count() > 1: + slot.get_child(1).visible = slot_index == targeted_playerboard_slot + if slot.get_child_count() > 2: + slot.get_child(2).visible = selected_playerboard_slot != -1 and get_adjacent_playerboard_slots(selected_playerboard_slot).has(slot_index) + +func _highlight_adjacent_playerboard_slots(): + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + for i in range(25): + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 2: + slot.get_child(2).hide() + + if selected_playerboard_slot != -1: + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + for adj_slot in adjacent_slots: + var slot = main.playerboard_ui.get_child(adj_slot) + if slot.get_child_count() > 2: + slot.get_child(2).show() + +@rpc("any_peer", "call_local", "reliable") +func sync_rotation(new_rotation: float): + if not is_multiplayer_authority(): + rotation.y = new_rotation + +@rpc("any_peer", "call_local", "reliable") +func sync_grid_item(x: int, y: int, z: int, item: int): + if enhanced_gridmap: + enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item) @rpc("any_peer", "call_local") func sync_goals(new_goals: Array): @@ -503,118 +889,33 @@ func sync_playerboard(new_playerboard: Array): playerboard = new_playerboard _after_action_completed() -func rotate_towards_target(target_pos: Vector2i): - var direction = Vector2( - target_pos.x - current_position.x, - target_pos.y - current_position.y - ).normalized() - - target_rotation = atan2(direction.x, direction.y) - - # Create a tween for smooth rotation - var tween = create_tween() - tween.tween_property(self, "rotation:y", target_rotation, 0.2) - func _after_action_completed(): if multiplayer.get_unique_id() == get_multiplayer_authority(): var main = get_node("/root/Main") - main.update_button_states() - main.update_playerboard_ui() + if main: + if not main.turn_based_mode and action_points <= 0: + action_points = 2 + has_performed_action = false + has_moved_this_turn = false + main.update_button_states() + main.update_playerboard_ui() -func has_item_at_current_position() -> bool: - var current_cell = Vector3i(current_position.x, 1, current_position.y) - return enhanced_gridmap.get_cell_item(current_cell) != -1 - -func has_items_in_playerboard() -> bool: - return playerboard.any(func(item): return item != -1) - -func highlight_movement_range(): - var cells_to_highlight = [] - for x in range(enhanced_gridmap.columns): - for z in range(enhanced_gridmap.rows): - var test_pos = Vector2i(x, z) - if is_within_movement_range(test_pos): - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) - if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): - cells_to_highlight.append(test_pos) - - for cell in cells_to_highlight: - highlighted_cells.append(cell) - # Store original item for restoration - var original_item = enhanced_gridmap.get_cell_item(Vector3i(cell.x, 0, cell.y)) - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) - -func highlight_adjacent_cells(): - var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) - for neighbor in neighbors: - if neighbor.is_walkable: - var cell_pos = neighbor.position - if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) != -1: - highlighted_cells.append(cell_pos) - enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) - -func highlight_empty_adjacent_cells(): - var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) - for neighbor in neighbors: - if neighbor.is_walkable: - var cell_pos = neighbor.position - if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) == -1: - highlighted_cells.append(cell_pos) - enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) - -func highlight_random_valid_cells(): - var valid_cells = [] - for x in range(enhanced_gridmap.columns): - for z in range(enhanced_gridmap.rows): - var cell_pos = Vector2i(x, z) - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) - if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): - valid_cells.append(cell_pos) - - # Highlight random subset of valid cells - var rng = RandomNumberGenerator.new() - rng.randomize() - for _i in range(min(5, valid_cells.size())): - var index = rng.randi() % valid_cells.size() - var cell = valid_cells[index] - highlighted_cells.append(cell) - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) - valid_cells.remove_at(index) - -func clear_highlights(): - for cell in highlighted_cells: - # Reset to normal item - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.normal_items[0]) - highlighted_cells.clear() - -func arrange_playerboard_item(slot_index: int): - if playerboard[slot_index] == -1: +func consume_action_points(points: int): + if not is_instance_valid(self) or not is_multiplayer_authority(): return - # Store the selected slot for arrangement - var temp_item = playerboard[slot_index] - playerboard[slot_index] = -1 - - # Wait for second click to complete arrangement - await get_tree().create_timer(0.1).timeout - - var target_slot = await wait_for_playerboard_click() - if target_slot != -1: - var swap_item = playerboard[target_slot] - playerboard[target_slot] = temp_item - playerboard[slot_index] = swap_item - - if multiplayer.is_server(): - rpc("sync_playerboard", playerboard) - -func wait_for_playerboard_click() -> int: + action_points -= points var main = get_node("/root/Main") - while true: - var event = await main.playerboard_ui.gui_input - if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: - var local_pos = main.playerboard_ui.get_local_mouse_position() - for i in range(25): - var slot = main.playerboard_ui.get_child(i) - if slot.get_global_rect().has_point(event.global_position): - return i - return -1 + if not main: + return + + if action_points <= 0: + if main.turn_based_mode: + main.request_end_turn() + else: + action_points = 2 + has_performed_action = false + has_moved_this_turn = false + rpc("display_message", "Action Points Reset!") + + _after_action_completed()