feat: update candy logic

This commit is contained in:
2026-07-07 18:08:49 +08:00
parent 04e40f5b76
commit 286d0ce069
5 changed files with 26 additions and 26 deletions
+1 -1
View File
@@ -299,7 +299,7 @@ func _try_activate_ghost() -> bool:
return false
var gm = strategic_planner._get_candy_survival_manager()
if not gm or not gm.is_active:
if not gm or not gm.active:
return false
var pid = actor.get("peer_id") if "peer_id" in actor else actor.name.to_int()
+2 -2
View File
@@ -103,7 +103,7 @@ func handle_unhandled_input(event):
if event.is_action_pressed("action_knock_tekton"):
if LobbyManager.game_mode == "Candy Survival":
var gm = player.get_node_or_null("/root/Main/CandySurvivalManager")
if gm and gm.is_active:
if gm and gm.active:
# Find a target to knock (first adjacent player)
var p_pos = player.current_position
var all_players = get_tree().get_nodes_in_group("Players")
@@ -130,7 +130,7 @@ func handle_unhandled_input(event):
elif event.is_action_pressed("action_grab_tekton"):
if LobbyManager.game_mode == "Candy Survival":
var gm = player.get_node_or_null("/root/Main/CandySurvivalManager")
if gm and gm.is_active:
if gm and gm.active:
var pid = player.get("peer_id") if "peer_id" in player else player.name.to_int()
if multiplayer.is_server():
gm.try_activate_ghost(pid)
+18 -18
View File
@@ -157,7 +157,7 @@ func simple_move_to(grid_position: Vector2i) -> bool:
# If moving into a sticky cell: block movement unless player is in ghost
# mode (is_invisible), which lets them bypass sticky tiles in Candy Survival
if gm and gm.is_active and gm.is_sticky_cell(grid_position):
if gm and gm.active and gm.is_sticky_cell(grid_position):
if player.get("is_invisible"):
# Ghost mode: walk through sticky tile freely
print("[Move] Ghost mode bypassed sticky cell at %s" % grid_position)
@@ -165,7 +165,7 @@ func simple_move_to(grid_position: Vector2i) -> bool:
print("[Move] Failed: Blocked by Candy Survival Sticky cell at %s" % grid_position)
return false
if gm and gm.is_active and gm.has_method("try_deliver"):
if gm and gm.active and gm.has_method("try_deliver"):
var dist = abs(grid_position.x - 8) + abs(grid_position.y - 8)
if dist <= 2:
var pid = player.get("peer_id") if "peer_id" in player else player.name.to_int()
@@ -214,14 +214,14 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
# === INVULNERABILITY CHECK ===
if other_player.get("is_carrying_tekton"):
print("[Move] Push blocked: Target is carrying a Tekton and is invulnerable.")
NotificationManager.send_message(player, "Target is Immune!", NotificationManager.MessageType.WARNING)
Engine.get_main_loop().root.get_node_or_null("NotificationManager").send_message(player, "Target is Immune!", Engine.get_main_loop().root.get_node_or_null("NotificationManager").MessageType.WARNING)
return false
# Candy Survival: check if attacker has knock charges
var has_knock = false
var main_for_knock = player.get_tree().root.get_node_or_null("Main")
var gm_for_knock = main_for_knock.get("candy_survival_manager") if main_for_knock else null
if gm_for_knock and gm_for_knock.is_active:
if gm_for_knock and gm_for_knock.active:
var att_pid = player.get("peer_id") if "peer_id" in player else player.name.to_int()
var charges = gm_for_knock.player_knocks.get(att_pid, 0) if gm_for_knock.player_knocks else 0
has_knock = charges > 0
@@ -236,18 +236,18 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
return false
# SAFE ZONE PROTECTION (Only in Stop n Go)
if LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO):
if Engine.get_main_loop().root.get_node_or_null("LobbyManager").is_game_mode(GameMode.Mode.STOP_N_GO):
var safe_columns = [6, 7, 8, 14, 15, 16]
# 1. Prevent attacker from attacking IF THEY ARE in a Safe Zone
if player.current_position.x in safe_columns:
print(" - Attack BLOCKED: Attacker is in Safe Zone!")
NotificationManager.send_message(player, "Cannot Attack while in Safe Zone!", NotificationManager.MessageType.WARNING)
Engine.get_main_loop().root.get_node_or_null("NotificationManager").send_message(player, "Cannot Attack while in Safe Zone!", Engine.get_main_loop().root.get_node_or_null("NotificationManager").MessageType.WARNING)
return false
# 2. Prevent attacking players WHO ARE in a Safe Zone (existing logic)
if target_pos.x in safe_columns:
print(" - Attack BLOCKED: Target is in Safe Zone!")
NotificationManager.send_message(player, "Target is in Safe Zone!", NotificationManager.MessageType.WARNING)
Engine.get_main_loop().root.get_node_or_null("NotificationManager").send_message(player, "Target is in Safe Zone!", Engine.get_main_loop().root.get_node_or_null("NotificationManager").MessageType.WARNING)
return false
@@ -257,7 +257,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
gm = main_push_check.candy_survival_manager
# Candy Survival: knock mechanic (candy-steal or backfire)
if gm and gm.is_active and gm.has_method("try_knock"):
if gm and gm.active and gm.has_method("try_knock"):
var pid = player.get("peer_id") if "peer_id" in player else player.name.to_int()
var other_pid = other_player.get("peer_id") if "peer_id" in other_player else other_player.name.to_int()
if gm.try_knock(pid, other_pid):
@@ -274,17 +274,17 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
# Visual Feedback: Attack Bump
if _can_rpc():
player.rpc("sync_bump", target_pos, false) # Attack bump
SfxManager.rpc("play_rpc", "attack_mode")
Engine.get_main_loop().root.get_node_or_null("SfxManager").rpc("play_rpc", "attack_mode")
elif player.has_method("sync_bump"):
player.sync_bump(target_pos, false)
SfxManager.play("attack_mode")
Engine.get_main_loop().root.get_node_or_null("SfxManager").play("attack_mode")
# 1. 3-Floor Knockback
var push_direction = Vector2i(-1, 0) # Default back (Stop N Go)
var main_push = player.get_tree().root.get_node_or_null("Main")
var gm_push = main_push.candy_survival_manager if main_push and main_push.has_node("CandySurvivalManager") else (main_push.get("candy_survival_manager") if main_push else null)
if gm_push and gm_push.is_active:
if gm_push and gm_push.active:
push_direction = direction # Use the direction of the attack
var pushed_to_pos = target_pos
var push_path = []
@@ -297,7 +297,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
pushed_to_pos = next_back
push_path.append(Vector2(pushed_to_pos.x, pushed_to_pos.y))
if gm_push and gm_push.is_active and gm_push.is_sticky_cell(pushed_to_pos):
if gm_push and gm_push.active and gm_push.is_sticky_cell(pushed_to_pos):
hit_sticky = true
break # stop pushing immediately upon touching sticky zone!
else:
@@ -320,7 +320,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
var main_sticky = player.get_tree().root.get_node_or_null("Main")
if main_sticky and main_sticky.get("candy_survival_manager"):
var gm_sticky = main_sticky.candy_survival_manager
if gm_sticky.is_active and gm_sticky.is_sticky_cell(pushed_to_pos):
if gm_sticky.active and gm_sticky.is_sticky_cell(pushed_to_pos):
if other_player.get("is_invisible"):
# Ghost mode: pushed player bypasses sticky
print("[Move] Ghost mode bypassed push-into-sticky at %s" % pushed_to_pos)
@@ -330,7 +330,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
gm_sticky.apply_sticky_slow(other_player)
# 2. Apply freeze/stun effect
var stun_duration = 1.0 if (gm_push and gm_push.is_active) else 1.5
var stun_duration = 1.0 if (gm_push and gm_push.active) else 1.5
if _can_rpc():
other_player.rpc("apply_stagger", stun_duration)
else:
@@ -347,7 +347,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
# SCORING: 200 Points for successful attack (ONLY in Free Mode)
if player.is_multiplayer_authority():
var is_sng = LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO)
var is_sng = Engine.get_main_loop().root.get_node_or_null("LobbyManager").is_game_mode(GameMode.Mode.STOP_N_GO)
if not is_sng:
var main_score = player.get_tree().get_root().get_node_or_null("Main")
if main_score:
@@ -359,9 +359,9 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
else:
# Client: Request score add (sender ID used)
gcm.rpc("request_add_score", 200)
NotificationManager.send_message(player, "Successful Attack! +200 Pts", NotificationManager.MessageType.GOAL)
Engine.get_main_loop().root.get_node_or_null("NotificationManager").send_message(player, "Successful Attack! +200 Pts", Engine.get_main_loop().root.get_node_or_null("NotificationManager").MessageType.GOAL)
else:
NotificationManager.send_message(player, "Successful Attack!", NotificationManager.MessageType.GOAL)
Engine.get_main_loop().root.get_node_or_null("NotificationManager").send_message(player, "Successful Attack!", Engine.get_main_loop().root.get_node_or_null("NotificationManager").MessageType.GOAL)
# 5. Block the attacker from moving into the victim's space to prevent overlapping
return false
@@ -379,7 +379,7 @@ pass
func _on_movement_finished():
# Auto-pickup logic for Candy Survival
if LobbyManager.game_mode == "Candy Survival":
if Engine.get_main_loop().root.get_node_or_null("LobbyManager").game_mode == "Candy Survival":
if player.has_method("grab_item"):
# Check if there is an item at current_position and if the board has space
if player.playerboard_manager and player.playerboard_manager.has_empty_slot():