259 lines
11 KiB
C#
259 lines
11 KiB
C#
// File: Utilities/ResearchRemover.cs
|
||
using RimWorld;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm
|
||
{
|
||
public static class ResearchRemover
|
||
{
|
||
private static FieldInfo progressField;
|
||
private static FieldInfo techprintsField;
|
||
private static FieldInfo anomalyKnowledgeField;
|
||
private static FieldInfo currentProjField;
|
||
private static FieldInfo currentAnomalyKnowledgeProjectsField;
|
||
|
||
static ResearchRemover()
|
||
{
|
||
// 一次性初始化反射字段
|
||
var type = typeof(ResearchManager);
|
||
progressField = type.GetField("progress", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
techprintsField = type.GetField("techprints", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
anomalyKnowledgeField = type.GetField("anomalyKnowledge", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
currentProjField = type.GetField("currentProj", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
currentAnomalyKnowledgeProjectsField = type.GetField("currentAnomalyKnowledgeProjects", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
|
||
if (progressField == null || techprintsField == null || anomalyKnowledgeField == null || currentProjField == null)
|
||
{
|
||
Log.Error("[ResearchRemover] Failed to find ResearchManager private fields!");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除一个已研发的科技项目
|
||
/// </summary>
|
||
/// <param name="projectDef">要移除的科技项目</param>
|
||
/// <param name="removeDependencies">是否同时移除依赖于此科技的科技</param>
|
||
/// <returns>是否成功移除</returns>
|
||
public static bool RemoveResearchProject(ResearchProjectDef projectDef, bool removeDependencies = false)
|
||
{
|
||
try
|
||
{
|
||
if (projectDef == null)
|
||
{
|
||
Log.Warning("[ResearchRemover] ProjectDef is null");
|
||
return false;
|
||
}
|
||
|
||
if (!projectDef.IsFinished)
|
||
{
|
||
Log.Warning($"[ResearchRemover] {projectDef.defName} is not finished, cannot remove.");
|
||
return false;
|
||
}
|
||
|
||
var manager = Find.ResearchManager;
|
||
if (manager == null)
|
||
{
|
||
Log.Error("[ResearchRemover] ResearchManager not found!");
|
||
return false;
|
||
}
|
||
|
||
ArachnaeLog.Debug($"[ResearchRemover] Removing research project: {projectDef.defName}");
|
||
|
||
// 获取字段值
|
||
var progress = (Dictionary<ResearchProjectDef, float>)progressField.GetValue(manager);
|
||
var techprints = (Dictionary<ResearchProjectDef, int>)techprintsField.GetValue(manager);
|
||
var anomalyKnowledge = (Dictionary<ResearchProjectDef, float>)anomalyKnowledgeField.GetValue(manager);
|
||
var currentProj = (ResearchProjectDef)currentProjField.GetValue(manager);
|
||
var currentAnomalyKnowledgeProjects = (List<ResearchManager.KnowledgeCategoryProject>)currentAnomalyKnowledgeProjectsField?.GetValue(manager);
|
||
|
||
// 检查是否有其他已完成的科技依赖于此科技
|
||
if (!CanSafelyRemove(projectDef, removeDependencies))
|
||
{
|
||
Log.Warning($"[ResearchRemover] Cannot remove {projectDef.defName}: other completed projects depend on it.");
|
||
return false;
|
||
}
|
||
|
||
// 1. 从进度字典中移除
|
||
if (progress != null && progress.ContainsKey(projectDef))
|
||
{
|
||
progress.Remove(projectDef);
|
||
ArachnaeLog.Debug($" Removed from progress dictionary");
|
||
}
|
||
|
||
// 2. 从科技碎片字典中移除
|
||
if (techprints != null && techprints.ContainsKey(projectDef))
|
||
{
|
||
techprints.Remove(projectDef);
|
||
ArachnaeLog.Debug($" Removed from techprints dictionary");
|
||
}
|
||
|
||
// 3. 从异常知识字典中移除
|
||
if (anomalyKnowledge != null && anomalyKnowledge.ContainsKey(projectDef))
|
||
{
|
||
anomalyKnowledge.Remove(projectDef);
|
||
ArachnaeLog.Debug($" Removed from anomalyKnowledge dictionary");
|
||
}
|
||
|
||
// 4. 如果这是当前项目,停止它
|
||
if (currentProj == projectDef)
|
||
{
|
||
manager.StopProject(projectDef);
|
||
currentProjField.SetValue(manager, null);
|
||
ArachnaeLog.Debug($" Stopped current project");
|
||
}
|
||
|
||
// 5. 从异常知识项目中移除
|
||
if (currentAnomalyKnowledgeProjects != null)
|
||
{
|
||
bool removed = false;
|
||
for (int i = currentAnomalyKnowledgeProjects.Count - 1; i >= 0; i--)
|
||
{
|
||
var knowledgeProject = currentAnomalyKnowledgeProjects[i];
|
||
if (knowledgeProject != null && knowledgeProject.project == projectDef)
|
||
{
|
||
knowledgeProject.project = null;
|
||
removed = true;
|
||
}
|
||
}
|
||
if (removed) ArachnaeLog.Debug($" Removed from anomaly knowledge projects");
|
||
}
|
||
|
||
// 6. 如果设置了移除依赖项,递归移除依赖于此科技的项目
|
||
if (removeDependencies)
|
||
{
|
||
RemoveDependentProjects(projectDef, progress, techprints, anomalyKnowledge,
|
||
currentProj, currentAnomalyKnowledgeProjects, manager);
|
||
}
|
||
|
||
// 7. 重新应用所有mod(取消该科技的效果)
|
||
manager.ReapplyAllMods();
|
||
|
||
ArachnaeLog.Debug($"[ResearchRemover] Successfully removed research project: {projectDef.defName}");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"[ResearchRemover] Error removing research project {projectDef.defName}: {ex}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否可以安全移除科技
|
||
/// </summary>
|
||
private static bool CanSafelyRemove(ResearchProjectDef projectDef, bool removeDependencies)
|
||
{
|
||
if (removeDependencies)
|
||
return true;
|
||
|
||
// 检查是否有其他已完成的科技依赖于此科技
|
||
foreach (var otherProject in DefDatabase<ResearchProjectDef>.AllDefs)
|
||
{
|
||
if (otherProject == projectDef || !otherProject.IsFinished)
|
||
continue;
|
||
|
||
if (otherProject.prerequisites != null && otherProject.prerequisites.Contains(projectDef))
|
||
{
|
||
Log.Warning($" - {otherProject.defName} depends on {projectDef.defName}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除所有依赖于此科技的科技项目
|
||
/// </summary>
|
||
private static void RemoveDependentProjects(ResearchProjectDef projectDef,
|
||
Dictionary<ResearchProjectDef, float> progress,
|
||
Dictionary<ResearchProjectDef, int> techprints,
|
||
Dictionary<ResearchProjectDef, float> anomalyKnowledge,
|
||
ResearchProjectDef currentProj,
|
||
List<ResearchManager.KnowledgeCategoryProject> currentAnomalyKnowledgeProjects,
|
||
ResearchManager manager)
|
||
{
|
||
// 查找所有依赖于此科技的项目
|
||
var dependentProjects = DefDatabase<ResearchProjectDef>.AllDefs
|
||
.Where(p => p != projectDef && p.IsFinished && p.prerequisites != null && p.prerequisites.Contains(projectDef))
|
||
.ToList();
|
||
|
||
foreach (var dependent in dependentProjects)
|
||
{
|
||
ArachnaeLog.Debug($" Removing dependent project: {dependent.defName}");
|
||
|
||
// 递归移除依赖项
|
||
RemoveDependentProjects(dependent, progress, techprints, anomalyKnowledge,
|
||
currentProj, currentAnomalyKnowledgeProjects, manager);
|
||
|
||
// 移除当前项目
|
||
if (progress != null && progress.ContainsKey(dependent))
|
||
progress.Remove(dependent);
|
||
|
||
if (techprints != null && techprints.ContainsKey(dependent))
|
||
techprints.Remove(dependent);
|
||
|
||
if (anomalyKnowledge != null && anomalyKnowledge.ContainsKey(dependent))
|
||
anomalyKnowledge.Remove(dependent);
|
||
|
||
if (currentProj == dependent)
|
||
{
|
||
manager.StopProject(dependent);
|
||
currentProjField.SetValue(manager, null);
|
||
}
|
||
|
||
if (currentAnomalyKnowledgeProjects != null)
|
||
{
|
||
for (int i = currentAnomalyKnowledgeProjects.Count - 1; i >= 0; i--)
|
||
{
|
||
var knowledgeProject = currentAnomalyKnowledgeProjects[i];
|
||
if (knowledgeProject != null && knowledgeProject.project == dependent)
|
||
{
|
||
knowledgeProject.project = null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批量移除多个科技项目
|
||
/// </summary>
|
||
public static int RemoveMultipleProjects(IEnumerable<ResearchProjectDef> projectDefs, bool removeDependencies = false)
|
||
{
|
||
int count = 0;
|
||
foreach (var project in projectDefs)
|
||
{
|
||
if (RemoveResearchProject(project, removeDependencies))
|
||
count++;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除所有科技(重置研究)
|
||
/// </summary>
|
||
public static void RemoveAllResearch()
|
||
{
|
||
var manager = Find.ResearchManager;
|
||
if (manager == null) return;
|
||
|
||
var allFinishedProjects = DefDatabase<ResearchProjectDef>.AllDefs
|
||
.Where(p => p.IsFinished)
|
||
.ToList();
|
||
|
||
ArachnaeLog.Debug($"[ResearchRemover] Removing all {allFinishedProjects.Count} finished research projects");
|
||
|
||
// 批量移除所有科技
|
||
RemoveMultipleProjects(allFinishedProjects, false);
|
||
|
||
// 也可以调用原版的 ResetAllProgress 方法
|
||
// manager.ResetAllProgress();
|
||
}
|
||
}
|
||
}
|