333 lines
12 KiB
C#
333 lines
12 KiB
C#
// File: Comps/CompProperties_EquipmentIncubatorData.cs
|
||
using RimWorld;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using UnityEngine;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm
|
||
{
|
||
// 装备孵化配置
|
||
public class EquipmentIncubationConfig : IExposable
|
||
{
|
||
public ThingDef thingDef;
|
||
public ResearchProjectDef requiredResearch;
|
||
public float daysRequired; // 从stat中读取
|
||
public string buttonIconPath;
|
||
|
||
// 缓存的生产时间(避免重复获取stat)
|
||
private float? cachedDaysRequired;
|
||
|
||
public EquipmentIncubationConfig() { }
|
||
|
||
public EquipmentIncubationConfig(ThingDef thingDef, ResearchProjectDef requiredResearch = null,
|
||
string buttonIconPath = null)
|
||
{
|
||
this.thingDef = thingDef;
|
||
this.requiredResearch = requiredResearch;
|
||
this.buttonIconPath = buttonIconPath;
|
||
cachedDaysRequired = null;
|
||
}
|
||
|
||
public void ExposeData()
|
||
{
|
||
Scribe_Defs.Look(ref thingDef, "thingDef");
|
||
Scribe_Defs.Look(ref requiredResearch, "requiredResearch");
|
||
Scribe_Values.Look(ref buttonIconPath, "buttonIconPath");
|
||
|
||
// 不保存缓存值,重新计算
|
||
if (Scribe.mode == LoadSaveMode.LoadingVars)
|
||
{
|
||
cachedDaysRequired = null;
|
||
}
|
||
}
|
||
|
||
// 获取生产时间(天)
|
||
public float DaysRequired
|
||
{
|
||
get
|
||
{
|
||
if (cachedDaysRequired.HasValue)
|
||
return cachedDaysRequired.Value;
|
||
|
||
if (thingDef == null)
|
||
{
|
||
cachedDaysRequired = 1f;
|
||
return cachedDaysRequired.Value;
|
||
}
|
||
|
||
// 从stat中读取ARA_IncubationTime
|
||
var statDef = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationTime");
|
||
if (statDef != null)
|
||
{
|
||
cachedDaysRequired = thingDef.GetStatValueAbstract(statDef, null);
|
||
}
|
||
else
|
||
{
|
||
// 默认值
|
||
cachedDaysRequired = 1f;
|
||
}
|
||
|
||
return cachedDaysRequired.Value;
|
||
}
|
||
}
|
||
|
||
// 检查是否满足研究要求
|
||
public bool IsResearchComplete => requiredResearch == null || requiredResearch.IsFinished;
|
||
|
||
// 获取描述
|
||
public string GetDescription()
|
||
{
|
||
var builder = new StringBuilder();
|
||
|
||
if (thingDef != null)
|
||
{
|
||
builder.AppendLine(thingDef.description ?? "ARA_EquipmentIncubator.NoDescription".Translate());
|
||
builder.AppendLine();
|
||
builder.AppendLine("ARA_EquipmentIncubator.IncubationTime".Translate(DaysRequired));
|
||
}
|
||
|
||
if (requiredResearch != null)
|
||
{
|
||
if (requiredResearch.IsFinished)
|
||
builder.AppendLine("ARA_EquipmentIncubator.ResearchCompleted".Translate(requiredResearch.LabelCap));
|
||
else
|
||
builder.AppendLine("ARA_EquipmentIncubator.ResearchRequired".Translate(requiredResearch.LabelCap));
|
||
}
|
||
|
||
return builder.ToString().TrimEndNewlines();
|
||
}
|
||
}
|
||
|
||
// 装备孵化器组件属性
|
||
public class CompProperties_EquipmentIncubatorData : CompProperties
|
||
{
|
||
// 支持手动指定配置列表(可选)
|
||
public List<EquipmentIncubationConfig> incubationConfigs;
|
||
|
||
// 默认选择索引
|
||
public int defaultIndex = 0;
|
||
|
||
// Gizmo相关配置
|
||
public string buttonLabel = "ARA_EquipmentIncubator.IncubateLabel";
|
||
public string buttonDesc = "ARA_EquipmentIncubator.ButtonDesc";
|
||
public string menuTitle = "ARA_EquipmentIncubator.MenuTitle";
|
||
public string defaultIconPath = "UI/Commands/Default";
|
||
|
||
// 是否自动扫描所有ThingDef来构建配置列表
|
||
public bool autoScanThingDefs = true;
|
||
|
||
// 手动指定要扫描的ThingDef类型(可选)
|
||
public List<string> thingDefCategories;
|
||
public List<ThingCategoryDef> thingCategoryDefs;
|
||
|
||
public CompProperties_EquipmentIncubatorData()
|
||
{
|
||
compClass = typeof(CompEquipmentIncubatorData);
|
||
}
|
||
}
|
||
|
||
// 装备孵化器数据组件
|
||
public class CompEquipmentIncubatorData : ThingComp
|
||
{
|
||
private CompProperties_EquipmentIncubatorData Props => (CompProperties_EquipmentIncubatorData)props;
|
||
|
||
// 当前选择的配置索引
|
||
private int selectedIndex = -1;
|
||
|
||
// 缓存的配置列表
|
||
private List<EquipmentIncubationConfig> cachedConfigs;
|
||
private bool configsBuilt = false;
|
||
|
||
// 公开获取孵化配置列表的方法
|
||
public List<EquipmentIncubationConfig> IncubationConfigs
|
||
{
|
||
get
|
||
{
|
||
if (!configsBuilt)
|
||
{
|
||
BuildIncubationConfigs();
|
||
}
|
||
return cachedConfigs ?? new List<EquipmentIncubationConfig>();
|
||
}
|
||
}
|
||
|
||
// 获取当前选择的配置
|
||
public EquipmentIncubationConfig SelectedConfig
|
||
{
|
||
get
|
||
{
|
||
var configs = IncubationConfigs;
|
||
if (configs.Count == 0) return null;
|
||
|
||
// 初始化选择
|
||
if (selectedIndex == -1)
|
||
{
|
||
selectedIndex = Mathf.Clamp(Props.defaultIndex, 0, configs.Count - 1);
|
||
}
|
||
|
||
if (selectedIndex < 0 || selectedIndex >= configs.Count)
|
||
selectedIndex = 0;
|
||
|
||
return configs[selectedIndex];
|
||
}
|
||
}
|
||
|
||
// 获取当前选择的ThingDef
|
||
public ThingDef SelectedThingDef => SelectedConfig?.thingDef;
|
||
|
||
// 构建孵化配置列表
|
||
private void BuildIncubationConfigs()
|
||
{
|
||
cachedConfigs = new List<EquipmentIncubationConfig>();
|
||
configsBuilt = true;
|
||
|
||
// 优先使用手动配置的列表
|
||
if (Props.incubationConfigs != null && Props.incubationConfigs.Count > 0)
|
||
{
|
||
foreach (var config in Props.incubationConfigs)
|
||
{
|
||
if (config?.thingDef != null)
|
||
{
|
||
cachedConfigs.Add(config);
|
||
}
|
||
}
|
||
|
||
if (cachedConfigs.Count > 0)
|
||
return;
|
||
}
|
||
|
||
// 如果没有手动配置,且启用了自动扫描,则扫描所有ThingDef
|
||
if (Props.autoScanThingDefs)
|
||
{
|
||
ScanThingDefsForConfigs();
|
||
}
|
||
}
|
||
|
||
// 扫描所有ThingDef来构建配置列表
|
||
private void ScanThingDefsForConfigs()
|
||
{
|
||
var allThingDefs = DefDatabase<ThingDef>.AllDefsListForReading;
|
||
|
||
foreach (var thingDef in allThingDefs)
|
||
{
|
||
// 检查该ThingDef是否包含CompProperties_ExtraIncubationInfo组件
|
||
var extraInfoProps = thingDef.comps?.FirstOrDefault(c => c is CompProperties_ExtraIncubationInfo)
|
||
as CompProperties_ExtraIncubationInfo;
|
||
|
||
if (extraInfoProps == null)
|
||
continue;
|
||
|
||
// 检查cocoonDefs是否包含当前建筑
|
||
bool isForThisCocoon = false;
|
||
|
||
if (extraInfoProps.cocoonDefs != null && extraInfoProps.cocoonDefs.Count > 0)
|
||
{
|
||
isForThisCocoon = extraInfoProps.cocoonDefs.Contains(parent.def);
|
||
}
|
||
else if (extraInfoProps.cocoonDef != null)
|
||
{
|
||
// 向后兼容:检查单个cocoonDef
|
||
isForThisCocoon = extraInfoProps.cocoonDef == parent.def;
|
||
}
|
||
|
||
if (!isForThisCocoon)
|
||
continue;
|
||
|
||
// 检查是否有ARA_IncubationTime这个stat
|
||
var incubationTimeStat = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationTime");
|
||
if (incubationTimeStat == null)
|
||
{
|
||
Log.Warning($"ThingDef {thingDef.defName} has CompProperties_ExtraIncubationInfo but ARA_IncubationTime stat is not defined.");
|
||
continue;
|
||
}
|
||
|
||
// 获取孵化时间
|
||
float daysRequired = thingDef.GetStatValueAbstract(incubationTimeStat, null);
|
||
if (daysRequired <= 0)
|
||
{
|
||
Log.Warning($"ThingDef {thingDef.defName} has invalid incubation time: {daysRequired}");
|
||
continue;
|
||
}
|
||
|
||
// 创建配置
|
||
var config = new EquipmentIncubationConfig
|
||
{
|
||
thingDef = thingDef,
|
||
daysRequired = daysRequired,
|
||
// 可以在这里添加其他配置,比如所需研究等
|
||
// requiredResearch = ...
|
||
// buttonIconPath = ...
|
||
};
|
||
|
||
cachedConfigs.Add(config);
|
||
}
|
||
|
||
// 按物品名称排序
|
||
cachedConfigs.Sort((a, b) => string.Compare(a.thingDef?.label ?? "", b.thingDef?.label ?? ""));
|
||
|
||
Log.Message($"Built {cachedConfigs.Count} equipment incubation configs for {parent.def.defName}");
|
||
}
|
||
|
||
// 切换到特定索引
|
||
public void SwitchToConfig(int index)
|
||
{
|
||
if (index >= 0 && index < IncubationConfigs.Count)
|
||
{
|
||
selectedIndex = index;
|
||
}
|
||
}
|
||
|
||
// 检查配置是否可用(研究是否完成)
|
||
public bool IsConfigAvailable(int index)
|
||
{
|
||
if (index < 0 || index >= IncubationConfigs.Count)
|
||
return false;
|
||
|
||
var config = IncubationConfigs[index];
|
||
return config?.IsResearchComplete ?? false;
|
||
}
|
||
|
||
// 获取配置索引
|
||
public int GetSelectedIndex()
|
||
{
|
||
return selectedIndex;
|
||
}
|
||
|
||
// 存档加载
|
||
public override void PostExposeData()
|
||
{
|
||
base.PostExposeData();
|
||
Scribe_Values.Look(ref selectedIndex, "selectedIndex", -1);
|
||
Scribe_Values.Look(ref configsBuilt, "configsBuilt", false);
|
||
|
||
if (Scribe.mode == LoadSaveMode.LoadingVars)
|
||
{
|
||
// 重置缓存,在需要时重新构建
|
||
cachedConfigs = null;
|
||
configsBuilt = false;
|
||
}
|
||
}
|
||
|
||
// 在建筑信息中显示额外信息
|
||
public override string CompInspectStringExtra()
|
||
{
|
||
var current = SelectedConfig;
|
||
if (current != null && current.thingDef != null)
|
||
{
|
||
string status = "ARA_EquipmentIncubator.IncubationTarget".Translate(current.thingDef.LabelCap);
|
||
|
||
if (current.requiredResearch != null && !current.requiredResearch.IsFinished)
|
||
{
|
||
status += " (" + "ARA_EquipmentIncubator.Requires".Translate() + ": " + current.requiredResearch.LabelCap + ")";
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
return base.CompInspectStringExtra();
|
||
}
|
||
}
|
||
}
|