fix(candy-survival): implement stagger (knockdown), lunge visual bump, and target stealing/backfire animations for Knock (Q)
This commit is contained in:
@@ -395,11 +395,21 @@ func try_knock(attacker: int, target: int) -> bool:
|
|||||||
var target_colors = player_candy_colors.get(target, [])
|
var target_colors = player_candy_colors.get(target, [])
|
||||||
var target_candies = target_colors.size()
|
var target_candies = target_colors.size()
|
||||||
|
|
||||||
|
var attacker_node = main_scene.get_node_or_null(str(attacker))
|
||||||
|
var target_node = main_scene.get_node_or_null(str(target))
|
||||||
|
|
||||||
|
if attacker_node and target_node:
|
||||||
|
attacker_node.rpc("sync_bump", target_node.current_position)
|
||||||
|
|
||||||
if target_candies == 0:
|
if target_candies == 0:
|
||||||
# Backfire: both lose a charge
|
# Backfire: both lose a charge
|
||||||
player_knocks[attacker] = player_knocks.get(attacker, 0) - 1
|
player_knocks[attacker] = player_knocks.get(attacker, 0) - 1
|
||||||
rpc("sync_knock_charge_count", attacker, player_knocks[attacker])
|
rpc("sync_knock_charge_count", attacker, player_knocks[attacker])
|
||||||
# Attacker is also knocked down briefly (visual handled by caller)
|
|
||||||
|
# Attacker is also knocked down briefly (backfire)
|
||||||
|
if attacker_node:
|
||||||
|
attacker_node.rpc("apply_stagger", 2.0)
|
||||||
|
|
||||||
rpc("sync_knock_result", attacker, target, 0)
|
rpc("sync_knock_result", attacker, target, 0)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
@@ -416,6 +426,10 @@ func try_knock(attacker: int, target: int) -> bool:
|
|||||||
rpc("sync_knock_charge_count", attacker, player_knocks[attacker])
|
rpc("sync_knock_charge_count", attacker, player_knocks[attacker])
|
||||||
player_last_knocked_by[target] = attacker
|
player_last_knocked_by[target] = attacker
|
||||||
|
|
||||||
|
# Target is knocked down / staggered on successful knock
|
||||||
|
if target_node:
|
||||||
|
target_node.rpc("apply_stagger", 2.0)
|
||||||
|
|
||||||
_add_score(attacker, target_candies * 100)
|
_add_score(attacker, target_candies * 100)
|
||||||
_update_candy_badge(attacker)
|
_update_candy_badge(attacker)
|
||||||
_update_candy_badge(target)
|
_update_candy_badge(target)
|
||||||
|
|||||||
@@ -119,22 +119,35 @@ func handle_unhandled_input(event):
|
|||||||
if LobbyManager.game_mode == "Candy Survival":
|
if LobbyManager.game_mode == "Candy Survival":
|
||||||
var gm = player.get_node_or_null("/root/Main/CandySurvivalManager")
|
var gm = player.get_node_or_null("/root/Main/CandySurvivalManager")
|
||||||
if gm and gm.active:
|
if gm and gm.active:
|
||||||
|
var att_id = player.get("peer_id") if "peer_id" in player else player.name.to_int()
|
||||||
|
if gm.player_knocks.get(att_id, 0) <= 0:
|
||||||
|
NotificationManager.send_message(player, "No Knock charges left!", NotificationManager.MessageType.WARNING)
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
return
|
||||||
|
|
||||||
# Find a target to knock (first adjacent player)
|
# Find a target to knock (first adjacent player)
|
||||||
var p_pos = player.current_position
|
var p_pos = player.current_position
|
||||||
var all_players = get_tree().get_nodes_in_group("Players")
|
var all_players = get_tree().get_nodes_in_group("Players")
|
||||||
|
var target_found = null
|
||||||
for other in all_players:
|
for other in all_players:
|
||||||
if other == player: continue
|
if other == player: continue
|
||||||
var other_pos = other.current_position
|
var other_pos = other.current_position
|
||||||
if abs(p_pos.x - other_pos.x) + abs(p_pos.y - other_pos.y) == 1:
|
if abs(p_pos.x - other_pos.x) + abs(p_pos.y - other_pos.y) == 1:
|
||||||
# Adjacent
|
target_found = other
|
||||||
var att_id = player.get("peer_id") if "peer_id" in player else player.name.to_int()
|
break
|
||||||
var tgt_id = other.get("peer_id") if "peer_id" in other else other.name.to_int()
|
|
||||||
if multiplayer.is_server():
|
if target_found:
|
||||||
gm.try_knock(att_id, tgt_id)
|
var tgt_id = target_found.get("peer_id") if "peer_id" in target_found else target_found.name.to_int()
|
||||||
else:
|
if multiplayer.is_server():
|
||||||
gm.rpc_id(1, "try_knock", att_id, tgt_id)
|
gm.try_knock(att_id, tgt_id)
|
||||||
get_viewport().set_input_as_handled()
|
else:
|
||||||
return
|
gm.rpc_id(1, "try_knock", att_id, tgt_id)
|
||||||
|
else:
|
||||||
|
# No target, but play the bump animation anyway in place
|
||||||
|
player.rpc("sync_bump", p_pos)
|
||||||
|
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
return
|
||||||
|
|
||||||
if player.powerup_manager:
|
if player.powerup_manager:
|
||||||
player.powerup_manager.use_special_effect()
|
player.powerup_manager.use_special_effect()
|
||||||
|
|||||||
Reference in New Issue
Block a user