supervisor-simulator/scripts/GameManager.cs
wjsjwr b8fecd080f 已把模型层改成组合式结构并补齐 MVC/内容配置骨架:Unit/任务/运行时状态现在通过组件组合,GameManager 作为桥接层改为驱动 GameSession/Controller;同时新增学科/羁绊/装备/任务/肉鸽等定义结构,预留 i18n 与 Mod 内容加载接口。
- 组合式单位与数值基础重构:scripts/Models/UnitModel.cs, scripts/Models/UnitComponents.cs, scripts/Models/StudentModel.cs, scripts/Models/MentorModel.cs, scripts/Models/StaffModel.cs, scripts/Models/PropertyValue.cs, scripts/Models/StatusValue.cs
  - 任务与运行时状态骨架:scripts/Models/Task.cs, scripts/Models/TaskDefinitions.cs, scripts/Models/GameState.cs
  - 配置与规则定义骨架:scripts/Models/DefinitionSupport.cs, scripts/Models/DomainEnums.cs, scripts/Models/Modifiers.cs, scripts/Models/DisciplineDefinitions.cs, scripts/Models/SynergyDefinitions.cs, scripts/Models/ItemDefinitions.cs, scripts/Models/PaperDefinitions.cs, scripts/Models/RogueliteDefinitions.cs, scripts/Models/GameContentDatabase.cs, scripts/Models/CoreIds.cs
  - MVC/会话/系统/i18n/Mod 支撑:scripts/Core/GameSession.cs, scripts/Core/GameSystems.cs, scripts/Core/GameController.cs, scripts/Core/Mvc.cs, scripts/Core/LocalizationService.cs, scripts/Core/ContentRegistry.cs, scripts/Core/ModManifest.cs, scripts/Core/EventBus.cs
  - 主控流程衔接:scripts/GameManager.cs
2025-12-31 23:54:31 +08:00

181 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Godot;
using System;
using System.Collections.Generic;
using Models;
using Core;
/// <summary>
/// 游戏主控制节点MVC 的桥接层)
/// 设计说明:
/// 1) 负责初始化 GameSession并把输入/信号转交给 Controller/System。
/// 2) 仅做“流程调度”,不直接计算复杂数值,避免逻辑堆积。
/// 注意事项:
/// - View 与 Model 的绑定应逐步迁移到独立 View 脚本,避免在此类膨胀。
/// 未来扩展:
/// - 可拆分为 SceneRoot + UIController + DebugController分层管理。
/// </summary>
public partial class GameManager : Node
{
/// <summary>
/// Indicates if the game is currently in tutorial mode.
/// </summary>
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<StudentModel> Students => State?.Roster.Students;
public List<TaskModel> 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);
}
/// <summary>
/// 结束筹备阶段,开始执行
/// </summary>
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)
}
/// <summary>
/// 结束执行阶段(通常由时间耗尽或玩家手动触发),进入结算
/// </summary>
public void EndExecution()
{
if (CurrentPhase != GamePhase.Execution) return;
Controller.EndExecution();
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Review");
PerformReview();
}
/// <summary>
/// 执行结算逻辑,并准备下一回合
/// </summary>
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.");
}
/// <summary>
/// 开始新的回合
/// </summary>
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");
}
}