update feature & bugfix
This commit is contained in:
@@ -51,8 +51,8 @@ func _ready():
|
||||
queue_free()
|
||||
return
|
||||
|
||||
# Wait for actor to be fully ready
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
# Wait for actor to be fully ready (player._ready awaits 0.5s then creates managers)
|
||||
await get_tree().create_timer(1.5).timeout
|
||||
|
||||
enhanced_gridmap = actor.enhanced_gridmap
|
||||
if not enhanced_gridmap:
|
||||
@@ -335,10 +335,23 @@ func _try_move() -> bool:
|
||||
_is_processing_action = true
|
||||
_current_action = "moving"
|
||||
|
||||
# Wait for movement to finish (signal from movement manager)
|
||||
await actor.movement_manager.movement_finished
|
||||
# Wait for movement to finish or timeout (safety)
|
||||
# Race: Signal vs Timeout
|
||||
# Since Godot 4 doesn't support 'await' racing easily without helper,
|
||||
# we'll just wait for the signal but ensure movement manager emits it.
|
||||
# safer approach: check if is_moving goes false
|
||||
|
||||
# Safety timeout to prevent infinite loop
|
||||
var max_wait_time = 2.0
|
||||
var elapsed = 0.0
|
||||
|
||||
while actor.is_player_moving and is_instance_valid(self):
|
||||
await get_tree().process_frame
|
||||
elapsed += get_process_delta_time()
|
||||
if elapsed > max_wait_time:
|
||||
print("[BotController] Movement timed out!")
|
||||
break
|
||||
|
||||
if not is_instance_valid(self): return true
|
||||
_is_processing_action = false
|
||||
_current_action = "idle"
|
||||
|
||||
@@ -42,10 +42,7 @@ func rotate_towards_target(target_pos: Vector2i):
|
||||
|
||||
func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
if is_moving:
|
||||
# Calculate direction for buffering
|
||||
var direction = grid_position - player.current_position
|
||||
|
||||
# FIX: Only buffer if direction is DIFFERENT from current move (prevents overshoot)
|
||||
if direction != current_move_direction:
|
||||
buffer_move_input(direction)
|
||||
return false
|
||||
@@ -53,11 +50,9 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
if not player.is_multiplayer_authority():
|
||||
return false
|
||||
|
||||
# Check if player is frozen
|
||||
if player.get("is_frozen"):
|
||||
return false
|
||||
|
||||
# Check if target is within 1-tile range
|
||||
var distance: int
|
||||
if use_diagonal_movement:
|
||||
distance = max(abs(grid_position.x - player.current_position.x), abs(grid_position.y - player.current_position.y))
|
||||
@@ -67,32 +62,23 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
if distance != 1:
|
||||
return false # Only single-step moves allowed
|
||||
|
||||
# Check if target position is within grid bounds
|
||||
if not enhanced_gridmap.is_position_valid(grid_position):
|
||||
return false
|
||||
|
||||
# Check for finish line logic (delegated back to player or race manager)
|
||||
if player.has_method("can_move_to_finish") and not player.can_move_to_finish(grid_position):
|
||||
return false
|
||||
|
||||
# Check walkability and obstacles
|
||||
var cell_item = enhanced_gridmap.get_cell_item(Vector3i(grid_position.x, 0, grid_position.y))
|
||||
if cell_item == -1 or cell_item in enhanced_gridmap.non_walkable_items:
|
||||
return false
|
||||
|
||||
# Check for player collision and try to push
|
||||
if player.is_position_occupied(grid_position):
|
||||
# Direction for the push
|
||||
var push_dir = grid_position - player.current_position
|
||||
if not try_push(grid_position, push_dir):
|
||||
return false
|
||||
# If push succeeded, the tile is now technically free (or will be processed as free)
|
||||
# proceed to move into it
|
||||
|
||||
# All checks passed, perform move
|
||||
rotate_towards_target(grid_position)
|
||||
|
||||
# Play walk animation (synced across network)
|
||||
if player.is_multiplayer_authority() and player.has_method("sync_walk_animation"):
|
||||
player.rpc("sync_walk_animation")
|
||||
|
||||
@@ -101,7 +87,6 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
|
||||
current_move_direction = grid_position - player.current_position
|
||||
|
||||
# Use the existing RPC to move
|
||||
player.rpc("start_movement_along_path", path, not (player.is_bot or player.is_in_group("Bots")))
|
||||
|
||||
return true
|
||||
@@ -119,15 +104,21 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
|
||||
# Check if pushed destination is valid
|
||||
if not enhanced_gridmap.is_position_valid(pushed_to_pos):
|
||||
# Blocked by world bounds -> Double Push!
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
return false
|
||||
|
||||
# Check walkability of pushed destination
|
||||
var cell_item = enhanced_gridmap.get_cell_item(Vector3i(pushed_to_pos.x, 0, pushed_to_pos.y))
|
||||
if cell_item == -1 or cell_item in enhanced_gridmap.non_walkable_items:
|
||||
# Blocked by obstacle -> Double Push!
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
return false
|
||||
|
||||
# Check if pushed destination is ALREADY occupied (no daisy chaining)
|
||||
# Check if pushed destination is ALREADY occupied (Double Push / Crush)
|
||||
if player.is_position_occupied(pushed_to_pos):
|
||||
# Blocked by another player -> Double Push!
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
return false
|
||||
|
||||
# Check if other player is currently moving (don't push moving players to avoid sync issues)
|
||||
|
||||
@@ -58,11 +58,22 @@ func _add_bar():
|
||||
# Type 1 = POWERUP message for special styling
|
||||
player.rpc("display_message", "Power-up bar filled!", 1)
|
||||
print("[PowerUp] Player %s gained 1 bar! Total: %d/%d points" % [player.name, current_points, MAX_POINTS])
|
||||
|
||||
if player.is_multiplayer_authority():
|
||||
player.get_node("PowerUpManager").rpc("sync_points", current_points)
|
||||
|
||||
# =============================================================================
|
||||
# Goal Completion Reward
|
||||
# =============================================================================
|
||||
|
||||
func acquire_smash_bonus():
|
||||
"""Called when player is smashed. Grants 1 bar up to a max of 2 bars."""
|
||||
if get_bars() < 2:
|
||||
_add_bar()
|
||||
print("[PowerUp] Player %s gained smash bonus bar! Total: %d/%d" % [player.name, current_points, MAX_POINTS])
|
||||
else:
|
||||
print("[PowerUp] Player %s smash bonus capped (already has >= 2 bars)" % player.name)
|
||||
|
||||
func add_goal_completion_reward():
|
||||
"""Called when player completes a goal pattern. Awards 1 bar."""
|
||||
_add_bar()
|
||||
|
||||
@@ -205,7 +205,8 @@ func set_local_player(player):
|
||||
|
||||
func _connect_powerup_manager_deferred(player):
|
||||
"""Wait for PowerUpManager to be initialized before connecting."""
|
||||
await player.get_tree().create_timer(0.3).timeout
|
||||
# player._ready waits 0.5s before creating managers, so wait longer
|
||||
await player.get_tree().create_timer(0.8).timeout
|
||||
|
||||
var powerup_manager = player.get_node_or_null("PowerUpManager")
|
||||
if powerup_manager:
|
||||
@@ -213,6 +214,8 @@ func _connect_powerup_manager_deferred(player):
|
||||
powerup_manager.points_changed.connect(_on_powerup_points_changed)
|
||||
# Initialize bar with current values
|
||||
update_powerup_bar(powerup_manager.get_points(), powerup_manager.get_max_points())
|
||||
else:
|
||||
push_warning("[UIManager] PowerUpManager not found on player after 0.8s wait")
|
||||
|
||||
# =============================================================================
|
||||
# Power-Up Bar UI (Battery Style)
|
||||
|
||||
Reference in New Issue
Block a user