feat: Implement Tekton roaming NPC with movement, combat, carry, throw, and knock mechanics.
This commit is contained in:
@@ -288,7 +288,8 @@ func add_score(peer_id: int, amount: int):
|
||||
player_scores[peer_id] += amount
|
||||
|
||||
# Sync
|
||||
rpc("sync_player_score", peer_id, player_scores[peer_id])
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
rpc("sync_player_score", peer_id, player_scores[peer_id])
|
||||
print("[GoalsCycle] Added %d points to Player %d. Total: %d" % [amount, peer_id, player_scores[peer_id]])
|
||||
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func after_action_completed():
|
||||
main.update_all_players_boards()
|
||||
|
||||
# Sync playerboard (Bots DO need to sync their board logic, just not update local UI)
|
||||
if player.is_multiplayer_authority():
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
var main = player.get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
main.rpc("sync_playerboard", player.name.to_int(), player.playerboard)
|
||||
|
||||
@@ -38,7 +38,7 @@ func rotate_towards_target(target_pos: Vector2i):
|
||||
if direction != Vector3.ZERO:
|
||||
target_rotation = atan2(direction.x, direction.z)
|
||||
# Sync rotation to other clients
|
||||
if player.is_multiplayer_authority():
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
player.rpc("sync_rotation", target_rotation)
|
||||
|
||||
func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
@@ -108,7 +108,9 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
|
||||
rotate_towards_target(grid_position)
|
||||
|
||||
if player.is_multiplayer_authority() and multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
rotate_towards_target(grid_position)
|
||||
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
if player.has_method("sync_walk_animation"):
|
||||
player.rpc("sync_walk_animation")
|
||||
|
||||
@@ -117,7 +119,7 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
|
||||
current_move_direction = grid_position - player.current_position
|
||||
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
player.rpc("start_movement_along_path", path, not (player.is_bot or player.is_in_group("Bots")))
|
||||
|
||||
return true
|
||||
@@ -139,9 +141,18 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
# === SUPER PUSH (Attack Mode) ===
|
||||
print("Player %s SUPER PUSHING %s!" % [player.name, other_player.name])
|
||||
|
||||
# SAFE ZONE PROTECTION
|
||||
# Columns 6, 7, 8 and 14, 15, 16 are Safe Zones
|
||||
var safe_columns = [6, 7, 8, 14, 15, 16]
|
||||
if target_pos.x in safe_columns:
|
||||
print(" - Attack BLOCKED by Safe Zone!")
|
||||
NotificationManager.send_message(player, "Cannot Attack in Safe Zone!", NotificationManager.MessageType.WARNING)
|
||||
return false
|
||||
|
||||
# 1. Drop Victim's Tiles
|
||||
if other_player.has_method("drop_all_tiles"):
|
||||
other_player.rpc("drop_all_tiles") # Sync drop
|
||||
if player.has_method("can_rpc") and player.can_rpc():
|
||||
other_player.rpc("drop_all_tiles") # Sync drop
|
||||
|
||||
# 2. Spawn PowerUps around Victim
|
||||
# We delegate this to the attacker's SpecialTilesManager to handle the spawning authority
|
||||
@@ -158,15 +169,18 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
not _is_position_blocked_by_physics(pushed_to_pos):
|
||||
# Valid push
|
||||
var push_path = [Vector2(pushed_to_pos.x, pushed_to_pos.y)]
|
||||
other_player.rpc("start_movement_along_path", push_path, false)
|
||||
if player.has_method("can_rpc") and player.can_rpc():
|
||||
other_player.rpc("start_movement_along_path", push_path, false)
|
||||
other_player.target_position = pushed_to_pos # Logical update
|
||||
|
||||
# Apply stun/freeze effect as requested (same as wall stagger)
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
if player.has_method("can_rpc") and player.can_rpc():
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
|
||||
else:
|
||||
# Wall/Blocked -> Stagger in place
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
if player.has_method("can_rpc") and player.can_rpc():
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
|
||||
# 4. Consume Boost (Full) - One hit per charge
|
||||
if player.powerup_manager:
|
||||
|
||||
@@ -74,7 +74,7 @@ func _on_boost_full():
|
||||
NotificationManager.send_message(player, NotificationManager.MESSAGES.ATTACK_MODE_READY, NotificationManager.MessageType.POWERUP)
|
||||
print("[PowerUp] Player %s Boost Full! Ready for Attack Mode." % player.name)
|
||||
|
||||
if player.is_multiplayer_authority():
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
rpc("sync_boost", current_boost)
|
||||
|
||||
func reset_boost():
|
||||
@@ -83,7 +83,7 @@ func reset_boost():
|
||||
emit_signal("points_changed", 0, int(MAX_BOOST))
|
||||
emit_signal("boost_reset")
|
||||
|
||||
if player.is_multiplayer_authority():
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
rpc("sync_boost", 0.0)
|
||||
|
||||
# =============================================================================
|
||||
@@ -173,7 +173,7 @@ func consume_boost(amount: float):
|
||||
|
||||
emit_signal("points_changed", int(current_boost), int(MAX_BOOST))
|
||||
|
||||
if player.is_multiplayer_authority():
|
||||
if player.is_multiplayer_authority() and player.has_method("can_rpc") and player.can_rpc():
|
||||
rpc("sync_boost", current_boost)
|
||||
|
||||
func spawn_boost_reward() -> bool:
|
||||
@@ -207,6 +207,6 @@ func add_goal_completion_reward():
|
||||
|
||||
# Optional: Notify user of difficulty increase?
|
||||
|
||||
if multiplayer.is_server():
|
||||
if multiplayer.is_server() and player.has_method("can_rpc") and player.can_rpc():
|
||||
rpc("sync_boost_level", current_level)
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ var current_phase: Phase = Phase.GO
|
||||
var phase_timer: float = GO_DURATION
|
||||
var is_active: bool = false
|
||||
|
||||
var player_missions: Dictionary = {} # player_id -> {tile_id: count, current: count}
|
||||
var player_missions: Dictionary = {} # player_id -> {target_tile: int, required: int, current: int}
|
||||
var finish_line_x: int = 21 # Right side of the map for win condition
|
||||
|
||||
# Tile IDs (Assumed based on analysis)
|
||||
# Tile IDs
|
||||
const TILE_WALKABLE = 0
|
||||
const TILE_SAFE = 2 # Green Safe Zone
|
||||
const TILE_OBSTACLE = 4 # Black Obstacle
|
||||
const TILE_OBSTACLE = 4 # Wall
|
||||
|
||||
var hud_layer: CanvasLayer
|
||||
var phase_label: Label
|
||||
@@ -66,7 +66,7 @@ func _setup_hud():
|
||||
inner_vbox.add_child(phase_label)
|
||||
|
||||
mission_label = Label.new()
|
||||
mission_label.text = "MISSION: Collect 3 Hearts"
|
||||
mission_label.text = "MISSION: Collect 3 Items"
|
||||
mission_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
inner_vbox.add_child(mission_label)
|
||||
|
||||
@@ -94,7 +94,16 @@ func _update_hud_visuals():
|
||||
var my_id = multiplayer.get_unique_id()
|
||||
if mission_label and player_missions.has(my_id):
|
||||
var mission = player_missions[my_id]
|
||||
mission_label.text = "Tiles: %d / %d" % [mission["current"], mission["required"]]
|
||||
# Get Icon name or ID for display
|
||||
var tile_name = "Items"
|
||||
match mission["target_tile"]:
|
||||
7: tile_name = "Hearts"
|
||||
8: tile_name = "Diamonds"
|
||||
9: tile_name = "Stars"
|
||||
10: tile_name = "Coins"
|
||||
|
||||
mission_label.text = "Collect %d %s: %d / %d" % [mission["required"], tile_name, mission["current"], mission["required"]]
|
||||
|
||||
if mission["current"] >= mission["required"]:
|
||||
mission_label.text = "MISSION COMPLETE! REACH FINISH!"
|
||||
mission_label.add_theme_color_override("font_color", Color.GOLD)
|
||||
@@ -106,11 +115,18 @@ func activate_client_side():
|
||||
set_process(true)
|
||||
|
||||
func start_game_mode():
|
||||
activate_client_side()
|
||||
# This should primarily be called by the Server
|
||||
# Clients get activated via RPCs (sync_phase, etc)
|
||||
|
||||
if multiplayer.is_server():
|
||||
activate_client_side() # Server also needs local processing
|
||||
_setup_arena()
|
||||
_assign_missions()
|
||||
_start_phase(Phase.GO)
|
||||
else:
|
||||
# Clients just wait for updates, but can enable HUD if needed
|
||||
# activate_client_side() can be called when first sync arrives
|
||||
pass
|
||||
|
||||
func _start_phase(phase: Phase):
|
||||
current_phase = phase
|
||||
@@ -118,11 +134,14 @@ func _start_phase(phase: Phase):
|
||||
|
||||
var phase_name = "GO" if phase == Phase.GO else "STOP"
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
rpc("sync_phase", phase_name, phase_timer)
|
||||
if multiplayer.get_peers().size() > 0:
|
||||
rpc("sync_phase", phase_name, phase_timer)
|
||||
emit_signal("phase_changed", phase_name, phase_timer)
|
||||
|
||||
@rpc("authority", "call_local", "reliable")
|
||||
func sync_phase(phase_name: String, duration: float):
|
||||
if not is_active:
|
||||
activate_client_side()
|
||||
current_phase = Phase.GO if phase_name == "GO" else Phase.STOP
|
||||
phase_timer = duration
|
||||
|
||||
@@ -130,7 +149,26 @@ func _setup_arena():
|
||||
var gridmap = get_node("/root/Main/EnhancedGridMap")
|
||||
if not gridmap: return
|
||||
|
||||
print("[StopNGo] Setting up 22x10 Accurate Horizontal Arena...")
|
||||
print("[StopNGo] Setting up 22x10 Arena with Randomized Obstacles...")
|
||||
|
||||
# Explicitly sync dimensions and clear grid on all clients
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
if multiplayer.get_peers().size() > 0:
|
||||
rpc("sync_arena_setup")
|
||||
|
||||
# Apply locally for Server (RPC is call_remote)
|
||||
_apply_arena_setup()
|
||||
|
||||
@rpc("authority", "call_remote", "reliable")
|
||||
func sync_arena_setup():
|
||||
print("[StopNGo] Client: Syncing Arena Setup (22x10)...")
|
||||
_apply_arena_setup()
|
||||
|
||||
func _apply_arena_setup():
|
||||
# Shared logic for resizing and clearing
|
||||
var gridmap = get_node("/root/Main/EnhancedGridMap")
|
||||
if not gridmap: return
|
||||
|
||||
# Set Size for Stop n Go
|
||||
gridmap.columns = 22
|
||||
gridmap.rows = 10
|
||||
@@ -138,41 +176,57 @@ func _setup_arena():
|
||||
# Clear existing items on all layers
|
||||
gridmap.clear()
|
||||
|
||||
# Safe Zones Columns: 6, 7, 8 and 14, 15, 16
|
||||
var safe_columns = [6, 7, 8, 14, 15, 16]
|
||||
|
||||
# Create bands based on X (Horizontal Progress)
|
||||
for x in range(gridmap.columns):
|
||||
var tile_id = TILE_WALKABLE
|
||||
# Green Safe Zones at X=7,8 and X=14,15
|
||||
if x == 7 or x == 8 or x == 14 or x == 15:
|
||||
if x in safe_columns:
|
||||
tile_id = TILE_SAFE
|
||||
|
||||
for z in range(gridmap.rows):
|
||||
gridmap.set_cell_item(Vector3i(x, 0, z), tile_id)
|
||||
|
||||
# Place Specific Obstacles (Black Bars) to match user images
|
||||
# Lane 1 (X=2..6) - Vertical bar at X=4
|
||||
for z in range(0, 4):
|
||||
gridmap.set_cell_item(Vector3i(4, 0, z), TILE_OBSTACLE)
|
||||
for z in range(6, 10):
|
||||
gridmap.set_cell_item(Vector3i(4, 0, z), TILE_OBSTACLE)
|
||||
|
||||
# --- SPECIFIC OBSTACLES (Black Walls) ---
|
||||
|
||||
# Lane 2 (X=9..13) - Vertical bar at X=11
|
||||
for z in range(3, 7):
|
||||
# Left Obstacles (Column 4)
|
||||
# Top Vertical Bar
|
||||
for z in range(0, 4): # z=0, 1, 2, 3
|
||||
gridmap.set_cell_item(Vector3i(4, 0, z), TILE_OBSTACLE)
|
||||
# Bottom Vertical Bar
|
||||
for z in range(6, 10): # z=6, 7, 8, 9
|
||||
gridmap.set_cell_item(Vector3i(4, 0, z), TILE_OBSTACLE)
|
||||
|
||||
# Center Obstacles (Column 11 area)
|
||||
# Top Middle Vertical Bar (Offset slightly down)
|
||||
for z in range(1, 5): # z=1, 2, 3, 4
|
||||
gridmap.set_cell_item(Vector3i(11, 0, z), TILE_OBSTACLE)
|
||||
|
||||
# Lane 3 (X=16..20) - L-shape at top
|
||||
for z in range(0, 3):
|
||||
|
||||
# Bottom Middle L-Shape (Vertical + Horizontal hook)
|
||||
for z in range(6, 9): # z=6, 7, 8 (Vertical part)
|
||||
gridmap.set_cell_item(Vector3i(11, 0, z), TILE_OBSTACLE)
|
||||
# Horizontal part of L (at z=6 to right?) - Image looks like inverted L or T?
|
||||
# Let's assume right hook at top of bottom part
|
||||
gridmap.set_cell_item(Vector3i(12, 0, 6), TILE_OBSTACLE)
|
||||
|
||||
# Right Obstacles (Column 18 area)
|
||||
# Top Right L-Shape (Horizontal hook + Vertical down)
|
||||
# Vertical
|
||||
for z in range(0, 3): # z=0, 1, 2
|
||||
gridmap.set_cell_item(Vector3i(18, 0, z), TILE_OBSTACLE)
|
||||
# Horizontal hook to right
|
||||
gridmap.set_cell_item(Vector3i(19, 0, 2), TILE_OBSTACLE)
|
||||
gridmap.set_cell_item(Vector3i(20, 0, 2), TILE_OBSTACLE)
|
||||
|
||||
# Another bar at bottom of Lane 3
|
||||
for z in range(6, 9):
|
||||
# Bottom Right Vertical Bar
|
||||
for z in range(5, 9): # z=5, 6, 7, 8
|
||||
gridmap.set_cell_item(Vector3i(18, 0, z), TILE_OBSTACLE)
|
||||
|
||||
|
||||
gridmap.update_grid_data()
|
||||
gridmap.initialize_astar()
|
||||
|
||||
# Spawn tiles for mission (Heart = 7)
|
||||
# Spawn tiles for missions
|
||||
if multiplayer.is_server():
|
||||
_spawn_mission_tiles()
|
||||
|
||||
@@ -186,27 +240,41 @@ func _setup_arena():
|
||||
|
||||
func _spawn_mission_tiles():
|
||||
var gridmap = get_node("/root/Main/EnhancedGridMap")
|
||||
var count = 0
|
||||
while count < 40: # Spawn plenty of hearts
|
||||
var x = randi() % gridmap.columns
|
||||
var z = randi() % gridmap.rows
|
||||
# Only spawn in walkable areas, not safe zones or start/finish
|
||||
if gridmap.get_cell_item(Vector3i(x, 0, z)) == TILE_WALKABLE:
|
||||
if gridmap.get_cell_item(Vector3i(x, 1, z)) == -1:
|
||||
gridmap.set_cell_item(Vector3i(x, 1, z), ScarcityModel.TILE_HEART)
|
||||
count += 1
|
||||
|
||||
# Tile IDs for missions: Heart(7), Diamond(8), Star(9), Coin(10)
|
||||
var mission_tiles = [7, 8, 9, 10]
|
||||
|
||||
for tile_type in mission_tiles:
|
||||
var count = 0
|
||||
while count < 15: # 15 of each type (plenty for finding 3)
|
||||
var x = randi() % gridmap.columns
|
||||
var z = randi() % gridmap.rows
|
||||
|
||||
# Only spawn in walkable areas (Floor 0 must be 0 or 2, and Floor 1 empty)
|
||||
var floor_item = gridmap.get_cell_item(Vector3i(x, 0, z))
|
||||
if (floor_item == TILE_WALKABLE or floor_item == TILE_SAFE):
|
||||
if gridmap.get_cell_item(Vector3i(x, 1, z)) == -1:
|
||||
gridmap.set_cell_item(Vector3i(x, 1, z), tile_type)
|
||||
count += 1
|
||||
|
||||
func _assign_missions():
|
||||
# Each player needs to collect 3 specific tiles (e.g. Heart)
|
||||
# Assign UNIQUE target tile types to players cyclicly
|
||||
var players = GameStateManager.players
|
||||
var tile_types = [ScarcityModel.TILE_HEART, ScarcityModel.TILE_DIAMOND, ScarcityModel.TILE_STAR, ScarcityModel.TILE_COIN]
|
||||
|
||||
var idx = 0
|
||||
for p_id in players:
|
||||
var target = tile_types[idx % tile_types.size()]
|
||||
player_missions[p_id] = {
|
||||
"target_tile": ScarcityModel.TILE_HEART,
|
||||
"target_tile": target,
|
||||
"required": 3,
|
||||
"current": 0
|
||||
}
|
||||
idx += 1
|
||||
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
rpc("sync_missions", player_missions)
|
||||
if multiplayer.get_peers().size() > 0:
|
||||
rpc("sync_missions", player_missions)
|
||||
|
||||
@rpc("authority", "call_local", "reliable")
|
||||
func sync_missions(missions: Dictionary):
|
||||
@@ -218,7 +286,11 @@ func check_movement_violation(player_id: int, from: Vector2i, to: Vector2i) -> b
|
||||
var main = get_node("/root/Main")
|
||||
var gridmap = main.get_node("EnhancedGridMap") if main else null
|
||||
if gridmap:
|
||||
# Check FROM position. If you were safe, you can move?
|
||||
# Rules: "If a player moves during this phase".
|
||||
# Usually implies checking if you ARE in a safe zone.
|
||||
var tile_from = gridmap.get_cell_item(Vector3i(from.x, 0, from.y))
|
||||
|
||||
if tile_from != TILE_SAFE:
|
||||
_penalize_player(player_id)
|
||||
return true
|
||||
@@ -232,8 +304,13 @@ func _penalize_player(player_id: int):
|
||||
|
||||
var player_node = main.get_node_or_null(str(player_id))
|
||||
if player_node:
|
||||
# Don't reset mission progress!
|
||||
# Just Drop All Tiles (which already exist on player)
|
||||
if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
player_node.rpc("on_stop_phase_violation")
|
||||
player_node.rpc("drop_all_tiles")
|
||||
|
||||
# Also send message
|
||||
NotificationManager.send_message(player_node, "Moved during STOP! Tiles Dropped!", NotificationManager.MessageType.WARNING)
|
||||
emit_signal("player_penalized", player_id)
|
||||
|
||||
func update_mission_progress(player_id: int, tile_id: int):
|
||||
@@ -245,9 +322,18 @@ func update_mission_progress(player_id: int, tile_id: int):
|
||||
|
||||
if mission["current"] >= mission["required"]:
|
||||
emit_signal("mission_status_updated", player_id, true)
|
||||
|
||||
# FIX: NotificationManager.send_message_to_player() does NOT exist.
|
||||
# We need to find the player node and use send_message(target, msg, type)
|
||||
var main = get_node("/root/Main")
|
||||
if main:
|
||||
var player_node = main.get_node_or_null(str(player_id))
|
||||
if player_node:
|
||||
NotificationManager.send_message(player_node, "Mission Complete! Reach the Finish!", NotificationManager.MessageType.GOAL)
|
||||
|
||||
if multiplayer.is_server() and multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
rpc("sync_mission_progress", player_id, mission["current"])
|
||||
if multiplayer.get_peers().size() > 0:
|
||||
rpc("sync_mission_progress", player_id, mission["current"])
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_mission_progress(player_id: int, current: int):
|
||||
|
||||
@@ -68,25 +68,25 @@ func _attempt_throw():
|
||||
tekton.look_at(Vector3(target_world_pos.x, tekton.global_position.y, target_world_pos.z), Vector3.UP)
|
||||
|
||||
# 2. Play Animation
|
||||
if tekton.has_method("play_animation_rpc"):
|
||||
if tekton.has_method("play_animation_rpc") and tekton.has_method("can_rpc") and tekton.can_rpc():
|
||||
tekton.rpc("play_animation_rpc", "tekton_throw_tile")
|
||||
|
||||
# 3. Create Projectile Visual (Synced)
|
||||
if tekton.has_method("spawn_projectile_rpc"):
|
||||
if tekton.has_method("spawn_projectile_rpc") and tekton.has_method("can_rpc") and tekton.can_rpc():
|
||||
tekton.rpc("spawn_projectile_rpc", target_world_pos, 0.5)
|
||||
|
||||
# 4. Impact / Spawn
|
||||
await get_tree().create_timer(0.5).timeout
|
||||
|
||||
var main = tekton.get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
if main and tekton.has_method("can_rpc") and tekton.can_rpc():
|
||||
# Spawn Item (Random ID 7-10)
|
||||
var item_id = randi_range(7, 10)
|
||||
main.rpc("sync_grid_item", target.x, 1, target.y, item_id)
|
||||
|
||||
# 5. Resume Idle
|
||||
await get_tree().create_timer(0.5).timeout # Small delay after throw
|
||||
if tekton.has_method("play_animation_rpc"):
|
||||
if tekton.has_method("play_animation_rpc") and tekton.has_method("can_rpc") and tekton.can_rpc():
|
||||
tekton.rpc("play_animation_rpc", "tekton_idle")
|
||||
|
||||
_start_timer()
|
||||
|
||||
+5
-2
@@ -106,9 +106,12 @@ func move_to(target_pos: Vector2i):
|
||||
emit_signal("movement_finished")
|
||||
)
|
||||
|
||||
if is_multiplayer_authority():
|
||||
if is_multiplayer_authority() and can_rpc():
|
||||
rpc("sync_movement", target_pos)
|
||||
|
||||
func can_rpc() -> bool:
|
||||
return multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED
|
||||
|
||||
@rpc("any_peer", "call_remote", "reliable")
|
||||
func sync_movement(target_pos: Vector2i):
|
||||
move_to(target_pos)
|
||||
@@ -388,7 +391,7 @@ func spawn_tiles_around(count: int = 4):
|
||||
|
||||
if item_id != -1:
|
||||
var main = get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
if main and can_rpc():
|
||||
main.rpc("sync_grid_item", pos.x, 1, pos.y, item_id)
|
||||
spawned += 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user