using System;
using System.Collections.Generic;
using Models;
namespace Core;
///
/// 系统层骨架(负责模型变化,不直接处理输入/显示)
/// 设计说明:
/// 1) 每个系统只关注单一职责,形成高内聚低耦合结构。
/// 2) 系统之间通过 GameSession 共享状态,通过事件总线通讯。
/// 注意事项:
/// - 系统逻辑应尽量“幂等”,便于回合重算与调试。
/// 未来扩展:
/// - 可加入“系统执行顺序配置”,支持 Mod 插入新系统。
///
public interface IGameSystem {
///
/// 初始化系统
///
/// 游戏会话
void Initialize(GameSession session);
///
/// 每帧更新
///
/// 帧间隔
void Tick(float delta);
}
///
/// 游戏系统管理器
///
public sealed class GameSystems {
///
/// 回合系统
///
public TurnSystem Turn { get; } = new();
///
/// 任务系统
///
public TaskSystem Task { get; } = new();
///
/// 经济系统
///
public EconomySystem Economy { get; } = new();
///
/// 羁绊/协同系统
///
public SynergySystem Synergy { get; } = new();
///
/// 分配系统
///
public AssignmentSystem Assignment { get; } = new();
///
/// 初始化所有系统
///
/// 游戏会话
public void Initialize(GameSession session) {
Turn.Initialize(session);
Task.Initialize(session);
Economy.Initialize(session);
Synergy.Initialize(session);
Assignment.Initialize(session);
}
///
/// 更新所有系统
///
/// 帧间隔
public void Tick(float delta) {
Turn.Tick(delta);
Synergy.Tick(delta);
Task.Tick(delta);
Economy.Tick(delta);
Assignment.Tick(delta);
}
}
///
/// 回合系统
///
public sealed class TurnSystem : IGameSystem {
private GameSession _session;
///
/// 初始化
///
/// 游戏会话
public void Initialize(GameSession session) {
_session = session;
}
///
/// 更新
///
/// 帧间隔
public void Tick(float delta) {
// 预留:回合推进计时器/阶段切换
}
}
///
/// 任务系统
///
public sealed class TaskSystem : IGameSystem {
private GameSession _session;
private StatResolver _statResolver;
///
/// 初始化
///
/// 游戏会话
public void Initialize(GameSession session) {
_session = session;
_statResolver = new StatResolver(session);
}
///
/// 更新
///
/// 帧间隔
public void Tick(float delta) {
if (_session.State.Turn.Phase != GamePhase.Execution) return;
AdvanceTasks(delta);
}
///
/// 回合结算(扣除 Deadline,判定完成与失败)
///
public void ResolveEndOfTurn() {
var state = _session.State;
var completed = new List();
var failed = new List();
foreach (var task in state.Tasks.ActiveTasks) {
if (task.Runtime.RemainingTurns > 0) task.Runtime.RemainingTurns--;
if (task.IsCompleted)
completed.Add(task);
else if (task.IsFailed) failed.Add(task);
}
foreach (var task in completed) {
state.Tasks.ActiveTasks.Remove(task);
state.Tasks.CompletedTasks.Add(task);
_session.Events.Publish(new TaskCompletedEvent(task));
}
foreach (var task in failed) {
state.Tasks.ActiveTasks.Remove(task);
state.Tasks.FailedTasks.Add(task);
_session.Events.Publish(new TaskFailedEvent(task));
}
}
///
/// 推进任务进度
///
/// 时间间隔
private void AdvanceTasks(float delta) {
var state = _session.State;
if (state.Tasks.ActiveTasks.Count == 0) return;
var unitIndex = BuildUnitIndex();
foreach (var task in state.Tasks.ActiveTasks) {
if (task.IsCompleted || task.IsFailed) continue;
if (task.Kind == TaskKind.Milestone) continue;
var taskDef = GetTaskDefinition(task);
var totalPower = 0f;
foreach (var unitId in task.AssignedUnitIds) {
if (!unitIndex.TryGetValue(unitId, out var entry)) continue;
var contribution = GetUnitContribution(entry, task, taskDef, delta);
totalPower += contribution;
}
if (totalPower <= 0f) continue;
var difficultyScale = task.Runtime.DifficultyScale * GetDifficultyScale(task.Difficulty);
task.AddProgress(totalPower * delta / difficultyScale);
}
}
///
/// 获取单位对任务的贡献
///
private float GetUnitContribution(UnitEntry entry, TaskModel task, TaskDefinition taskDef, float delta) {
var unit = entry.Unit;
var basePower = GetTaskBasePower(unit, task.Kind);
if (basePower <= 0f) return 0f;
var roleMultiplier = GetRoleMultiplier(unit, taskDef);
var disciplineMultiplier = GetDisciplineMultiplier(unit, taskDef);
var statusMultiplier = GetStatusMultiplier(entry);
var requirementMultiplier = GetRequirementMultiplier(unit, taskDef);
var effectivePower = basePower * roleMultiplier * disciplineMultiplier * statusMultiplier *
requirementMultiplier;
TrackContribution(entry, task, effectivePower * delta);
return effectivePower;
}
///
/// 获取任务基础效率
///
private float GetTaskBasePower(UnitModel unit, TaskKind kind) {
var academic = _statResolver.GetAttribute(unit, AttributeType.Academic);
var engineering = _statResolver.GetAttribute(unit, AttributeType.Engineering);
var writing = _statResolver.GetAttribute(unit, AttributeType.Writing);
var financial = _statResolver.GetAttribute(unit, AttributeType.Financial);
var social = _statResolver.GetAttribute(unit, AttributeType.Social);
var activation = _statResolver.GetAttribute(unit, AttributeType.Activation);
return kind switch {
TaskKind.AcademicExploration => academic * 0.6f + writing * 0.4f,
TaskKind.GrantVertical => writing * 0.4f + social * 0.4f + financial * 0.2f,
TaskKind.GrantHorizontal => engineering * 0.5f + activation * 0.3f + academic * 0.2f,
TaskKind.Administrative => activation * 0.6f + social * 0.4f,
TaskKind.Conference => social * 0.5f + writing * 0.3f + financial * 0.2f,
TaskKind.Milestone => 0f,
_ => academic
};
}
///
/// 获取状态乘数
///
private float GetStatusMultiplier(UnitEntry entry) {
var mood = entry.Unit.Statuses.Mood.Normalized;
var stress = entry.Unit.Statuses.Stress.Current.Normalized;
var moodMultiplier = 0.5f + mood * 0.5f;
var stressMultiplier = Math.Clamp(1.0f - 0.3f * stress, 0.7f, 1.0f);
var multiplier = moodMultiplier * stressMultiplier;
if (entry.Student != null) {
var stamina = entry.Student.Progress.Stamina.Current.Normalized;
if (stamina < 0.1f) multiplier *= 0.4f;
else if (stamina < 0.2f) multiplier *= 0.7f;
}
return Math.Clamp(multiplier, 0.3f, 1.2f);
}
///
/// 获取角色乘数
///
private float GetRoleMultiplier(UnitModel unit, TaskDefinition taskDef) {
if (taskDef == null) return 1.0f;
if (taskDef.Requirements.RequiredRoleIds.Count > 0) {
foreach (var roleId in taskDef.Requirements.RequiredRoleIds)
if (unit.Tags.RoleIds.Contains(roleId))
return 1.0f;
return 0.5f;
}
if (taskDef.RecommendedRoleIds.Count > 0) {
foreach (var roleId in taskDef.RecommendedRoleIds)
if (unit.Tags.RoleIds.Contains(roleId))
return 1.1f;
return 0.9f;
}
return 1.0f;
}
///
/// 获取需求乘数
///
private float GetRequirementMultiplier(UnitModel unit, TaskDefinition taskDef) {
if (taskDef == null) return 1.0f;
var multiplier = 1.0f;
foreach (var requirement in taskDef.Requirements.AttributeChecks) {
var value = _statResolver.GetAttribute(unit, requirement.Type);
if (value < requirement.MinValue) multiplier *= 0.85f;
}
return multiplier;
}
///
/// 获取学科乘数
///
private float GetDisciplineMultiplier(UnitModel unit, TaskDefinition taskDef) {
if (taskDef == null) return 1.0f;
if (taskDef.AllowedDisciplineIds.Count == 0) return 1.0f;
if (string.IsNullOrWhiteSpace(unit.Tags.DisciplineId)) return 0.8f;
foreach (var disciplineId in taskDef.AllowedDisciplineIds)
if (disciplineId == unit.Tags.DisciplineId)
return 1.0f;
return 0.7f;
}
///
/// 获取难度系数
///
private float GetDifficultyScale(TaskDifficulty difficulty) {
return difficulty switch {
TaskDifficulty.Water => 0.8f,
TaskDifficulty.Standard => 1.0f,
TaskDifficulty.Hardcore => 1.3f,
TaskDifficulty.BlackBox => 1.6f,
_ => 1.0f
};
}
///
/// 获取任务定义
///
private TaskDefinition GetTaskDefinition(TaskModel task) {
if (string.IsNullOrWhiteSpace(task.DefinitionId)) return null;
return _session.Content.Tasks.TryGetValue(task.DefinitionId, out var definition) ? definition : null;
}
///
/// 构建单位索引
///
private Dictionary BuildUnitIndex() {
var index = new Dictionary();
var roster = _session.State.Roster;
if (roster.Mentor != null) {
var unit = roster.Mentor.Core;
index[unit.Identity.Id] = new UnitEntry(unit, roster.Mentor, null, null);
}
foreach (var student in roster.Students) {
var unit = student.Core;
index[unit.Identity.Id] = new UnitEntry(unit, null, student, null);
}
foreach (var staff in roster.Staffs) {
var unit = staff.Core;
index[unit.Identity.Id] = new UnitEntry(unit, null, null, staff);
}
return index;
}
///
/// 追踪贡献
///
private void TrackContribution(UnitEntry entry, TaskModel task, float deltaContribution) {
if (entry.Student == null) return;
var contributions = entry.Student.Contributions.ByTask;
if (!contributions.TryGetValue(task.Id, out var value)) {
value = new PropertyValue(0, 0, 1000000);
contributions[task.Id] = value;
}
value.Add(deltaContribution);
}
private readonly struct UnitEntry {
public UnitModel Unit { get; }
public MentorModel Mentor { get; }
public StudentModel Student { get; }
public StaffModel Staff { get; }
public UnitEntry(UnitModel unit, MentorModel mentor, StudentModel student, StaffModel staff) {
Unit = unit;
Mentor = mentor;
Student = student;
Staff = staff;
}
}
}
///
/// 经济系统
///
public sealed class EconomySystem : IGameSystem {
private const int MasterSalary = 500;
private const int DoctorSalary = 800;
private const int PostDocSalary = 1200;
private const int JuniorFacultySalary = 2000;
private GameSession _session;
///
/// 初始化
///
/// 游戏会话
public void Initialize(GameSession session) {
_session = session;
_session.Events.Subscribe(OnTaskCompleted);
_session.Events.Subscribe(OnTaskFailed);
_session.Events.Subscribe(OnTurnEnded);
}
///
/// 更新
///
/// 帧间隔
public void Tick(float delta) {
// 当前为回合驱动,不在 Tick 中结算
}
///
/// 任务完成回调
///
private void OnTaskCompleted(TaskCompletedEvent evt) {
var task = evt.Task;
var economy = _session.State.Economy;
economy.Money += task.Reward.Money;
economy.Reputation += task.Reward.Reputation;
if (task.Reward.PaperIds.Count > 0) {
foreach (var paperId in task.Reward.PaperIds)
if (_session.Content.Papers.TryGetValue(paperId, out var paper))
AddPaper(paper.Rank);
}
else if (task.Kind == TaskKind.AcademicExploration) {
AddPaper(GetPaperRankByDifficulty(task.Difficulty));
}
foreach (var itemId in task.Reward.ItemIds) AddItem(itemId, 1);
}
///
/// 任务失败回调
///
private void OnTaskFailed(TaskFailedEvent evt) {
var task = evt.Task;
var penalty = task.Track == TaskTrack.Tenure ? 20 : 10;
if (task.Kind == TaskKind.GrantVertical) penalty += 10;
_session.State.Economy.Reputation -= penalty;
}
///
/// 回合结束回调
///
private void OnTurnEnded(TurnEndedEvent evt) {
ApplySalaries();
ApplyInterest();
}
///
/// 支付薪水
///
private void ApplySalaries() {
var economy = _session.State.Economy;
foreach (var student in _session.State.Roster.Students)
economy.Money -= student.Type == StudentModel.StudentType.MasterCandidate
? MasterSalary
: DoctorSalary;
foreach (var staff in _session.State.Roster.Staffs)
economy.Money -= staff.Type == StaffModel.StaffType.PostDoc
? PostDocSalary
: JuniorFacultySalary;
}
///
/// 计算利息
///
private void ApplyInterest() {
var economy = _session.State.Economy;
UpdateInterestRate();
if (economy.Money <= 0 || economy.InterestRate <= 0) return;
var interest = (int)(economy.Money * economy.InterestRate);
economy.Money += interest;
}
///
/// 更新利率
///
private void UpdateInterestRate() {
var economy = _session.State.Economy;
var mentor = _session.State.Roster.Mentor;
if (mentor?.Core.Tags.DisciplineId == CoreIds.DisciplineEconomics)
economy.InterestRate = Math.Max(economy.InterestRate, 0.1f);
}
///
/// 添加论文
///
private void AddPaper(PaperRank rank) {
var inventory = _session.State.Inventory;
if (!inventory.PaperCounts.ContainsKey(rank)) inventory.PaperCounts[rank] = 0;
inventory.PaperCounts[rank] += 1;
}
///
/// 添加物品
///
private void AddItem(string itemId, int count) {
if (string.IsNullOrWhiteSpace(itemId)) return;
var inventory = _session.State.Inventory;
if (!inventory.ItemCounts.ContainsKey(itemId)) inventory.ItemCounts[itemId] = 0;
inventory.ItemCounts[itemId] += count;
}
///
/// 根据难度获取论文等级
///
private PaperRank GetPaperRankByDifficulty(TaskDifficulty difficulty) {
return difficulty switch {
TaskDifficulty.Water => PaperRank.C,
TaskDifficulty.Standard => PaperRank.B,
TaskDifficulty.Hardcore => PaperRank.A,
TaskDifficulty.BlackBox => PaperRank.S,
_ => PaperRank.C
};
}
}
///
/// 羁绊/协同系统
///
public sealed class SynergySystem : IGameSystem {
private GameSession _session;
///
/// 初始化
///
/// 游戏会话
public void Initialize(GameSession session) {
_session = session;
}
///
/// 更新
///
/// 帧间隔
public void Tick(float delta) {
RecalculateSynergy();
}
///
/// 重新计算协同
///
private void RecalculateSynergy() {
var state = _session.State.Synergy;
state.ArchetypeStacks.Clear();
state.RoleStacks.Clear();
state.ActiveSynergyIds.Clear();
ClearModifiers(state.ActiveModifiers);
CountUnitTags(state);
ApplySynergyDefinitions(state);
}
///
/// 统计单位标签
///
private void CountUnitTags(SynergyState synergy) {
var roster = _session.State.Roster;
AddUnitTags(synergy, roster.Mentor?.Core);
foreach (var student in roster.Students) AddUnitTags(synergy, student.Core);
foreach (var staff in roster.Staffs) AddUnitTags(synergy, staff.Core);
}
///
/// 添加单位标签
///
private void AddUnitTags(SynergyState synergy, UnitModel unit) {
if (unit == null) return;
foreach (var archetypeId in unit.Tags.ArchetypeIds) AddStack(synergy.ArchetypeStacks, archetypeId);
foreach (var roleId in unit.Tags.RoleIds) AddStack(synergy.RoleStacks, roleId);
}
///
/// 增加堆叠计数
///
private void AddStack(Dictionary stacks, string id) {
if (string.IsNullOrWhiteSpace(id)) return;
if (!stacks.ContainsKey(id)) stacks[id] = 0;
stacks[id] += 1;
}
///
/// 应用协同定义
///
private void ApplySynergyDefinitions(SynergyState synergy) {
foreach (var archetype in _session.Content.Archetypes.Values)
ApplySynergyTier(archetype.Header.Id, archetype.Tiers, synergy.ArchetypeStacks, synergy);
foreach (var role in _session.Content.Roles.Values)
ApplySynergyTier(role.Header.Id, role.Tiers, synergy.RoleStacks, synergy);
}
///
/// 应用协同层级
///
private void ApplySynergyTier(string id, List tiers, Dictionary stacks,
SynergyState synergy) {
if (string.IsNullOrWhiteSpace(id)) return;
stacks.TryGetValue(id, out var count);
foreach (var tier in tiers) {
if (count < tier.RequiredCount) continue;
var synergyId = $"{id}@{tier.RequiredCount}";
synergy.ActiveSynergyIds.Add(synergyId);
MergeModifiers(synergy.ActiveModifiers, tier.Modifiers);
}
}
///
/// 合并修正
///
private void MergeModifiers(ModifierBundle target, ModifierBundle source) {
if (target == null || source == null) return;
target.AttributeModifiers.AddRange(source.AttributeModifiers);
target.StatusModifiers.AddRange(source.StatusModifiers);
target.ResourceModifiers.AddRange(source.ResourceModifiers);
target.RuleIds.AddRange(source.RuleIds);
}
///
/// 清除修正
///
private void ClearModifiers(ModifierBundle bundle) {
bundle.AttributeModifiers.Clear();
bundle.StatusModifiers.Clear();
bundle.ResourceModifiers.Clear();
bundle.RuleIds.Clear();
}
}
///
/// 分配系统
///
public sealed class AssignmentSystem : IGameSystem {
private GameSession _session;
///
/// 初始化
///
/// 游戏会话
public void Initialize(GameSession session) {
_session = session;
}
///
/// 更新
///
/// 帧间隔
public void Tick(float delta) {
// 预留:人员分配、交接惩罚等
}
}