update
This commit is contained in:
+128
-23
@@ -33,6 +33,15 @@ var is_frozen: bool = false
|
||||
var is_invisible: bool = false
|
||||
var original_movement_range: int = 1
|
||||
|
||||
# Tekton Interaction
|
||||
var carried_tekton: Node3D = null
|
||||
var is_carrying_tekton: bool:
|
||||
get: return is_carried_tekton
|
||||
set(value):
|
||||
is_carried_tekton = value
|
||||
# Visual/Logic side effects if any
|
||||
|
||||
var is_carried_tekton: bool = false
|
||||
var is_attack_mode: bool = false:
|
||||
set(value):
|
||||
if is_attack_mode == value:
|
||||
@@ -41,9 +50,9 @@ var is_attack_mode: bool = false:
|
||||
is_attack_mode = value
|
||||
# Visual feedback for attack mode (Red Tint)
|
||||
if is_attack_mode:
|
||||
_apply_tint_recursive(self, Color(1.0, 0.5, 0.5))
|
||||
_apply_tint_recursive(self , Color(1.0, 0.5, 0.5))
|
||||
else:
|
||||
_apply_tint_recursive(self, Color.WHITE)
|
||||
_apply_tint_recursive(self , Color.WHITE)
|
||||
|
||||
# Sync to others if we are the authority
|
||||
if is_multiplayer_authority():
|
||||
@@ -148,7 +157,7 @@ const AVAILABLE_CHARACTERS: Array[String] = ["Bob", "Masbro", "Gatot", "Oldpop"]
|
||||
set(value):
|
||||
is_my_turn = value
|
||||
if is_my_turn and is_multiplayer_authority():
|
||||
NotificationManager.send_message(self, NotificationManager.MESSAGES.TURN_START, NotificationManager.MessageType.NORMAL)
|
||||
NotificationManager.send_message(self , NotificationManager.MESSAGES.TURN_START, NotificationManager.MessageType.NORMAL)
|
||||
|
||||
@export var has_moved_this_turn = false
|
||||
|
||||
@@ -287,39 +296,39 @@ func _init_managers():
|
||||
movement_manager = load("res://scripts/managers/player_movement_manager.gd").new()
|
||||
movement_manager.name = "MovementManager"
|
||||
add_child(movement_manager)
|
||||
movement_manager.initialize(self, enhanced_gridmap)
|
||||
movement_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
race_manager = load("res://scripts/managers/player_race_manager.gd").new()
|
||||
race_manager.name = "RaceManager"
|
||||
add_child(race_manager)
|
||||
race_manager.initialize(self, enhanced_gridmap)
|
||||
race_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
# Skip InputManager for bots
|
||||
if not (is_bot or is_in_group("Bots")):
|
||||
input_manager = load("res://scripts/managers/player_input_manager.gd").new()
|
||||
input_manager.name = "InputManager"
|
||||
add_child(input_manager)
|
||||
input_manager.initialize(self, movement_manager, race_manager)
|
||||
input_manager.initialize(self , movement_manager, race_manager)
|
||||
|
||||
playerboard_manager = load("res://scripts/managers/playerboard_manager.gd").new()
|
||||
playerboard_manager.name = "PlayerboardManager"
|
||||
add_child(playerboard_manager)
|
||||
playerboard_manager.initialize(self, enhanced_gridmap)
|
||||
playerboard_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
action_manager = load("res://scripts/managers/player_action_manager.gd").new()
|
||||
action_manager.name = "ActionManager"
|
||||
add_child(action_manager)
|
||||
action_manager.initialize(self, enhanced_gridmap)
|
||||
action_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
special_tiles_manager = load("res://scripts/managers/special_tiles_manager.gd").new()
|
||||
special_tiles_manager.name = "SpecialTilesManager"
|
||||
add_child(special_tiles_manager)
|
||||
special_tiles_manager.initialize(self, enhanced_gridmap)
|
||||
special_tiles_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
powerup_manager = load("res://scripts/managers/powerup_manager.gd").new()
|
||||
powerup_manager.name = "PowerUpManager"
|
||||
add_child(powerup_manager)
|
||||
powerup_manager.initialize(self, enhanced_gridmap)
|
||||
powerup_manager.initialize(self , enhanced_gridmap)
|
||||
|
||||
# =============================================================================
|
||||
# Character Selection
|
||||
@@ -689,7 +698,7 @@ func apply_stagger(duration: float = 1.5):
|
||||
return # Already staggered
|
||||
|
||||
is_frozen = true
|
||||
_apply_tint_recursive(self, Color.BLUE) # Visual feedback
|
||||
_apply_tint_recursive(self , Color.BLUE) # Visual feedback
|
||||
|
||||
# Set immunity (3 seconds as requested)
|
||||
immunity_timer = 3.0
|
||||
@@ -697,7 +706,7 @@ func apply_stagger(duration: float = 1.5):
|
||||
print("Player %s staggered for %.1f seconds" % [name, duration])
|
||||
|
||||
if is_multiplayer_authority():
|
||||
NotificationManager.send_message(self, NotificationManager.MESSAGES.CRUSHED, NotificationManager.MessageType.WARNING)
|
||||
NotificationManager.send_message(self , NotificationManager.MESSAGES.CRUSHED, NotificationManager.MessageType.WARNING)
|
||||
drop_random_item()
|
||||
|
||||
# Grant "Smashed" Bonus (1 bar, max 2)
|
||||
@@ -709,20 +718,20 @@ func apply_stagger(duration: float = 1.5):
|
||||
is_frozen = false
|
||||
# If still immune, show immunity tint (Green?), otherwise White
|
||||
if immunity_timer > 0:
|
||||
_apply_tint_recursive(self, Color(0.5, 1.0, 0.5)) # Light Green for immunity
|
||||
_apply_tint_recursive(self , Color(0.5, 1.0, 0.5)) # Light Green for immunity
|
||||
else:
|
||||
_apply_tint_recursive(self, Color.WHITE) # Remove tint
|
||||
_apply_tint_recursive(self , Color.WHITE) # Remove tint
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func apply_slow_effect(duration: float = 3.0):
|
||||
# "area with blue like wall... Player who cross on that area will got slowed and freeze effect"
|
||||
# Visual: Blue Tint
|
||||
_apply_tint_recursive(self, Color(0.6, 0.8, 1.0)) # Icy Blue
|
||||
_apply_tint_recursive(self , Color(0.6, 0.8, 1.0)) # Icy Blue
|
||||
|
||||
# Logic: Slow Movement speed
|
||||
if movement_manager:
|
||||
# Use 0.2 multipliers to match "slowed" request (20% speed)
|
||||
movement_manager.set_speed_multiplier(0.2)
|
||||
movement_manager.set_speed_multiplier(0.2)
|
||||
|
||||
print("Player %s is slowed for %.1f seconds" % [name, duration])
|
||||
|
||||
@@ -740,9 +749,9 @@ func apply_slow_effect(duration: float = 3.0):
|
||||
movement_manager.set_speed_multiplier(1.0)
|
||||
|
||||
if immunity_timer > 0:
|
||||
_apply_tint_recursive(self, Color(0.5, 1.0, 0.5))
|
||||
_apply_tint_recursive(self , Color(0.5, 1.0, 0.5))
|
||||
else:
|
||||
_apply_tint_recursive(self, Color.WHITE)
|
||||
_apply_tint_recursive(self , Color.WHITE)
|
||||
|
||||
func playerboard_is_empty() -> bool:
|
||||
for item in playerboard:
|
||||
@@ -779,7 +788,7 @@ func drop_random_item():
|
||||
var cell = Vector3i(drop_pos.x, 0, drop_pos.y)
|
||||
rpc("sync_grid_item", cell.x, cell.y, cell.z, item_id)
|
||||
|
||||
NotificationManager.send_message(self, NotificationManager.MESSAGES.DROPPED_ITEM, NotificationManager.MessageType.WARNING)
|
||||
NotificationManager.send_message(self , NotificationManager.MESSAGES.DROPPED_ITEM, NotificationManager.MessageType.WARNING)
|
||||
print("Player %s dropped item %d at %s" % [name, item_id, drop_pos])
|
||||
|
||||
|
||||
@@ -805,7 +814,7 @@ func drop_all_tiles():
|
||||
if dropped_count > 0:
|
||||
rpc("sync_playerboard", playerboard)
|
||||
rpc("trigger_screen_shake", "targeted")
|
||||
NotificationManager.send_message(self, NotificationManager.MESSAGES.CRITICALLY_HIT, NotificationManager.MessageType.WARNING)
|
||||
NotificationManager.send_message(self , NotificationManager.MESSAGES.CRITICALLY_HIT, NotificationManager.MessageType.WARNING)
|
||||
print("Player %s dropped %d tiles due to Super Push" % [name, dropped_count])
|
||||
|
||||
func _find_valid_drop_position() -> Vector2i:
|
||||
@@ -865,7 +874,7 @@ func attempt_target_action(target_index: int):
|
||||
|
||||
if target_player == self and effect != 4: # 4 = INVISIBLE (Self)
|
||||
# Trying to target self with harmful effect?
|
||||
NotificationManager.send_message(self, NotificationManager.MESSAGES.CANT_TARGET_SELF, NotificationManager.MessageType.WARNING)
|
||||
NotificationManager.send_message(self , NotificationManager.MESSAGES.CANT_TARGET_SELF, NotificationManager.MessageType.WARNING)
|
||||
return
|
||||
|
||||
# 3. Activate Effect
|
||||
@@ -941,7 +950,7 @@ func _process(delta):
|
||||
immunity_timer -= delta
|
||||
if immunity_timer <= 0:
|
||||
immunity_timer = 0
|
||||
_apply_tint_recursive(self, Color.WHITE) # Remove immunity tint
|
||||
_apply_tint_recursive(self , Color.WHITE) # Remove immunity tint
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func ping_existence():
|
||||
@@ -1179,13 +1188,16 @@ func start_movement_along_path(path: Array, clear_visual: bool = true):
|
||||
|
||||
for point in path:
|
||||
# Use global_position for consistency
|
||||
tween.tween_property(self, "global_position", grid_to_world(Vector2i(point.x, point.y)), step_duration)
|
||||
tween.tween_property(self , "global_position", grid_to_world(Vector2i(point.x, point.y)), step_duration)
|
||||
|
||||
tween.tween_callback(func():
|
||||
current_position = Vector2i(path[-1].x, path[-1].y)
|
||||
is_player_moving = false
|
||||
target_position = Vector2i(-1, -1)
|
||||
|
||||
if is_carrying_tekton and is_instance_valid(carried_tekton):
|
||||
carried_tekton.current_position = current_position
|
||||
|
||||
# FORCE SNAP: Update target visual position to the perfect grid center
|
||||
# This ensures that when interpolation resumes (in _process), it pulls to the correct spot
|
||||
target_visual_position = grid_to_world(current_position)
|
||||
@@ -1797,3 +1809,96 @@ func set_spawn_position(pos: Vector2i):
|
||||
func complete_race(final_position: int):
|
||||
if race_manager:
|
||||
race_manager.on_race_completed(final_position)
|
||||
|
||||
# =============================================================================
|
||||
# Tekton Interaction Logic
|
||||
# =============================================================================
|
||||
|
||||
func grab_tekton():
|
||||
if not is_multiplayer_authority() or is_carrying_tekton or is_frozen:
|
||||
return
|
||||
|
||||
# Find nearby Tekton
|
||||
var tekton = _find_nearby_tekton()
|
||||
if tekton:
|
||||
if is_multiplayer_authority():
|
||||
rpc("sync_grab_tekton", tekton.get_path())
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_grab_tekton(tekton_path: NodePath):
|
||||
var tekton = get_node_or_null(tekton_path)
|
||||
if tekton:
|
||||
carried_tekton = tekton
|
||||
is_carrying_tekton = true
|
||||
tekton.set_carried(true, self )
|
||||
print("[Player %s] Grabbed Tekton %s" % [name, tekton.name])
|
||||
|
||||
func throw_tekton():
|
||||
if not is_multiplayer_authority() or not is_carrying_tekton:
|
||||
return
|
||||
|
||||
# Determine throw direction (where player is facing)
|
||||
# For simplicity, we use the player's current rotation to find the target tile
|
||||
var forward = - global_transform.basis.z.normalized()
|
||||
var throw_dir = Vector2i(round(forward.x), round(forward.z))
|
||||
if throw_dir == Vector2i.ZERO: throw_dir = Vector2i(1, 0) # Fallback
|
||||
|
||||
var target_pos = current_position + throw_dir
|
||||
|
||||
if is_multiplayer_authority():
|
||||
rpc("sync_throw_tekton", target_pos)
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_throw_tekton(target_pos: Vector2i):
|
||||
if carried_tekton:
|
||||
var tekton = carried_tekton
|
||||
carried_tekton = null
|
||||
is_carrying_tekton = false
|
||||
tekton.set_carried(false)
|
||||
|
||||
# Move Tekton to target pos
|
||||
tekton.current_position = target_pos
|
||||
|
||||
# Intensity 0.5 for throw (drops 50% tiles)
|
||||
tekton.on_hit(self , 0.5)
|
||||
|
||||
print("[Player %s] Threw Tekton to %s" % [name, target_pos])
|
||||
|
||||
func knock_tekton():
|
||||
if not is_multiplayer_authority() or is_frozen:
|
||||
return
|
||||
|
||||
# Requirement: Full Powerup Bar
|
||||
if not powerup_manager or not powerup_manager.can_use_special():
|
||||
NotificationManager.send_message(self , "Need Full Boost to Knock!", NotificationManager.MessageType.WARNING)
|
||||
return
|
||||
|
||||
var tekton = _find_nearby_tekton()
|
||||
if tekton:
|
||||
# Consume Boost
|
||||
powerup_manager.consume_boost(100.0)
|
||||
|
||||
if is_multiplayer_authority():
|
||||
rpc("sync_knock_tekton", tekton.get_path())
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_knock_tekton(tekton_path: NodePath):
|
||||
var tekton = get_node_or_null(tekton_path)
|
||||
if tekton:
|
||||
# Intensity 2.0 for knock (drops 200% tiles)
|
||||
tekton.on_hit(self , 2.0)
|
||||
print("[Player %s] Knocked Tekton %s" % [name, tekton.name])
|
||||
|
||||
# Visual feedback (Juice)
|
||||
if is_multiplayer_authority():
|
||||
rpc("trigger_screen_shake", "heavy")
|
||||
|
||||
func _find_nearby_tekton() -> Node3D:
|
||||
var tektons = get_tree().get_nodes_in_group("Tektons")
|
||||
for tekton in tektons:
|
||||
if tekton.is_carried: continue
|
||||
|
||||
var dist = (tekton.current_position - current_position).length()
|
||||
if dist <= 1.5: # Adjacent (1.0 or 1.41)
|
||||
return tekton
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user