Files
tekton/scripts/managers/player_race_manager.gd
T
2025-12-03 18:16:00 +08:00

161 lines
4.3 KiB
GDScript

extends Node
var player: Node3D
var enhanced_gridmap: Node
# Race state
var current_lap: int = 0
var first_lap_goals: Array[int] = []
var second_lap_goals: Array[int] = []
var race_position: int = 0
static var lap1_finishers: int = 0
static var lap2_finishers: int = 0
# Goals and Playerboard
var goals: Array[int] = [0,0,0,0,0,0,0,0,0]
var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
var can_finish: bool = false
# Finish locations (copied from player.gd)
var finish_locations = [
Vector2i(13, 0), Vector2i(13, 1), Vector2i(13, 2), Vector2i(13, 3),
Vector2i(13, 4), Vector2i(13, 5), Vector2i(13, 6), Vector2i(13, 7),
Vector2i(13, 8), Vector2i(13, 9), Vector2i(13, 10), Vector2i(13, 11),
Vector2i(13, 12), Vector2i(13, 13)
]
func initialize(p_player: Node3D, p_gridmap: Node):
player = p_player
enhanced_gridmap = p_gridmap
if player.is_multiplayer_authority():
first_lap_goals = goals.duplicate()
generate_second_lap_goals()
func get_ordinal_string(number: int) -> String:
match number:
1: return "1st"
2: return "2nd"
3: return "3rd"
4: return "4th"
_: return str(number) + "th"
func generate_second_lap_goals():
second_lap_goals.clear()
for i in range(9):
var val = (randi() % 4) + 7
second_lap_goals.append(val)
if player.is_multiplayer_authority():
player.rpc("sync_second_lap_goals", second_lap_goals)
func check_3x3_section(board: Array, goals_pattern: Array, start_row: int, start_col: int) -> bool:
for i in range(3):
for j in range(3):
if goals_pattern[i][j] != -1:
var board_value = board[start_row + i][start_col + j]
if board_value == -1:
return false
for i in range(3):
for j in range(3):
if goals_pattern[i][j] != -1:
if board[start_row + i][start_col + j] != goals_pattern[i][j]:
return false
return true
func check_pattern_match() -> bool:
if playerboard.size() != 25 or goals.size() != 9:
return false
var board_2d = []
var goals_2d = []
for i in range(5):
var row = []
for j in range(5):
row.append(playerboard[i * 5 + j])
board_2d.append(row)
for i in range(3):
var row = []
for j in range(3):
row.append(goals[i * 3 + j])
goals_2d.append(row)
for start_row in range(3):
for start_col in range(3):
if check_3x3_section(board_2d, goals_2d, start_row, start_col):
return true
return false
func update_finish_availability():
can_finish = check_pattern_match()
if player.is_multiplayer_authority():
if can_finish:
highlight_finish_line()
else:
unhighlight_finish_line()
func highlight_finish_line():
if not player.is_multiplayer_authority() or player.is_bot:
return
for finish_pos in finish_locations:
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(finish_pos.x, 0, finish_pos.y),
enhanced_gridmap.hover_item
)
func unhighlight_finish_line():
if not player.is_multiplayer_authority() or player.is_bot:
return
for finish_pos in finish_locations:
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(
Vector3i(finish_pos.x, 0, finish_pos.y),
enhanced_gridmap.normal_items[0]
)
func is_at_finish_line() -> bool:
return player.current_position in finish_locations
func finish_race():
if current_lap == 0:
lap1_finishers += 1
race_position = lap1_finishers
var message = "Finish 1st lap on " + get_ordinal_string(race_position)
if player.is_multiplayer_authority():
player.rpc("display_message", message)
current_lap += 1
player.rpc("start_new_lap")
elif current_lap == 1:
lap2_finishers += 1
race_position = lap2_finishers
var message = "Finish 2nd lap on " + get_ordinal_string(race_position)
if player.is_multiplayer_authority():
player.rpc("display_message", message)
func start_new_lap():
if current_lap == 1:
var valid_finish_pos = find_valid_position_in_finish_line()
if valid_finish_pos != Vector2i(-1, -1):
player.current_position = valid_finish_pos
player.update_player_position(player.current_position)
goals = second_lap_goals.duplicate()
can_finish = false
if player.is_multiplayer_authority():
player.rpc("sync_position", player.current_position)
player.rpc("sync_playerboard", playerboard)
player.rpc("sync_goals", goals)
func find_valid_position_in_finish_line() -> Vector2i:
for pos in finish_locations:
if not player.is_position_occupied(pos):
return pos
return Vector2i(-1, -1)