zc
This commit is contained in:
Binary file not shown.
@@ -3,12 +3,8 @@
|
||||
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_destroyownbodypart\\compabilityeffect_destroyownbodypart.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_destroyownbodypart\\compabilityeffect_destroyownbodypart.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_destroyownbodypart\\compproperties_abilitydestroyownbodypart.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_destroyownbodypart\\compproperties_abilitydestroyownbodypart.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\stat\\statworker_incubationinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:stat\\statworker_incubationinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
@@ -18,35 +14,23 @@
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 2,
|
||||
"SelectedChildIndex": 1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CompProperties_AbilityDestroyOwnBodyPart.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_DestroyOwnBodyPart\\CompProperties_AbilityDestroyOwnBodyPart.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_DestroyOwnBodyPart\\CompProperties_AbilityDestroyOwnBodyPart.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_DestroyOwnBodyPart\\CompProperties_AbilityDestroyOwnBodyPart.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_DestroyOwnBodyPart\\CompProperties_AbilityDestroyOwnBodyPart.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-09-28T08:57:43.206Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "CompAbilityEffect_DestroyOwnBodyPart.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_DestroyOwnBodyPart\\CompAbilityEffect_DestroyOwnBodyPart.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_DestroyOwnBodyPart\\CompAbilityEffect_DestroyOwnBodyPart.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_DestroyOwnBodyPart\\CompAbilityEffect_DestroyOwnBodyPart.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_DestroyOwnBodyPart\\CompAbilityEffect_DestroyOwnBodyPart.cs",
|
||||
"ViewState": "AgIAADYAAAAAAAAAAAAIwGIAAAAJAAAAAAAAAA==",
|
||||
"Title": "StatWorker_IncubationInfo.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Stat\\StatWorker_IncubationInfo.cs",
|
||||
"RelativeDocumentMoniker": "Stat\\StatWorker_IncubationInfo.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Stat\\StatWorker_IncubationInfo.cs",
|
||||
"RelativeToolTip": "Stat\\StatWorker_IncubationInfo.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-09-28T08:57:31.224Z",
|
||||
"WhenOpened": "2025-09-30T08:38:06.014Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
|
||||
@@ -170,9 +170,12 @@
|
||||
<Compile Include="Hediffs\WULA_HediffDamgeShield\DRMDamageShield.cs" />
|
||||
<Compile Include="Hediffs\WULA_HediffDamgeShield\Hediff_DamageShield.cs" />
|
||||
<Compile Include="Hediff_DynamicInterceptor.cs" />
|
||||
<Compile Include="Stat\StatWorker_IncubationInfo.cs" />
|
||||
<Compile Include="ThingComp_GuardianPsyField.cs" />
|
||||
<Compile Include="Harmony_ProjectileInterceptor.cs" />
|
||||
<Compile Include="MainHarmony.cs" />
|
||||
<Compile Include="Thing_Comps\ARA_CompExtraIncubationInfo\CompExtraIncubationInfo.cs" />
|
||||
<Compile Include="Thing_Comps\ARA_CompExtraIncubationInfo\CompProperties_ExtraIncubationInfo.cs" />
|
||||
<Compile Include="Thing_Comps\CompAndPatch_GiveHediffOnShot.cs" />
|
||||
<Compile Include="Pawn_Comps\ARA_AutoMechCarrier\CompAutoMechCarrier.cs" />
|
||||
<Compile Include="Pawn_Comps\ARA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />
|
||||
|
||||
@@ -8,11 +8,9 @@ using Verse.AI;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
// V14: Final refactor to work with the new GrowthVat-style fuel comp.
|
||||
|
||||
public class CompProperties_InteractiveProducer : CompProperties
|
||||
{
|
||||
public List<ProcessDef> processes;
|
||||
// 不再需要手动配置 processes 列表
|
||||
public List<PawnKindDef> whitelist;
|
||||
public IntRange spawnCount = new IntRange(1, 1);
|
||||
public bool destroyOnSpawn;
|
||||
@@ -21,7 +19,7 @@ namespace ArachnaeSwarm
|
||||
public float penaltyPerDegreePerTick = 0.00001f;
|
||||
public List<QualityThreshold> qualityThresholds;
|
||||
public float damagePerTickWhenUnfueled = 0.2f;
|
||||
public float minNutritionToStart = 0.1f; // Minimum fuel required to start a process
|
||||
public float minNutritionToStart = 0.1f;
|
||||
|
||||
public CompProperties_InteractiveProducer()
|
||||
{
|
||||
@@ -36,12 +34,27 @@ namespace ArachnaeSwarm
|
||||
private int productionUntilTick = -1;
|
||||
private int ticksUnderOptimalConditions;
|
||||
private float temperaturePenaltyPercent;
|
||||
private List<ProcessDef> _cachedProcesses;
|
||||
|
||||
private CompRefuelableNutrition _fuelComp;
|
||||
private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
|
||||
|
||||
public bool InProduction => _selectedProcess != null;
|
||||
public CompProperties_InteractiveProducer Props => (CompProperties_InteractiveProducer)props;
|
||||
|
||||
// 自动生成的 ProcessDef 列表
|
||||
public List<ProcessDef> Processes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cachedProcesses == null)
|
||||
{
|
||||
BuildProcessList();
|
||||
}
|
||||
return _cachedProcesses;
|
||||
}
|
||||
}
|
||||
|
||||
private CompRefuelableNutrition FuelComp
|
||||
{
|
||||
get
|
||||
@@ -55,12 +68,126 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
_fuelComp = parent.GetComp<CompRefuelableNutrition>();
|
||||
BuildProcessList(); // 确保进程列表在生成时构建
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
// ... (Scribe logic is the same as V11) ...
|
||||
|
||||
// 序列化 selectedProcess 的 thingDef 而不是整个 ProcessDef
|
||||
ThingDef selectedProcessThingDef = _selectedProcess?.thingDef;
|
||||
Scribe_Defs.Look(ref selectedProcessThingDef, "selectedProcessThingDef");
|
||||
|
||||
Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1);
|
||||
Scribe_Values.Look(ref ticksUnderOptimalConditions, "ticksUnderOptimalConditions", 0);
|
||||
Scribe_Values.Look(ref temperaturePenaltyPercent, "temperaturePenaltyPercent", 0f);
|
||||
|
||||
// 加载时重建 selectedProcess
|
||||
if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessThingDef != null)
|
||||
{
|
||||
// 确保 Processes 列表已构建
|
||||
if (_cachedProcesses == null)
|
||||
{
|
||||
BuildProcessList();
|
||||
}
|
||||
|
||||
// 根据 thingDef 找到对应的 ProcessDef
|
||||
_selectedProcess = Processes.FirstOrDefault(p => p.thingDef == selectedProcessThingDef);
|
||||
|
||||
// 如果找不到对应的 ProcessDef,重置生产状态
|
||||
if (_selectedProcess == null)
|
||||
{
|
||||
Log.Warning($"Could not find ProcessDef for {selectedProcessThingDef.defName} after loading. Resetting production.");
|
||||
ResetProduction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动构建 ProcessDef 列表的方法
|
||||
private void BuildProcessList()
|
||||
{
|
||||
_cachedProcesses = new List<ProcessDef>();
|
||||
|
||||
// 扫描所有定义了 CompExtraIncubationInfo 的物品
|
||||
foreach (ThingDef thingDef in DefDatabase<ThingDef>.AllDefs)
|
||||
{
|
||||
// 检查是否是服装或武器
|
||||
if (thingDef.IsApparel || thingDef.IsWeapon)
|
||||
{
|
||||
var incubationCompProps = thingDef.GetCompProperties<CompProperties_ExtraIncubationInfo>();
|
||||
if (incubationCompProps != null && incubationCompProps.cocoonDef == parent.def)
|
||||
{
|
||||
// 获取研究前提 - 从 recipeMaker 中获取
|
||||
ResearchProjectDef researchPrerequisite = null;
|
||||
|
||||
// 方法1:从 recipeMaker.researchPrerequisite 获取
|
||||
if (thingDef.recipeMaker?.researchPrerequisite != null)
|
||||
{
|
||||
researchPrerequisite = thingDef.recipeMaker.researchPrerequisite;
|
||||
}
|
||||
// 方法2:从 recipeMaker.researchPrerequisites 获取第一个
|
||||
else if (thingDef.recipeMaker?.researchPrerequisites?.Count > 0)
|
||||
{
|
||||
researchPrerequisite = thingDef.recipeMaker.researchPrerequisites[0];
|
||||
}
|
||||
// 方法3:从 thingDef.researchPrerequisites 获取(备用)
|
||||
else if (thingDef.researchPrerequisites?.Count > 0)
|
||||
{
|
||||
researchPrerequisite = thingDef.researchPrerequisites[0];
|
||||
}
|
||||
|
||||
// 创建 ProcessDef
|
||||
ProcessDef process = new ProcessDef
|
||||
{
|
||||
thingDef = thingDef,
|
||||
productionTicks = GetIncubationTimeTicks(thingDef),
|
||||
totalNutritionNeeded = GetIncubationCost(thingDef),
|
||||
requiredResearch = researchPrerequisite
|
||||
};
|
||||
|
||||
_cachedProcesses.Add(process);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按物品名称排序以便更好的 UI 显示
|
||||
_cachedProcesses.SortBy(p => p.thingDef.label);
|
||||
}
|
||||
|
||||
// 获取孵化时间(转换为 ticks)
|
||||
private int GetIncubationTimeTicks(ThingDef thingDef)
|
||||
{
|
||||
StatDef incubationTimeStat = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationTime");
|
||||
if (incubationTimeStat != null && thingDef.statBases != null)
|
||||
{
|
||||
var statValue = thingDef.statBases.FirstOrDefault(s => s.stat == incubationTimeStat);
|
||||
if (statValue != null)
|
||||
{
|
||||
// ARA_IncubationTime 是以天为单位,转换为 ticks (1天 = 60000 ticks)
|
||||
return Mathf.RoundToInt(statValue.value * 60000f);
|
||||
}
|
||||
}
|
||||
|
||||
// 默认值:1 天
|
||||
return 60000;
|
||||
}
|
||||
|
||||
// 获取孵化所需营养
|
||||
private float GetIncubationCost(ThingDef thingDef)
|
||||
{
|
||||
StatDef incubationCostStat = DefDatabase<StatDef>.GetNamedSilentFail("ARA_IncubationCost");
|
||||
if (incubationCostStat != null && thingDef.statBases != null)
|
||||
{
|
||||
var statValue = thingDef.statBases.FirstOrDefault(s => s.stat == incubationCostStat);
|
||||
if (statValue != null)
|
||||
{
|
||||
return statValue.value;
|
||||
}
|
||||
}
|
||||
|
||||
// 默认值:10 营养
|
||||
return 10f;
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
@@ -70,8 +197,6 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
if (FuelComp == null) return;
|
||||
|
||||
// Nutrition consumption is now handled by CompRefuelableNutrition's CompTick.
|
||||
// We just need to check if there is any fuel left.
|
||||
bool hasFuel = FuelComp.HasFuel;
|
||||
|
||||
if (!hasFuel)
|
||||
@@ -110,7 +235,8 @@ namespace ArachnaeSwarm
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var process in Props.processes)
|
||||
// 使用自动生成的 Processes 列表
|
||||
foreach (var process in Processes)
|
||||
{
|
||||
if (process.requiredResearch != null && !process.requiredResearch.IsFinished)
|
||||
{
|
||||
@@ -135,7 +261,6 @@ namespace ArachnaeSwarm
|
||||
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
|
||||
ticksUnderOptimalConditions = 0;
|
||||
temperaturePenaltyPercent = 0f;
|
||||
// Set the consumption rate on the fuel comp (nutrition per day)
|
||||
float nutritionPerDay = (_selectedProcess.totalNutritionNeeded / _selectedProcess.productionTicks) * 60000f;
|
||||
FuelComp.currentConsumptionRate = nutritionPerDay;
|
||||
}
|
||||
@@ -144,25 +269,21 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
if (!InProduction || Props.qualityThresholds.NullOrEmpty())
|
||||
{
|
||||
return (QualityCategory.Normal, 0f, 0f); // Default or no quality system
|
||||
return (QualityCategory.Normal, 0f, 0f);
|
||||
}
|
||||
|
||||
// Estimate progress based on optimal ticks vs total ticks
|
||||
float progress = (float)ticksUnderOptimalConditions / _selectedProcess.productionTicks;
|
||||
// Apply temperature penalty
|
||||
float finalQualityPercent = Mathf.Clamp01(progress - temperaturePenaltyPercent);
|
||||
|
||||
QualityCategory finalQuality = QualityCategory.Awful;
|
||||
// Find the best quality that meets the threshold
|
||||
foreach (var threshold in Props.qualityThresholds.OrderByDescending(q => q.threshold))
|
||||
{
|
||||
if (finalQualityPercent >= threshold.threshold)
|
||||
{
|
||||
finalQuality = threshold.quality;
|
||||
break; // Exit after finding the highest met quality
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If no threshold is met, it will remain the lowest quality
|
||||
if (finalQuality == QualityCategory.Awful && Props.qualityThresholds.Any())
|
||||
{
|
||||
finalQuality = Props.qualityThresholds.OrderBy(q => q.threshold).First().quality;
|
||||
@@ -179,27 +300,22 @@ namespace ArachnaeSwarm
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Determine final quality
|
||||
var qualityDetails = GetEstimatedQualityDetails();
|
||||
QualityCategory finalQuality = qualityDetails.quality;
|
||||
|
||||
// 2. Create and spawn the item
|
||||
for (int i = 0; i < Props.spawnCount.RandomInRange; i++)
|
||||
{
|
||||
Thing product = ThingMaker.MakeThing(_selectedProcess.thingDef);
|
||||
product.TryGetComp<CompQuality>()?.SetQuality(finalQuality, ArtGenerationContext.Colony);
|
||||
|
||||
// Spawn the item near the parent building
|
||||
GenPlace.TryPlaceThing(product, parent.Position, parent.Map, ThingPlaceMode.Near);
|
||||
}
|
||||
|
||||
// 3. Destroy self if configured
|
||||
if (Props.destroyOnSpawn)
|
||||
{
|
||||
parent.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
|
||||
// 4. Reset state
|
||||
ResetProduction();
|
||||
}
|
||||
|
||||
@@ -221,13 +337,11 @@ namespace ArachnaeSwarm
|
||||
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
|
||||
sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod());
|
||||
|
||||
// Quality Details
|
||||
var qualityDetails = GetEstimatedQualityDetails();
|
||||
sb.AppendLine("EstimatedQuality".Translate() + ": " + qualityDetails.quality.GetLabel());
|
||||
sb.AppendLine($" {"QualityScore".Translate()}: {qualityDetails.baseScore.ToStringPercent("F0")}");
|
||||
sb.AppendLine($" {"TemperaturePenalty".Translate()}: -{qualityDetails.penalty.ToStringPercent("F0")}");
|
||||
|
||||
// Temperature Details
|
||||
string tempStr = "CurrentTemperature".Translate(parent.AmbientTemperature.ToStringTemperature("F0"));
|
||||
tempStr += $" ({"SafeTemperatureRange".Translate()}: {Props.minSafeTemperature.ToStringTemperature("F0")} ~ {Props.maxSafeTemperature.ToStringTemperature("F0")})";
|
||||
sb.AppendLine(tempStr);
|
||||
@@ -236,7 +350,9 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
if (!InProduction)
|
||||
{
|
||||
return "ARA_NeedArachnaeToStartIncubation".Translate();
|
||||
// 显示可生产的物品数量
|
||||
int availableProcesses = Processes.Count(p => p.requiredResearch == null || p.requiredResearch.IsFinished);
|
||||
return "ARA_NeedArachnaeToStartIncubation".Translate() + $" ({availableProcesses} items available)";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -255,4 +371,4 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
172
Source/ArachnaeSwarm/Stat/StatWorker_IncubationInfo.cs
Normal file
172
Source/ArachnaeSwarm/Stat/StatWorker_IncubationInfo.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
// ARA_IncubationCost 的 StatWorker
|
||||
public class StatWorker_IncubationCost : StatWorker
|
||||
{
|
||||
public override bool ShouldShowFor(StatRequest req)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 只在拥有 CompProperties_ExtraIncubationInfo 的 ThingDef 上显示
|
||||
if (!base.ShouldShowFor(req))
|
||||
return false;
|
||||
|
||||
return HasIncubationComp(req);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationCost.ShouldShowFor for {req.Def?.defName}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetValueUnfinalized(StatRequest req, bool applyPostProcess = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从 ThingDef 的 statBases 中获取值
|
||||
if (req.Def is ThingDef thingDef)
|
||||
{
|
||||
var statModifier = thingDef.statBases?.FirstOrDefault(s => s.stat == this.stat);
|
||||
if (statModifier != null)
|
||||
{
|
||||
return statModifier.value;
|
||||
}
|
||||
}
|
||||
|
||||
return base.GetValueUnfinalized(req, applyPostProcess);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationCost.GetValueUnfinalized for {req.Def?.defName}: {ex.Message}");
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetExplanationUnfinalized(StatRequest req, ToStringNumberSense numberSense)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!HasIncubationComp(req))
|
||||
return string.Empty;
|
||||
|
||||
float value = GetValueUnfinalized(req);
|
||||
return "IncubationCostDesc".Translate(value);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationCost.GetExplanationUnfinalized for {req.Def?.defName}: {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasIncubationComp(StatRequest req)
|
||||
{
|
||||
try
|
||||
{
|
||||
ThingDef thingDef = req.Def as ThingDef ?? req.Thing?.def;
|
||||
return thingDef?.comps?.Any(c => c is CompProperties_ExtraIncubationInfo) == true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationCost.HasIncubationComp for {req.Def?.defName}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ARA_IncubationTime 的 StatWorker
|
||||
public class StatWorker_IncubationTime : StatWorker
|
||||
{
|
||||
public override bool ShouldShowFor(StatRequest req)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 只在拥有 CompProperties_ExtraIncubationInfo 的 ThingDef 上显示
|
||||
if (!base.ShouldShowFor(req))
|
||||
return false;
|
||||
|
||||
return HasIncubationComp(req);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationTime.ShouldShowFor for {req.Def?.defName}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetValueUnfinalized(StatRequest req, bool applyPostProcess = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从 ThingDef 的 statBases 中获取值
|
||||
if (req.Def is ThingDef thingDef)
|
||||
{
|
||||
var statModifier = thingDef.statBases?.FirstOrDefault(s => s.stat == this.stat);
|
||||
if (statModifier != null)
|
||||
{
|
||||
return statModifier.value;
|
||||
}
|
||||
}
|
||||
|
||||
return base.GetValueUnfinalized(req, applyPostProcess);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationTime.GetValueUnfinalized for {req.Def?.defName}: {ex.Message}");
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetExplanationUnfinalized(StatRequest req, ToStringNumberSense numberSense)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!HasIncubationComp(req))
|
||||
return string.Empty;
|
||||
|
||||
float value = GetValueUnfinalized(req);
|
||||
return "IncubationTimeDesc".Translate(value);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationTime.GetExplanationUnfinalized for {req.Def?.defName}: {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStatDrawEntryLabel(StatDef stat, float value, ToStringNumberSense numberSense, StatRequest req, bool finalized = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!HasIncubationComp(req))
|
||||
return base.GetStatDrawEntryLabel(stat, value, numberSense, req, finalized);
|
||||
|
||||
return value + " days";
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationTime.GetStatDrawEntryLabel for {req.Def?.defName}: {ex.Message}");
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasIncubationComp(StatRequest req)
|
||||
{
|
||||
try
|
||||
{
|
||||
ThingDef thingDef = req.Def as ThingDef ?? req.Thing?.def;
|
||||
return thingDef?.comps?.Any(c => c is CompProperties_ExtraIncubationInfo) == true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Warning($"Error in StatWorker_IncubationTime.HasIncubationComp for {req.Def?.defName}: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompExtraIncubationInfo : ThingComp
|
||||
{
|
||||
public CompProperties_ExtraIncubationInfo Props => (CompProperties_ExtraIncubationInfo)props;
|
||||
|
||||
// 公开属性,供其他组件读取
|
||||
public ThingDef CocoonDef => Props.cocoonDef;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_ExtraIncubationInfo : CompProperties
|
||||
{
|
||||
// 指定的茧建筑定义
|
||||
public ThingDef cocoonDef;
|
||||
public CompProperties_ExtraIncubationInfo()
|
||||
{
|
||||
compClass = typeof(CompExtraIncubationInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user