Files
ArachnaeSwarm/Source/ArachnaeSwarm/HarmonyPatches/Patch_ResearchManager_AddRemoveMethod.cs
2025-12-19 17:27:32 +08:00

259 lines
11 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.
// 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();
}
}
}