using Godot;
using System;
using System.Collections.Generic;
using Models;
using Core;
///
/// 游戏主控制节点(MVC 的桥接层)
/// 设计说明:
/// 1) 负责初始化 GameSession,并把输入/信号转交给 Controller/System。
/// 2) 仅做“流程调度”,不直接计算复杂数值,避免逻辑堆积。
/// 注意事项:
/// - View 与 Model 的绑定应逐步迁移到独立 View 脚本,避免在此类膨胀。
/// 未来扩展:
/// - 可拆分为 SceneRoot + UIController + DebugController,分层管理。
///
public partial class GameManager : Node
{
///
/// Indicates if the game is currently in tutorial mode.
///
public static bool IsTutorial { get; private set; }
public static string NextScene { get; set; } = null;
public static readonly Resource Arrow2X = ResourceLoader.Load("res://temp_res/kenney_ui-pack-space-expansion/PNG/Extra/Double/cursor_f.png");
[Export]
public int MaxTurns = 30;
// --- Global State ---
public GameSession Session { get; private set; }
public GameState State => Session?.State;
public GameController Controller { get; private set; }
public GamePhase CurrentPhase => State?.Turn.Phase ?? GamePhase.Planning;
public int CurrentTurn => State?.Turn.CurrentTurn ?? 1;
// --- Domain Model ---
public MentorModel Mentor => State?.Roster.Mentor;
public List Students => State?.Roster.Students;
public List ActiveTasks => State?.Tasks.ActiveTasks;
public EconomyState Economy => State?.Economy;
// --- Signals ---
[Signal] public delegate void PhaseChangedEventHandler(int phase); // int cast of GamePhase
[Signal] public delegate void TurnChangedEventHandler(int turn);
// Singleton instance access (if needed, though Godot uses node paths)
public static GameManager Instance { get; private set; }
public override void _EnterTree()
{
Instance = this;
}
public override void _Ready()
{
Input.SetCustomMouseCursor(Arrow2X);
// MVP Initialization
InitializeGame();
}
private void InitializeGame()
{
Session = GameSession.CreateDefault();
Controller = new GameController();
Controller.Initialize(Session);
State.Turn.MaxTurns = MaxTurns;
State.Turn.CurrentTurn = 1;
State.Turn.Phase = GamePhase.Planning;
// MVP: Add a test student
var s1 = new StudentModel("张三");
Students.Add(s1);
// MVP: Add a test task
var t1 = new TaskModel("深度学习导论", TaskKind.AcademicExploration, 1000f, 3);
t1.Reward.Money = 1000;
t1.Reward.Reputation = 5;
ActiveTasks.Add(t1);
GD.Print("Game Initialized. Phase: Planning, Turn: 1");
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
if (CurrentPhase == GamePhase.Execution)
{
// Update game logic (timers, etc.)
// In a real implementation, this might manage the global timer for the day/week
}
Session?.Tick((float)delta);
}
///
/// 结束筹备阶段,开始执行
///
public void StartExecution()
{
if (CurrentPhase != GamePhase.Planning) return;
Controller.StartExecution();
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Execution");
// Notify all agents to start working (this would be handled by a system listening to the signal)
}
///
/// 结束执行阶段(通常由时间耗尽或玩家手动触发),进入结算
///
public void EndExecution()
{
if (CurrentPhase != GamePhase.Execution) return;
Controller.EndExecution();
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Review");
PerformReview();
}
///
/// 执行结算逻辑,并准备下一回合
///
private void PerformReview()
{
// 1. Task progress check
foreach (var task in ActiveTasks)
{
task.Runtime.RemainingTurns--;
if (task.IsCompleted)
{
GD.Print($"Task {task.Name} Completed!");
Economy.Reputation += task.Reward.Reputation;
Economy.Money += task.Reward.Money;
}
else if (task.IsFailed)
{
GD.Print($"Task {task.Name} Failed!");
Economy.Reputation -= 10; // Penalty
}
}
// 2. Student status update (Salary, etc.)
foreach (var student in Students)
{
// Deduct salary? Restore some stamina?
}
GD.Print("Review Complete. Waiting for Next Turn confirmation.");
}
///
/// 开始新的回合
///
public void StartNextTurn()
{
if (CurrentPhase != GamePhase.Review) return;
Controller.StartNextTurn();
if (CurrentTurn > State.Turn.MaxTurns)
{
GD.Print("Game Over!");
// Handle Game Over
return;
}
State.Turn.Phase = GamePhase.Planning;
EmitSignal(SignalName.TurnChanged, CurrentTurn);
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
// Refresh resources/AP
Mentor.Resources.Energy.Current.Value = Mentor.Resources.Energy.UpperThreshold;
GD.Print($"Turn {CurrentTurn} Started. Phase: Planning");
}
}