diff --git a/scripts/main.gd b/scripts/main.gd index 777771a..4bcc49e 100644 --- a/scripts/main.gd +++ b/scripts/main.gd @@ -15,6 +15,7 @@ const BUILD_UNLOCKS := Constants.BUILD_UNLOCKS const RotatingGoal := preload("res://scripts/rotating_goal.gd") const GoalProgression := preload("res://scripts/goal_progression.gd") const GoalReward := preload("res://scripts/goal_reward.gd") +const MilestoneManager := preload("res://scripts/milestone_manager.gd") const RESOURCE_TRENDS := Constants.RESOURCE_TRENDS const ColonyStance := preload("res://scripts/colony_stance.gd") const TileRender := preload("res://scripts/tile_render.gd") @@ -100,6 +101,8 @@ var game_active := false var active_goal: Dictionary = {} var completed_goal_ids: Array = [] var active_rewards: Array = [] +var current_milestone_id: String = "" +var completed_milestone_ids: Array = [] var event_drawer_visible := false func make_panel_style(bg: Color, border: Color, corner_radius: int = 12) -> StyleBoxFlat: @@ -764,6 +767,10 @@ func bootstrap_state() -> void: apply_priority_order() # Initialize active goal active_goal = GoalProgression.init_goals(completed_goal_ids) + # Initialize milestone state + var milestone_seed: Dictionary = MilestoneManager.make_goal_state() + current_milestone_id = String(milestone_seed.get("milestone_id", "")) + completed_milestone_ids = Array(milestone_seed.get("completed_ids", [])) completed_goal_ids = [] active_rewards = [] _mark_dirty() @@ -914,6 +921,10 @@ func load_saved_game() -> void: completed_goal_ids = state["completed_goal_ids"] if state.has("active_rewards"): active_rewards = state["active_rewards"] + # Restore milestone state (seed defaults for legacy saves without milestone keys) + var milestone_seed: Dictionary = MilestoneManager.make_goal_state() + current_milestone_id = String(state.get("current_milestone_id", milestone_seed.get("milestone_id", ""))) + completed_milestone_ids = Array(state.get("completed_milestone_ids", milestone_seed.get("completed_ids", []))) colony_stance = String(state.get("colony_stance", ColonyStance.STANCE_BALANCED)) apply_priority_order() apply_orientation_lock_ui() @@ -1398,6 +1409,13 @@ func _on_tick() -> void: push_event(evt) for expired_label in reward_result["expired"]: push_event("Reward ended: %s" % expired_label) + # Milestone evaluation (issue #237) + var active_milestone: Dictionary = MilestoneManager.get_current_milestone(MilestoneManager.MILESTONE_CATALOG, current_milestone_id) + if not active_milestone.is_empty() and MilestoneManager.is_milestone_complete(active_milestone, state): + var completed_milestone_id: String = current_milestone_id + completed_milestone_ids.append(completed_milestone_id) + push_event("Milestone reached: %s" % MilestoneManager.milestone_description(active_milestone)) + current_milestone_id = MilestoneManager.advance_to_next(completed_milestone_ids, completed_milestone_id) persist() state.workers = state.workers render_all() @@ -2440,6 +2458,9 @@ func persist() -> void: state["completed_goal_ids"] = completed_goal_ids.duplicate() # Persist active rewards for goal reward system state["active_rewards"] = active_rewards.duplicate(true) + # Persist milestone state (issue #237) + state["current_milestone_id"] = current_milestone_id + state["completed_milestone_ids"] = completed_milestone_ids.duplicate() GameState.save_game(state) func get_tile(pos: Vector2i) -> Dictionary: diff --git a/scripts/milestone_manager.gd b/scripts/milestone_manager.gd index 2d24353..3a0e303 100644 --- a/scripts/milestone_manager.gd +++ b/scripts/milestone_manager.gd @@ -80,29 +80,29 @@ static func get_current_milestone(catalog: Array, milestone_id: String) -> Dicti # Evaluate whether the current milestone is complete given game state. # Returns {progress: int, total: int} for UI progress display. static func evaluate_milestone(milestone: Dictionary, game_state: Dictionary) -> Dictionary: - var mtype := String(milestone.get("type", "")) - var target := milestone.get("target", {}) + var mtype: String = String(milestone.get("type", "")) + var target: Dictionary = milestone.get("target", {}) match mtype: MILESTONE_TYPE_BUILD: - var build_kind := String(target.get("build_kind", "")) - var builds := game_state.get("builds", []) + var build_kind: String = String(target.get("build_kind", "")) + var builds: Array = game_state.get("builds", []) for build in builds: if bool(build.get("complete")) and String(build.get("kind", "")) == build_kind: return {"progress": 1, "total": 1} return {"progress": 0, "total": 1} MILESTONE_TYPE_STOCKPILE: - var resource := String(target.get("resource", "")) - var amount := int(target.get("amount", 0)) - var harvested := game_state.get("harvested", {}) - var current := int(harvested.get(resource, 0)) + var resource: String = String(target.get("resource", "")) + var amount: int = int(target.get("amount", 0)) + var harvested: Dictionary = game_state.get("harvested", {}) + var current: int = int(harvested.get(resource, 0)) return {"progress": mini(current, amount), "total": amount} MILESTONE_TYPE_WORKER: - var count := int(target.get("worker_count", 0)) - var workers := game_state.get("workers", []) - var active := 0 + var count: int = int(target.get("worker_count", 0)) + var workers: Array = game_state.get("workers", []) + var active: int = 0 for worker in workers: if int(worker.get("break_ticks", 0)) <= 0: active += 1 @@ -113,13 +113,13 @@ static func evaluate_milestone(milestone: Dictionary, game_state: Dictionary) -> # ── Completion check ──────────────────────────────────────────────────────── static func is_milestone_complete(milestone: Dictionary, game_state: Dictionary) -> bool: - var eval := evaluate_milestone(milestone, game_state) - return eval.get("progress", 0) >= eval.get("total", 1) + var eval: Dictionary = evaluate_milestone(milestone, game_state) + return int(eval.get("progress", 0)) >= int(eval.get("total", 1)) # ── Advance to next milestone ─────────────────────────────────────────────── static func advance_to_next(completed_ids: Array, current_id: String) -> String: # Find the index of the current milestone in the catalog - var current_index := -1 + var current_index: int = -1 for i in range(MILESTONE_CATALOG.size()): if MILESTONE_CATALOG[i]["id"] == current_id: current_index = i @@ -128,7 +128,7 @@ static func advance_to_next(completed_ids: Array, current_id: String) -> String: if current_index < 0 or current_index >= MILESTONE_CATALOG.size() - 1: return current_id # No next milestone - var next_index := current_index + 1 + var next_index: int = current_index + 1 return MILESTONE_CATALOG[next_index]["id"] # ── Milestone description for event log ─────────────────────────────────────