feat: update vfx

This commit is contained in:
2026-06-18 14:04:06 +08:00
parent 5354d8b30f
commit 78f071b728
18 changed files with 704 additions and 62 deletions
+11
View File
@@ -140,6 +140,10 @@ var _bot_names: Dictionary = {}
# Room list filter ("" = all, "Freemode", "Stop n Go", etc.)
var _room_mode_filter: String = ""
# Re-entry guard for the async host flow (prevents double-click from starting
# two overlapping create_match() calls).
var _is_hosting: bool = false
# =============================================================================
# Chat System
# =============================================================================
@@ -248,6 +252,13 @@ func _ready():
# Connect UserProfileManager signals
UserProfileManager.profile_loaded.connect(func(_p): _sync_room_profile_card())
UserProfileManager.profile_updated.connect(func(): _sync_room_profile_card())
# Clear the host re-entry guard whenever the host flow concludes — success,
# failure, or leaving the room.
LobbyManager.room_joined.connect(func(_r): _is_hosting = false)
LobbyManager.room_left.connect(func(): _is_hosting = false)
NakamaManager.match_join_error.connect(func(_e): _is_hosting = false)
NakamaManager.connection_failed.connect(func(_e): _is_hosting = false)
# Connect Mailbox UI
if MailManager:
+138
View File
@@ -1919,6 +1919,144 @@ func sync_grid_item(x: int, y: int, z: int, item: int):
if enhanced_gridmap.has_method("update_grid_data"):
enhanced_gridmap.update_grid_data()
@rpc("any_peer", "call_local", "reliable")
func play_freeze_floor_vfx(center_x: int, center_z: int, radius: int, duration: float) -> void:
# Spawns a flat freeze-floor AnimatedSprite3D that covers the (2*radius+1)^2
# frozen area, centered on the given grid cell and sitting just above the
# floor surface. The template under vfxController/AnimatedSprite3D (hidden) is
# laid flat and sized for ~1 tile; we duplicate it, then size it to the area
# from its measured footprint. Runs on every peer.
var vfx_root := get_node_or_null("vfxController")
if not vfx_root:
return
var template := vfx_root.get_node_or_null("AnimatedSprite3D") as AnimatedSprite3D
if not template:
return
var enhanced_gridmap = $EnhancedGridMap
if not enhanced_gridmap:
return
var cell: Vector3 = enhanced_gridmap.cell_size
var vfx := template.duplicate() as AnimatedSprite3D
# --- Scale to cover the whole area -------------------------------------
# The template's world footprint = its local sprite size (texture * pixel_size,
# from the AABB) times each basis axis length. Scale each flat axis (X = width,
# Y = depth, since the sprite is rotated to lie flat) so it spans the area.
# AREA_SIZE_FACTOR oversizes slightly so the visible art (which has transparent
# padding inside the frame) actually fills the (2*radius+1)-tile region — tune
# this if it reads a touch small or large.
const AREA_SIZE_FACTOR := 1.25
var aabb := template.get_aabb()
var b := template.transform.basis
var base_w: float = absf(aabb.size.x) * b.x.length()
var base_d: float = absf(aabb.size.y) * b.y.length()
var want_w: float = float(2 * radius + 1) * cell.x * AREA_SIZE_FACTOR
var want_d: float = float(2 * radius + 1) * cell.z * AREA_SIZE_FACTOR
if base_w > 0.0001:
b.x = b.x * (want_w / base_w)
if base_d > 0.0001:
b.y = b.y * (want_d / base_d)
# --- World center of the freeze area -----------------------------------
# X/Z use the same convention players use (grid_to_world): cell center =
# index*size + half a cell. Y is taken from the template's own position in the
# scene, so the height can be tuned in the editor (move vfxController/
# AnimatedSprite3D up/down) without touching code. vfxController/Main sit at
# the origin, so this local point is also the world point.
var world_center := Vector3(
center_x * cell.x + cell.x * 0.5,
template.position.y,
center_z * cell.z + cell.z * 0.5
)
# Assign basis + origin together in one shot so nothing overwrites the position.
vfx.transform = Transform3D(b, world_center)
vfx.visible = true
vfx_root.add_child(vfx)
vfx.play()
print("[FreezeVFX] center cell=(%d,%d) -> world=%s, scale=(%.2f x %.2f)" % [center_x, center_z, world_center, want_w, want_d])
await get_tree().create_timer(duration).timeout
if is_instance_valid(vfx):
vfx.queue_free()
@rpc("any_peer", "call_local", "reliable")
func play_block_floor_vfx(cells: PackedVector2Array, duration: float) -> void:
# Spawns one box_block VFX per blocked cell (each covers 1x1), autoplaying its
# wall animation. The template under vfxController/box_block (hidden) is sized
# for one cell; we duplicate it per cell, keeping its Y/scale from the scene so
# height can be tuned in the editor. Runs on every peer.
var vfx_root := get_node_or_null("vfxController")
if not vfx_root:
return
var template := vfx_root.get_node_or_null("box_block")
if not template:
return
var enhanced_gridmap = $EnhancedGridMap
if not enhanced_gridmap:
return
var cell: Vector3 = enhanced_gridmap.cell_size
var spawned: Array = []
for c in cells:
# DUPLICATE_USE_INSTANTIATION so the instanced glb subtree (incl. its
# AnimationPlayer) is recreated in the copy rather than dropped.
var box := template.duplicate(DUPLICATE_USE_INSTANTIATION)
# X/Z = cell center (same convention as players), Y/scale kept from template.
var pos := Vector3(
int(c.x) * cell.x + cell.x * 0.5,
template.position.y,
int(c.y) * cell.z + cell.z * 0.5
)
box.transform = Transform3D(template.transform.basis, pos)
box.visible = true
vfx_root.add_child(box)
_autoplay_vfx_animation(box)
spawned.append(box)
await get_tree().create_timer(duration).timeout
for box in spawned:
if is_instance_valid(box):
box.queue_free()
func _autoplay_vfx_animation(node: Node) -> void:
# Find the AnimationPlayer Godot creates for an imported glb/scene and play its
# first clip once (one-shot) when the VFX is spawned.
var anim_player := node.get_node_or_null("AnimationPlayer") as AnimationPlayer
if not anim_player:
for child in node.get_children():
if child is AnimationPlayer:
anim_player = child
break
if not anim_player:
return
var list := anim_player.get_animation_list()
if list.is_empty():
return
var anim_name: String = list[0]
var anim := anim_player.get_animation(anim_name)
if anim:
anim.loop_mode = Animation.LOOP_NONE
anim_player.play(anim_name)
func play_playerboard_scatter_vfx() -> void:
# One-shot "scatter" animation over the local player's board UI. Triggered for
# the player whose tiles were scattered (caught outside the safe zone in
# Stop n Go). The clip is already non-looping in the SpriteFrames.
var vfx := get_node_or_null("PlayerBoardUI/AnimatedSprite2D") as AnimatedSprite2D
if not vfx:
return
vfx.visible = true
vfx.play("scatter")
await vfx.animation_finished
vfx.visible = false
@rpc("any_peer", "call_local", "reliable")
func sync_grid_items_batch(data: Array):
# data is an array of dictionaries: [{x: int, y: int, z: int, item: int}, ...]
+335
View File
@@ -2,6 +2,8 @@
[ext_resource type="MeshLibrary" uid="uid://kcv6ans86ug7" path="res://addons/enhanced_gridmap/meshlibrary/default.tres" id="1_110wo"]
[ext_resource type="Script" uid="uid://co1ads72by6na" path="res://scenes/main.gd" id="1_xcpe3"]
[ext_resource type="Texture2D" uid="uid://byh7506oksbhb" path="res://assets/graphics/vfx/tile_vfx_freeze/freezebawah.png" id="2_2cjbq"]
[ext_resource type="PackedScene" uid="uid://d3m0u8gl5odhw" path="res://assets/models/meshes/box_block.tscn" id="2_chjal"]
[ext_resource type="Script" uid="uid://bja8ixryvthu0" 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"]
@@ -14,6 +16,7 @@
[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"]
[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="13_j8jky"]
[ext_resource type="Texture2D" uid="uid://cmoyhmh4jpep0" path="res://assets/graphics/vfx/playerboard_scatter.png" id="14_5poiv"]
[ext_resource type="Texture2D" uid="uid://bafocgx2apwjm" path="res://assets/graphics/gui/stop_timer/Segment0_empty.png" id="14_fv21b"]
[ext_resource type="Texture2D" uid="uid://c4xpg3j7p7g33" path="res://assets/graphics/gui/global_match_timer/timer.png" id="14_tel4y"]
[ext_resource type="Texture2D" uid="uid://73ayhl1lqdpt" path="res://assets/graphics/gui/gauge/PowerLabel.png" id="14_vxglm"]
@@ -41,6 +44,316 @@
[ext_resource type="Script" uid="uid://b54tfa0n6kogi" path="res://scripts/managers/touch_controls.gd" id="touch_manager"]
[ext_resource type="Script" uid="uid://djiml4sh61dc1" path="res://scripts/ui/virtual_joystick.gd" id="virtual_joystick"]
[sub_resource type="AtlasTexture" id="AtlasTexture_0loja"]
atlas = ExtResource("2_2cjbq")
region = Rect2(0, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ids8r"]
atlas = ExtResource("2_2cjbq")
region = Rect2(500, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_dnhof"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1000, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_1v6qk"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1500, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_augu2"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2000, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_tm6hj"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2500, 0, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_kf5aa"]
atlas = ExtResource("2_2cjbq")
region = Rect2(0, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_t5ykj"]
atlas = ExtResource("2_2cjbq")
region = Rect2(500, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_e755i"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1000, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ro3en"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1500, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_od4ux"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2000, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_xhfw6"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2500, 500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_1epgm"]
atlas = ExtResource("2_2cjbq")
region = Rect2(0, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_152kg"]
atlas = ExtResource("2_2cjbq")
region = Rect2(500, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_r4e17"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1000, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_y57op"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1500, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_mlv25"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2000, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_a82wo"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2500, 1000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_gdvew"]
atlas = ExtResource("2_2cjbq")
region = Rect2(0, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_kjtvk"]
atlas = ExtResource("2_2cjbq")
region = Rect2(500, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_xrs0c"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1000, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_xljpf"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1500, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_j4bwh"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2000, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ksmap"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2500, 1500, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ygd8o"]
atlas = ExtResource("2_2cjbq")
region = Rect2(0, 2000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_2s0kr"]
atlas = ExtResource("2_2cjbq")
region = Rect2(500, 2000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_xaipn"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1000, 2000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ndrjj"]
atlas = ExtResource("2_2cjbq")
region = Rect2(1500, 2000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_ih3m7"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2000, 2000, 500, 500)
[sub_resource type="AtlasTexture" id="AtlasTexture_11yus"]
atlas = ExtResource("2_2cjbq")
region = Rect2(2500, 2000, 500, 500)
[sub_resource type="SpriteFrames" id="SpriteFrames_5poiv"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_0loja")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ids8r")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_dnhof")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1v6qk")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_augu2")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_tm6hj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_kf5aa")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_t5ykj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_e755i")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ro3en")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_od4ux")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xhfw6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1epgm")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_152kg")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_r4e17")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_y57op")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mlv25")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_a82wo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_gdvew")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_kjtvk")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xrs0c")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xljpf")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_j4bwh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ksmap")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ygd8o")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2s0kr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xaipn")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ndrjj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ih3m7")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_11yus")
}],
"loop": false,
"name": &"freeze_floor",
"speed": 15.0
}]
[sub_resource type="AtlasTexture" id="AtlasTexture_2cjbq"]
atlas = ExtResource("14_5poiv")
region = Rect2(0, 0, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_chjal"]
atlas = ExtResource("14_5poiv")
region = Rect2(357, 0, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_cjqg0"]
atlas = ExtResource("14_5poiv")
region = Rect2(714, 0, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_vchkt"]
atlas = ExtResource("14_5poiv")
region = Rect2(1071, 0, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_txyw0"]
atlas = ExtResource("14_5poiv")
region = Rect2(0, 340, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_vc5cj"]
atlas = ExtResource("14_5poiv")
region = Rect2(357, 340, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_nvyfr"]
atlas = ExtResource("14_5poiv")
region = Rect2(714, 340, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_ty1g6"]
atlas = ExtResource("14_5poiv")
region = Rect2(1071, 340, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_j2jfr"]
atlas = ExtResource("14_5poiv")
region = Rect2(0, 680, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_bjg73"]
atlas = ExtResource("14_5poiv")
region = Rect2(357, 680, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_bu4jf"]
atlas = ExtResource("14_5poiv")
region = Rect2(714, 680, 357, 340)
[sub_resource type="AtlasTexture" id="AtlasTexture_o7ddy"]
atlas = ExtResource("14_5poiv")
region = Rect2(1071, 680, 357, 340)
[sub_resource type="SpriteFrames" id="SpriteFrames_0loja"]
animations = [{
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_2cjbq")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_chjal")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_cjqg0")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vchkt")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_txyw0")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vc5cj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_nvyfr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ty1g6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_j2jfr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bjg73")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bu4jf")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_o7ddy")
}],
"loop": false,
"name": &"scatter",
"speed": 30.0
}]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_c6pm6"]
content_margin_bottom = 20.0
texture = ExtResource("14_tel4y")
@@ -104,6 +417,20 @@ texture = SubResource("CompressedTexture2D_chjal")
[node name="Main" type="Node3D" unique_id=864552263]
script = ExtResource("1_xcpe3")
[node name="vfxController" type="Node3D" parent="." unique_id=968868013]
[node name="box_block" parent="vfxController" unique_id=1480078977 instance=ExtResource("2_chjal")]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0.5, 0.35, 0.5)
visible = false
[node name="AnimatedSprite3D" type="AnimatedSprite3D" parent="vfxController" unique_id=1360317189]
transform = Transform3D(0.2, 0, 0, 0, -8.742278e-09, 0.15, 0, -0.2, -6.5567085e-09, 0.5, 0.4, 0.5)
visible = false
sprite_frames = SubResource("SpriteFrames_5poiv")
animation = &"freeze_floor"
frame = 29
frame_progress = 1.0
[node name="EnhancedGridMap" type="GridMap" parent="." unique_id=1838552857]
mesh_library = ExtResource("1_110wo")
cell_size = Vector3(1, 0.2, 1)
@@ -1077,6 +1404,14 @@ theme_override_fonts/font = ExtResource("13_j8jky")
theme_override_font_sizes/font_size = 32
text = "X0"
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="PlayerBoardUI" unique_id=390404299]
visible = false
position = Vector2(117.56293, 165.96373)
sprite_frames = SubResource("SpriteFrames_0loja")
animation = &"scatter"
frame = 11
frame_progress = 1.0
[node name="GlobalMatchTimer" type="PanelContainer" parent="." unique_id=1714357974]
custom_minimum_size = Vector2(372, 162)
anchors_preset = 5
+12
View File
@@ -413,6 +413,18 @@ func play_scatter_knock():
await vfx_scatter_knock.animation_finished
vfx_scatter_knock.visible = false
@rpc("any_peer", "call_local", "reliable")
func play_playerboard_scatter():
"""Show the one-shot scatter VFX over the playerboard UI, but only on the
local human player's own client (the board UI belongs to them)."""
var is_local = name == str(multiplayer.get_unique_id())
var is_bot_check = is_bot or is_in_group("Bots")
if not is_local or is_bot_check:
return
var main = get_tree().get_root().get_node_or_null("Main")
if main and main.has_method("play_playerboard_scatter_vfx"):
main.play_playerboard_scatter_vfx()
func _init_managers():
movement_manager = load("res://scripts/managers/player_movement_manager.gd").new()
movement_manager.name = "MovementManager"
+2 -1
View File
@@ -2,7 +2,7 @@
[ext_resource type="Script" uid="uid://dyovwailce5tf" path="res://scripts/tekton.gd" id="1_tekton"]
[ext_resource type="Script" uid="uid://c67yq846u8y68" path="res://scripts/tekton_controller.gd" id="2_controller"]
[ext_resource type="PackedScene" uid="uid://statictektonmesh001" path="res://scenes/static_tekton_mesh.tscn" id="3_d2kpk"]
[ext_resource type="PackedScene" uid="uid://df7h7y7y7y7y7" path="res://scenes/static_tekton_mesh.tscn" id="3_d2kpk"]
[ext_resource type="Texture2D" uid="uid://biun2yvglxgij" path="res://assets/graphics/touch_control/grab_tekton.png" id="4_grab_icon"]
[sub_resource type="BoxShape3D" id="BoxShape3D_tekton"]
@@ -17,6 +17,7 @@ script = ExtResource("2_controller")
[node name="Visuals" type="Node3D" parent="." unique_id=1698719440]
[node name="tekton" parent="Visuals" unique_id=2052742928 instance=ExtResource("3_d2kpk")]
transform = Transform3D(-0.2, 0, -1.7484556e-08, 0, 0.2, 0, 1.7484556e-08, 0, -0.2, 0, 0, 0)
[node name="HitArea" type="Area3D" parent="." unique_id=2139590311]
collision_layer = 4
+8
View File
@@ -72,6 +72,13 @@ func on_create_room_pressed() -> void:
lobby._sync_room_profile_card()
func host_room(game_mode: String) -> void:
# Guard against double-clicks: the create flow is async, and a second press
# before it finishes re-enters create_match() while the bridge is still
# JOINING, which throws "Cannot create match when state is JOINING".
if lobby._is_hosting:
return
lobby._is_hosting = true
if AuthManager.is_guest:
if LobbyManager.local_player_name.is_empty() or LobbyManager.local_player_name == "Player":
LobbyManager.local_player_name = NameGenerator.generate_guest_name()
@@ -92,6 +99,7 @@ func host_room(game_mode: String) -> void:
var ok = await LobbyManager.create_room_lan(room_label)
if not ok:
lobby.connection_status.text = "Failed to start LAN room. Check port 7777."
lobby._is_hosting = false
else:
lobby.connection_status.text = "Creating Nakama room..."
var room_label := "%sRoom %d" % [mode_prefix, randi_range(1000, 9999)]