diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index d56bfb1..164255d 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
index 05e370b..2856bc2 100644
--- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
+++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
@@ -293,7 +293,7 @@
ARA_NeuroSwarm_jump
ARA_GuardianPsyField_On
ARA_GuardianPsyField_Off
-
+ ARA_Ability_Morph
diff --git a/1.6/1.6/Defs/Stats/ARA_Stats.xml b/1.6/1.6/Defs/Stats/ARA_Stats.xml
index 7b818f6..abd7706 100644
--- a/1.6/1.6/Defs/Stats/ARA_Stats.xml
+++ b/1.6/1.6/Defs/Stats/ARA_Stats.xml
@@ -25,32 +25,36 @@
ARA_Incubation_StatCategory
- 999
+ 100
ARA_IncubationCost
-
孵化该武装器官/织物所需的总营养
ARA_Incubation_StatCategory
1
0
- Integer
- true
+ FloatOne
+ {0} 份
+
5010
- false
+
+ true
ARA_IncubationTime
-
孵化该武装器官/织物所需的时间
ARA_Incubation_StatCategory
1
0
- Integer
- true
- 5010
- false
+ FloatOne
+ {0} 天
+
+ 5011
+
+
+ true
\ No newline at end of file
diff --git a/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_Apparel.xml b/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_Apparel.xml
index d597601..9d44699 100644
--- a/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_Apparel.xml
+++ b/1.6/1.6/Defs/Thing_Misc/Apparels/ARA_Apparel.xml
@@ -18,7 +18,7 @@
ARA_Inner
- Torso
+ Torso
OnSkin
@@ -35,9 +35,9 @@
- ARA_Bodystocking_White
-
- 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
+ ARA_Bodystocking_White
+
+ 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
ARA_Cocoon_Cloth
@@ -54,12 +54,19 @@
3000
+ 1
+ 1
+
+
+
- ARA_Bodystocking_Black
-
- 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
+ ARA_Bodystocking_Black
+
+ 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
ARA_Cocoon_Cloth
@@ -76,12 +83,19 @@
3000
+ 1
+ 1
+
+
+
- ARA_Latex_Catsuit
-
- 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
+ ARA_Latex_Catsuit
+
+ 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
ARA_Cocoon_Cloth
@@ -98,12 +112,19 @@
3000
+ 1
+ 1
+
+
+
- ARA_Pantyhose_Black
-
- 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
+ ARA_Pantyhose_Black
+
+ 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
ARA_Cocoon_Cloth
@@ -120,12 +141,19 @@
3000
+ 1
+ 1
+
+
+
- ARA_Pantyhose_White
-
- 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
+ ARA_Pantyhose_White
+
+ 阿拉克涅虫群的装饰性织物,对于虫群来说应该是没啥用的东西。
ARA_Cocoon_Cloth
@@ -142,7 +170,14 @@
3000
+ 1
+ 1
+
+
+
@@ -223,9 +258,9 @@
- ARA_Maid_Uniform
-
- 阿拉克涅督虫们所着织物中的一种,设计上修身轻便,可以使其在阿拉克捏菌毯上获得额外的工作速度,是她们永远服侍虫巢的形象的完美具现化。
+ ARA_Maid_Uniform
+
+ 阿拉克涅督虫们所着织物中的一种,设计上修身轻便,可以使其在阿拉克捏菌毯上获得额外的工作速度,是她们永远服侍虫巢的形象的完美具现化。
ARA_Cocoon_Cloth
@@ -242,10 +277,10 @@
- Torso
- Shoulders
- Arms
- Legs
+ Torso
+ Shoulders
+ Arms
+ Legs
@@ -255,17 +290,24 @@
+
+ 10
+ 2
+
0
ARA_TerrainWorkSpeedHediff
+
- ARA_Bunny_Girl_Uniform
-
- 阿拉克涅督虫们所着织物中的一种,紧紧贴合督虫们的身体曲线,可以使其在阿拉克捏菌毯上获得额外的移动速度。
+ ARA_Bunny_Girl_Uniform
+
+ 阿拉克涅督虫们所着织物中的一种,紧紧贴合督虫们的身体曲线,可以使其在阿拉克捏菌毯上获得额外的移动速度。
ARA_Cocoon_Cloth_1Stage
@@ -282,10 +324,10 @@
- Torso
- Shoulders
- Arms
- Legs
+ Torso
+ Shoulders
+ Arms
+ Legs
@@ -293,6 +335,10 @@
ArachnaeSwarm/Apparel/ARA_Bunny_Girl_Uniform
+
+ 120
+ 2.5
+
0
@@ -300,14 +346,17 @@
ARA_TerrainMoveSpeedHediff
+
- ARA_Nurse_Uniform
-
- 阿拉克涅督虫们所着织物中的一种,似乎是从人类的社会中得到了红十字元素的设计构思——只是虫群自己并不清楚为什么要使用这个标志。织物内部蕴含多根愈合素导管,可以让阿拉克涅虫族从菌毯中抽取营养以治疗其他个体。
+ ARA_Nurse_Uniform
+
+ 阿拉克涅督虫们所着织物中的一种,似乎是从人类的社会中得到了红十字元素的设计构思——只是虫群自己并不清楚为什么要使用这个标志。织物内部蕴含多根愈合素导管,可以让阿拉克涅虫族从菌毯中抽取营养以治疗其他个体。
- ARA_Cocoon_Cloth_2Stage
+ ARA_Cocoon_Cloth_1Stage
ARA_TerrainHeal_Ability
@@ -318,15 +367,19 @@
25
+
+ 350
+ 5
+
ArachnaeSwarm/Apparel/ARA_Nurse_Uniform
- Torso
- Shoulders
- Arms
- Legs
+ Torso
+ Shoulders
+ Arms
+ Legs
@@ -341,12 +394,15 @@
ARA_TerrainHealHediff
+
- ARA_Wedding_Dress
-
- 阿拉克涅督虫们所着织物中的一种,拥有摄人心魄的力量,可以抽取菌毯的力量发动夺取心智的能力,让敌方调转枪口攻击自己人。
+ ARA_Wedding_Dress
+
+ 阿拉克涅督虫们所着织物中的一种,拥有摄人心魄的力量,可以抽取菌毯的力量发动夺取心智的能力,让敌方调转枪口攻击自己人。
ARA_Cocoon_Cloth_2Stage
ARA_TerrainTempt_Ability
@@ -364,10 +420,10 @@
- Torso
- Shoulders
- Arms
- Legs
+ Torso
+ Shoulders
+ Arms
+ Legs
@@ -375,6 +431,10 @@
ArachnaeSwarm/Apparel/ARA_Wedding_Dress
+
+ 350
+ 5
+
0
@@ -382,12 +442,15 @@
ARA_TerrainTemptHediff
+
- ARA_Dragoon_Uniform
-
- 阿拉克涅虫群中的高阶战士所着织物,她们能够发出震耳欲聋的咆哮,并且看上去给人一种意外的庄严感——只不过她们挥着咔咔作响的鳌钳将你的同伴撕裂时,所有美好的幻想都会成为泡影。
+ ARA_Dragoon_Uniform
+
+ 阿拉克涅虫群中的高阶战士所着织物,她们能够发出震耳欲聋的咆哮,并且看上去给人一种意外的庄严感——只不过她们挥着咔咔作响的鳌钳将你的同伴撕裂时,所有美好的幻想都会成为泡影。
ARA_Cocoon_Cloth_2Stage
ARA_TerrorRoar_Ability
@@ -405,10 +468,10 @@
- Torso
- Shoulders
- Arms
- Legs
+ Torso
+ Shoulders
+ Arms
+ Legs
@@ -416,6 +479,10 @@
ArachnaeSwarm/Apparel/ARA_Dragoon_Uniform
+
+ 500
+ 10
+
0
@@ -423,12 +490,15 @@
ARA_TerrainTerrorRoar_Hediff
+
-
- Shield
-
- 275
-
+
+ Shield
+
+ 275
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
index 63f0a46..9ceca4d 100644
--- a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
+++ b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml
@@ -31,6 +31,8 @@
1000
5
+ 25
+ 2.5
@@ -66,6 +68,11 @@
RewardStandardQualitySuper
+
+
+
ARA_MW_Cartilage_Whip
@@ -261,6 +268,8 @@
0.45
0.3
1.25
+ 15
+ 1
@@ -307,6 +316,9 @@
+
ARA_Weapon_Damage_Toxid
diff --git a/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml b/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml
index cb54cf1..0e8828c 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml
@@ -515,6 +515,9 @@
ARA_Bodystocking_White
ARA_Bodystocking_Black
+ ARA_Latex_Catsuit
+ ARA_Pantyhose_Black
+ ARA_Pantyhose_White
ARA_Maid_Uniform
@@ -535,25 +538,6 @@
-
-
- ARA_Bodystocking_White
- 6000
- 1
-
-
- ARA_Bodystocking_Black
- 6000
- 1
-
-
- ARA_Maid_Uniform
- 18000
- 15
- ARA_Technology_4DIL
-
-
-
ArachnaeNode_Race_WeaponSmith
@@ -633,26 +617,6 @@
-
-
- ARA_MW_Bone_Sword
- 60000
- 15
-
-
- ARA_RW_Basic_Fist_Needle_Gun
- 40000
- 10
- ARA_Technology_5PAV
-
-
- ARA_RW_Basic_Acid_Bladder_Gun
- 80000
- 30
- ARA_Technology_7VXI
-
-
-
ArachnaeNode_Race_WeaponSmith
@@ -729,8 +693,8 @@
-
-
+
ArachnaeNode_Race_WeaponSmith
@@ -813,7 +777,7 @@
-
+
ArachnaeNode_Race_WeaponSmith
@@ -916,8 +880,8 @@
-
-
+
ArachnaeNode_Race_WeaponSmith
@@ -999,7 +963,7 @@
-
+
ArachnaeNode_Race_WeaponSmith
@@ -1104,7 +1068,7 @@
-
+
ArachnaeNode_Race_Myrmecocystus
diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo
index cbd6a69..a89630e 100644
Binary files a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo and b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo differ
diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
index 2768895..ee53ed6 100644
--- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
+++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
@@ -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": ""
}
]
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index eb83722..c491768 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -170,9 +170,12 @@
+
+
+
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs
index 1a21032..1dd2180 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.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 processes;
+ // 不再需要手动配置 processes 列表
public List whitelist;
public IntRange spawnCount = new IntRange(1, 1);
public bool destroyOnSpawn;
@@ -21,7 +19,7 @@ namespace ArachnaeSwarm
public float penaltyPerDegreePerTick = 0.00001f;
public List 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 _cachedProcesses;
private CompRefuelableNutrition _fuelComp;
private static readonly Texture2D CancelIcon = ContentFinder.Get("UI/Designators/Cancel");
public bool InProduction => _selectedProcess != null;
public CompProperties_InteractiveProducer Props => (CompProperties_InteractiveProducer)props;
+
+ // 自动生成的 ProcessDef 列表
+ public List Processes
+ {
+ get
+ {
+ if (_cachedProcesses == null)
+ {
+ BuildProcessList();
+ }
+ return _cachedProcesses;
+ }
+ }
+
private CompRefuelableNutrition FuelComp
{
get
@@ -55,12 +68,126 @@ namespace ArachnaeSwarm
{
base.PostSpawnSetup(respawningAfterLoad);
_fuelComp = parent.GetComp();
+ 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();
+
+ // 扫描所有定义了 CompExtraIncubationInfo 的物品
+ foreach (ThingDef thingDef in DefDatabase.AllDefs)
+ {
+ // 检查是否是服装或武器
+ if (thingDef.IsApparel || thingDef.IsWeapon)
+ {
+ var incubationCompProps = thingDef.GetCompProperties();
+ 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.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.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()?.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
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Source/ArachnaeSwarm/Stat/StatWorker_IncubationInfo.cs b/Source/ArachnaeSwarm/Stat/StatWorker_IncubationInfo.cs
new file mode 100644
index 0000000..a7ac19d
--- /dev/null
+++ b/Source/ArachnaeSwarm/Stat/StatWorker_IncubationInfo.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompExtraIncubationInfo.cs b/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompExtraIncubationInfo.cs
new file mode 100644
index 0000000..e89ef79
--- /dev/null
+++ b/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompExtraIncubationInfo.cs
@@ -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;
+ }
+}
diff --git a/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompProperties_ExtraIncubationInfo.cs b/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompProperties_ExtraIncubationInfo.cs
new file mode 100644
index 0000000..9505232
--- /dev/null
+++ b/Source/ArachnaeSwarm/Thing_Comps/ARA_CompExtraIncubationInfo/CompProperties_ExtraIncubationInfo.cs
@@ -0,0 +1,15 @@
+using RimWorld;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ public class CompProperties_ExtraIncubationInfo : CompProperties
+ {
+ // 指定的茧建筑定义
+ public ThingDef cocoonDef;
+ public CompProperties_ExtraIncubationInfo()
+ {
+ compClass = typeof(CompExtraIncubationInfo);
+ }
+ }
+}