feat: update

This commit is contained in:
2026-06-12 18:05:04 +08:00
parent 8a2fb36a98
commit 9dd3c59edf
67 changed files with 2298 additions and 74 deletions
+3
View File
@@ -167,6 +167,9 @@ func _process(delta: float) -> void:
if not is_active:
return
if not multiplayer.has_multiplayer_peer() or multiplayer.multiplayer_peer == null:
return
elapsed_time += delta
# Phase escalation
+1 -1
View File
@@ -103,7 +103,7 @@ func handle_unhandled_input(event):
if event.is_action_pressed("action_knock_tekton"):
if player.powerup_manager:
player.powerup_manager.use_special_effect()
if player.is_attack_mode and player.has_method("enter_attack_mode"):
if player.get("is_attack_mode") and player.has_method("enter_attack_mode"):
player.enter_attack_mode()
get_viewport().set_input_as_handled()
+2 -2
View File
@@ -149,7 +149,7 @@ func can_use_special() -> bool:
func enable_attack_mode():
"""Enable Attack Mode without consuming boost."""
player.is_attack_mode = true
player.set("is_attack_mode", true)
NotificationManager.send_message(player, NotificationManager.MESSAGES.ATTACK_MODE_READY, NotificationManager.MessageType.POWERUP)
print("[PowerUp] Attack Mode Enabled (Free).")
@@ -177,7 +177,7 @@ func consume_boost(amount: float):
current_boost -= amount
if current_boost <= 0:
current_boost = 0.0
player.is_attack_mode = false # Out of fuel
player.set("is_attack_mode", false) # Out of fuel
emit_signal("boost_reset") # UI update for empty
print("[PowerUp] Boost depleted. Attack Mode OFF.")
+5 -10
View File
@@ -317,16 +317,11 @@ func is_controller_button_used(button_index: int) -> String:
return ""
func get_control_keycode(action_name: String) -> int:
# Map friendly names to their internal settings.controls keys
var mapped_name = action_name
if action_name == "tekton_grab":
mapped_name = "action_grab_tekton"
elif action_name == "attack_mode":
mapped_name = "action_knock_tekton"
elif action_name == "grab":
mapped_name = "action_grab"
return settings.controls.get(mapped_name, -1)
# settings.controls stores keys by the same name callers pass in
# (e.g. "tekton_grab", "attack_mode", "grab"). The InputMap action name
# (e.g. "action_grab_tekton") is a separate concept handled by
# apply_control_settings(). Do NOT remap here.
return settings.controls.get(action_name, -1)
func get_control_text(action_name: String) -> String:
var code = get_control_keycode(action_name)
+1 -1
View File
@@ -4,7 +4,7 @@ extends Node
# Handles spawning and placement of Static Tektons in restricted zones.
const STAND_SCENE_PATH = "res://scenes/static_tekton_stand.tscn"
const TEKTON_SCENE_PATH = "res://scenes/tekton.tscn"
const TEKTON_SCENE_PATH = "res://scenes/static_tekton.tscn"
const STATIC_CONTROLLER_SCRIPT = "res://scripts/static_tekton_controller.gd"
const PERIMETER_BUFFER = 1 # 1-tile safe zone on all sides (matches main.gd)
+3
View File
@@ -90,6 +90,9 @@ func _process(delta):
if not is_active:
return
if not multiplayer.has_multiplayer_peer() or multiplayer.multiplayer_peer == null:
return
# Decrement timer locally for all peers (smoother HUD than waiting for RPC)
phase_timer -= delta
+35 -12
View File
@@ -97,14 +97,14 @@ func move_to(target_pos: Vector2i):
var target_rot = atan2(dir.x, dir.z)
rotation.y = target_rot
play_animation("tekton_move")
play_animation("tekton_move" if not is_static_turret else "Armature|tekton_move")
tween = create_tween()
tween.tween_property(self , "position", target_world_pos, movement_speed).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_IN_OUT)
tween.tween_callback(func():
current_position = target_pos
is_moving = false
play_animation("tekton_idle")
play_animation("tekton_idle" if not is_static_turret else "Armature|tekton_idle")
emit_signal("movement_finished")
)
@@ -143,7 +143,7 @@ func set_carried(state: bool, p_carrier: Node3D = null):
carrier = p_carrier
if is_carried:
play_animation("tekton_idle")
play_animation("tekton_idle" if not is_static_turret else "Armature|tekton_idle")
is_moving = false
if tween: tween.kill()
@@ -242,6 +242,10 @@ func _update_prompt_label():
prompt_container.visible = false
func _ready():
# For static tekton, mark it as static
if name.begins_with("StaticTekton") or has_node("Visuals/static_tekton_mesh"):
is_static_turret = true
# Cache meshes and their initial scales
_cache_meshes(self)
@@ -329,7 +333,12 @@ func on_thrown_landing(attacker: Node = null, intensity: float = 1.0):
spawn_tiles_around(int(8 * intensity))
# Floor Freeze (Visual/Instant - Run on all clients locally)
temporarily_change_floor(current_position, 1, 6, 3.0)
var mode_val = GameMode.Mode.FREEMODE
if LobbyManager:
mode_val = LobbyManager.get_game_mode()
if mode_val != GameMode.Mode.FREEMODE:
temporarily_change_floor(current_position, 1, 6, 3.0)
# Wait 3.0 seconds
await get_tree().create_timer(3.0).timeout
@@ -345,8 +354,8 @@ func on_thrown_landing(attacker: Node = null, intensity: float = 1.0):
is_recovering = false
# Resume AI
if controller and controller.has_method("_start_timer"):
if is_multiplayer_authority() and not is_carried:
if not is_multiplayer_authority() or not is_carried:
if controller and controller.has_method("_start_timer"):
controller._start_timer()
@@ -417,22 +426,24 @@ func spawn_tiles_around(count: int = 4):
# If it's a static turret, make it face the target tile it's about to spawn instead
if is_static_turret:
# We don't have a specific target yet, but we can pick an average direction
# Or just let it throw randomly like the others. Wait, the user wants:
# "static tekton, should facing toward where they're going to thrown the tiles"
# We'll calculate rotation inside the spawning loop for static turrets.
pass
else:
rotation.y = random_angle
# Play throw animation
if not is_carried and not is_thrown:
if not is_carried and not is_thrown and has_node("Visuals/tekton/Armature/AnimationPlayer"):
play_animation("tekton_throw_tile")
# Queue idle after animation finishes (approx 1.0s)
get_tree().create_timer(1.0).timeout.connect(func():
if not is_moving and not is_carried and not is_thrown:
play_animation("tekton_idle")
)
elif is_static_turret and not is_carried and not is_thrown:
play_animation("Armature|tekton_throw_tile")
get_tree().create_timer(1.0).timeout.connect(func():
if not is_moving and not is_carried and not is_thrown:
play_animation("Armature|tekton_idle")
)
print("[Tekton] Spawning %d tiles around %s" % [count, current_position])
@@ -453,6 +464,11 @@ func spawn_tiles_around(count: int = 4):
var throw_dir = Vector3(x, 0, y).normalized()
if throw_dir.length_squared() > 0.01:
rotation.y = atan2(throw_dir.x, throw_dir.z)
# Also make the visuals node rotate if needed (sometimes necessary for static items)
var visuals = get_node_or_null("Visuals")
if visuals:
visuals.rotation.y = 0 # keep base at 0 since parent rotated
# Don't overwrite the Tekton's own cell? Or do?
# Maybe avoid center.
@@ -496,8 +512,10 @@ func spawn_tiles_around(count: int = 4):
if LobbyManager:
mode = LobbyManager.get_game_mode()
if mode == GameMode.Mode.TEKTON_DOORS:
if LobbyManager and LobbyManager.get_game_mode() == GameMode.Mode.TEKTON_DOORS:
item_id = [11, 14].pick_random()
elif mode == GameMode.Mode.FREEMODE:
item_id = rng.randi_range(7, 10) # No powerups in freemode either, just normal tiles
else:
item_id = rng.randi_range(11, 14)
@@ -540,6 +558,11 @@ func play_animation(anim_name: String):
# Try specific user path first
var anim_player = get_node_or_null("Visuals/tekton/Armature/AnimationPlayer")
if is_static_turret:
anim_player = get_node_or_null("Visuals/static_tekton_mesh/tekton_throwing_tiles/AnimationPlayer")
if not anim_player:
anim_player = get_node_or_null("Visuals/tekton_throwing_tiles/AnimationPlayer") # Check direct child just in case
# If not found, try finding recursive
if not anim_player:
anim_player = find_child("AnimationPlayer", true, false)