feat: introduce core player logic with manager integration and power-up inventory UI.

This commit is contained in:
Yogi Wiguna
2026-03-04 15:56:03 +08:00
parent a78acd12b8
commit 8f03cc15c5
5 changed files with 123 additions and 174 deletions
+55 -80
View File
@@ -26,7 +26,6 @@ const FREEZE_SLOW_DURATION = 3.0
signal cooldown_updated(effect: int, time_left: float, max_time: float)
signal powerup_unlocked(effect: int, level: int)
var wall_orientation_horizontal: bool = false # False = Vertical, True = Horizontal
# New Helper functions for Targeting and Preview
@@ -35,28 +34,12 @@ func get_skill_affected_area(effect: int, center_pos: Vector2i) -> Array[Vector2
match effect:
SpecialEffect.AREA_FREEZE:
var current_lvl = powerup_levels.get(SpecialEffect.AREA_FREEZE, 1)
var radius = 1
if current_lvl >= 5:
radius = 2
for x in range(-radius, radius + 1):
for y in range(-radius, radius + 1):
var pos = center_pos + Vector2i(x, y)
# Validate bounds
if enhanced_gridmap.is_position_valid(pos):
area.append(pos)
# Preview 3 blocks ahead of current hover (if we ever re-enable targeting)
area.append(center_pos)
SpecialEffect.BLOCK_FLOOR:
# Logic: Based on toggled orientation state
var is_horizontal = wall_orientation_horizontal
if is_horizontal:
for x in range(enhanced_gridmap.columns):
area.append(Vector2i(x, center_pos.y))
else:
for z in range(enhanced_gridmap.rows):
area.append(Vector2i(center_pos.x, z))
# Preview just the single block
area.append(center_pos)
return area
@@ -143,12 +126,8 @@ func get_effect_from_item(item_id: int) -> int:
match item_id:
11: return SpecialEffect.FASTER_SPEED
12:
if is_restricted: return -1
return SpecialEffect.AREA_FREEZE
13:
if is_restricted: return -1
return SpecialEffect.BLOCK_FLOOR
12: return SpecialEffect.AREA_FREEZE
13: return SpecialEffect.BLOCK_FLOOR
14: return SpecialEffect.INVISIBLE_MODE
_: return -1
@@ -231,32 +210,11 @@ func activate_effect(effect: int, target_player: Node3D = null):
SpecialEffect.FASTER_SPEED:
_execute_faster_speed()
SpecialEffect.AREA_FREEZE, SpecialEffect.BLOCK_FLOOR:
# Enter Targeting Mode instead of executing immediately (ONLY for human players)
if not (player.is_bot or player.is_in_group("Bots")):
var main = player.get_tree().get_root().get_node_or_null("Main")
if main and main.ui_manager:
# Toggle Logic for Wall Block
if main.ui_manager.current_action_state == main.ui_manager.ActionState.TARGETING and main.ui_manager.pending_skill_id == effect:
if effect == SpecialEffect.BLOCK_FLOOR:
toggle_wall_orientation()
powerup_cooldowns[effect] = 0.0 # Revert cooldown
emit_signal("cooldown_updated", effect, 0.0, 0.0)
return
main.ui_manager.current_action_state = main.ui_manager.ActionState.TARGETING
main.ui_manager.pending_skill_id = effect
var msg = "Select a target area..."
if effect == SpecialEffect.BLOCK_FLOOR:
msg = "Click again to toggle Vertical/Horizontal"
NotificationManager.send_message(player, msg, NotificationManager.MessageType.NORMAL)
# Do NOT set cooldown yet. Cooldown sets on execution.
# Revert the cooldown set above (hacky but handles the split flow)
powerup_cooldowns[effect] = 0.0
emit_signal("cooldown_updated", effect, 0.0, 0.0)
print("[SpecialTiles] Entered Targeting Mode for %s" % SpecialEffect.keys()[effect])
return # Exit, wait for input
# Execute immediately based on direction instead of entering Targeting Mode
if effect == SpecialEffect.BLOCK_FLOOR:
_execute_block_floor()
else:
_execute_area_freeze()
SpecialEffect.INVISIBLE_MODE:
_execute_invisible_mode(player)
@@ -284,13 +242,33 @@ func _execute_faster_speed():
active_buffs[SpecialEffect.FASTER_SPEED] = FASTER_DURATION
NotificationManager.send_message(player, "Speed Boost! (5s)", NotificationManager.MessageType.POWERUP)
func _execute_area_freeze(center_pos: Vector2i = Vector2i.ZERO):
func _execute_area_freeze(target_pos: Vector2i = Vector2i.ZERO):
var center_pos = target_pos
# Determine Level early for distance calculation
var current_lvl = powerup_levels.get(SpecialEffect.AREA_FREEZE, 1)
if center_pos == Vector2i.ZERO:
# Fallback to old behavior if no target provided (or error)
return
# Calculate distance ahead based on Level
# Gap of 3 floors = 4 tiles ahead
# Gap of 5 floors = 6 tiles ahead
var distance = 4 if current_lvl < 5 else 6
var movement = player.movement_manager
if movement and movement.current_move_direction != Vector2i.ZERO:
center_pos = player.current_position + movement.current_move_direction * distance
else:
# Fallback if standing still
var last_dir = player.movement_manager.last_move_direction if movement else Vector2i(0, 1)
center_pos = player.current_position + last_dir * distance
if not enhanced_gridmap.is_position_valid(center_pos):
# Try a bit closer if out of bounds
center_pos = player.current_position + (center_pos - player.current_position).normalized() * 1.0
if not enhanced_gridmap.is_position_valid(center_pos):
return
# 3. Determine Radius based on Level
var current_lvl = powerup_levels.get(SpecialEffect.AREA_FREEZE, 1)
var radius = 1
if current_lvl >= 5:
radius = 2 # Bigger area at high levels
@@ -366,29 +344,29 @@ func _execute_area_freeze(center_pos: Vector2i = Vector2i.ZERO):
main.rpc("sync_grid_items_batch", restore_batch)
)
func toggle_wall_orientation():
wall_orientation_horizontal = !wall_orientation_horizontal
var mode_str = "HORIZONTAL" if wall_orientation_horizontal else "VERTICAL"
NotificationManager.send_message(player, "Wall Mode: " + mode_str, NotificationManager.MessageType.NORMAL)
func _execute_block_floor(target_pos: Vector2i):
# "Wall Block"
var is_horizontal = wall_orientation_horizontal
func _execute_block_floor(target_pos: Vector2i = Vector2i.ZERO):
# "Wall Block" - Spawn line behind player
var behind_pos = target_pos
var last_dir = player.movement_manager.last_move_direction if player.movement_manager else Vector2i(0, 1)
if behind_pos == Vector2i.ZERO:
behind_pos = player.current_position - last_dir
if not enhanced_gridmap.is_position_valid(behind_pos):
return
print("Player %s activated Wall Block behind at %s" % [player.name, behind_pos])
var neighbors = []
if is_horizontal:
# Block entire Row (Fixed Z, iterate all X)
var row_z = target_pos.y
for x in range(enhanced_gridmap.columns):
neighbors.append({"position": Vector2i(x, row_z)})
print("Player %s activated Wall Block: HORIZONTAL ROW (Z=%d)" % [player.name, row_z])
else:
# Block entire Column (Fixed X, iterate all Z)
var col_x = target_pos.x
if last_dir.x != 0:
# Moving on X-axis (Columns) -> Vertical Wall (Fixed X, all Z)
for z in range(enhanced_gridmap.rows):
neighbors.append({"position": Vector2i(col_x, z)})
print("Player %s activated Wall Block: VERTICAL COLUMN (X=%d)" % [player.name, col_x])
neighbors.append({"position": Vector2i(behind_pos.x, z)})
else:
# Moving on Z-axis (Rows) -> Horizontal Wall (Fixed Z, all X)
for x in range(enhanced_gridmap.columns):
neighbors.append({"position": Vector2i(x, behind_pos.y)})
if player.is_multiplayer_authority():
var main = player.get_tree().get_root().get_node_or_null("Main")
@@ -420,10 +398,7 @@ func _execute_block_floor(target_pos: Vector2i):
main.rpc("sync_grid_items_batch", batch_data)
# Notify
var all_players = player.get_tree().get_nodes_in_group("Players")
for p in all_players:
if p.current_position == target_pos:
NotificationManager.send_message(p, "Wall Block Created!", NotificationManager.MessageType.POWERUP)
NotificationManager.send_message(player, "Defensive Wall Deployed!", NotificationManager.MessageType.POWERUP)
func _execute_invisible_mode(target: Node3D):
target.is_invisible = true