extends Node # GoalManager - Manages goal generation, synchronization, and speed tracking var preset_goals: Array = [] # Speed Tracking var player_completion_times: Dictionary = {} # { player_id: [time_taken, time_taken, ...] } var player_start_times: Dictionary = {} # { player_id: timestamp_msec } func initialize_random_goals(size: int, min_value: int, max_value: int, null_count: float) -> Array: var goals = [] var rng = RandomNumberGenerator.new() rng.randomize() var null_val = 0 var max_nulls = 3 const SPECIAL_VALUES = {1: 7, 2: 8, 3: 9, 4: 10} for i in range(size): if null_val < max_nulls and rng.randf() < null_count: goals.append(-1) null_val += 1 else: var val = rng.randi_range(min_value, max_value) goals.append(val if not val in SPECIAL_VALUES else SPECIAL_VALUES[val]) return goals func generate_preset_goals(count: int) -> Array: preset_goals.clear() for i in range(count): var goals = initialize_random_goals(9, 7, 10, 1.0) var int_goals: Array[int] = [] for g in goals: int_goals.append(g) preset_goals.append(int_goals) return preset_goals func get_goals_for_player(player_index: int) -> Array: if player_index >= 0 and player_index < preset_goals.size(): return preset_goals[player_index].duplicate() return [] # ============================================================================= # Speed Tracking Logic # ============================================================================= func mark_goal_start(player_id: int): player_start_times[player_id] = Time.get_ticks_msec() func mark_goal_complete(player_id: int): if not player_start_times.has(player_id): return var duration_sec = (Time.get_ticks_msec() - player_start_times[player_id]) / 1000.0 if not player_completion_times.has(player_id): player_completion_times[player_id] = [] player_completion_times[player_id].append(duration_sec) # Reset start time for next goal player_start_times[player_id] = Time.get_ticks_msec() # print("Player %s completed goal in %.2fs" % [player_id, duration_sec]) func get_player_average_time(player_id: int) -> float: if not player_completion_times.has(player_id) or player_completion_times[player_id].is_empty(): return 10.0 # Default baseline (10 seconds) var total = 0.0 for t in player_completion_times[player_id]: total += t return total / player_completion_times[player_id].size() func get_global_average_time() -> float: var total_avg = 0.0 var count = 0 for pid in player_completion_times: var p_avg = get_player_average_time(pid) total_avg += p_avg count += 1 if count == 0: return 10.0 return total_avg / count func get_boost_multiplier(player_id: int) -> float: var p_avg = get_player_average_time(player_id) var g_avg = get_global_average_time() if p_avg > g_avg: # Player is slower than average -> Boost fills faster # Scale up to 1.5x based on how much slower (capped) var ratio = p_avg / max(g_avg, 0.1) return min(ratio, 1.5) else: # Player is faster than average -> Boost fills slower # Scale down to 0.8x return 0.8 func reset(): preset_goals.clear() player_completion_times.clear() player_start_times.clear()