diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index 674f98b..92a21e3 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/AbilityDefs/ARA_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
index aeea6af..42bc198 100644
--- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
+++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml
@@ -91,6 +91,36 @@
+
+ ARA_Suicide_Ability
+ 自杀
+ 只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去
+ ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability
+ 1
+ false
+ 9900
+ true
+ false
+ AcidSpray_Warmup
+
+ Verb_CastAbility
+ 24
+ 15
+ AcidSpray_Resolve
+ false
+ false
+
+ true
+
+
+
+
+
+ Brain
+
+
+
+
@@ -532,6 +562,45 @@
-->
+
+ ARA_Baneling_Suicide_Ability
+ 良性自爆
+ 阿拉克涅爆裂种在不使强腐蚀酸活化的情况下发生自爆,这种自爆只会造成轻微的伤害,不会产生酸雾,但是依然留下相同面积的菌毯。
+ ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability
+ 1
+ false
+ 9900
+ true
+ false
+ AcidSpray_Warmup
+
+ 3.9
+
+
+ Verb_CastAbility
+ 24
+ 2
+ AcidSpray_Resolve
+ false
+ false
+
+ true
+
+
+
+
+ 1
+ ARA_AcidBomb
+ 3.9
+ 0
+
+
+
+ Brain
+
+
+
+
ARA_Smokepop_Creeper_Ability_On
@@ -1592,33 +1661,4 @@
-
- ARA_Suicide_Ability
- 自杀
- 只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去
- ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability
- 1
- false
- 9900
- true
- AcidSpray_Warmup
-
- Verb_CastAbility
- 24
- 15
- AcidSpray_Resolve
- false
- false
-
- true
-
-
-
-
-
- Brain
-
-
-
-
\ No newline at end of file
diff --git a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
index 12b2151..50a23dd 100644
--- a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
+++ b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
@@ -63,6 +63,15 @@
ARA_Myrmecocystus_Production_Fuel
+
+
+
+ ArachnaeBase_Race_Scavenger
+ 2
+ 5000
+
+
+
diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
index bd66035..c38db40 100644
--- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
+++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml
@@ -549,6 +549,9 @@
+
+ ARA_Baneling_Suicide_Ability
+
diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
index 4268ff6..906288a 100644
--- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
+++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
@@ -779,18 +779,6 @@
true
ARA_RaceBaseSwarmProduceSwitchHediff
- ARA_InsectJelly
- 1
- 1
- 1
- 9999
-
-
- ArachnaeBase_Race_Scavenger
- 2
- 5000
-
-
CocoonDestroyed
@@ -1446,16 +1434,11 @@
true
ARA_RaceBaseSwarmProduceSwitchHediff
- ARA_InsectJelly
- 1
- 1
- 1
- 9999
ArachnaeBase_Race_Baneling
6
- 800
+ 600
CocoonDestroyed
diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo
index b83d73e..ce9243d 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 f262da8..5c0ff76 100644
--- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
+++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
@@ -3,27 +3,47 @@
"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\\pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
- "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.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\\hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.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\\pawn_comps\\ara_automechcarrier\\compautomechcarrier.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\\hediffs\\ara_productionqueue\\hediffcomp_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_productionqueue\\hediffcomp_productionqueue.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\\pawn_comps\\ara_automechcarrier\\compproperties_automechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproperties_automechcarrier.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\\pawn_comps\\ara_automechcarrier\\compautomechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compautomechcarrier.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\\damage\\damagedefextension_terraincover.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\\pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.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\\eventsystem\\compopencustomui.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:eventsystem\\compopencustomui.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.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\\damage\\damagedefextension_terraincover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:damage\\damagedefextension_terraincover.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\\damage\\damageworker_explosionwithterrain.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\\damage\\damageworker_explosionwithterrain.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:damage\\damageworker_explosionwithterrain.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\\buildings\\building_arachnaegravengine.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\\buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_arachnaegravengine.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\\jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.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\\jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
@@ -77,6 +97,10 @@
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\workgivers\\workgiver_feedwithhoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_feedwithhoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@@ -86,41 +110,116 @@
"DocumentGroups": [
{
"DockedWidth": 200,
- "SelectedChildIndex": 0,
+ "SelectedChildIndex": 1,
"Children": [
- {
- "$type": "Document",
- "DocumentIndex": 0,
- "Title": "CompProducedByMechCarrier.cs",
- "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
- "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
- "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
- "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
- "ViewState": "AgIAABgAAAAAAAAAAAAkwHIAAAAAAAAAAAAAAA==",
- "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
- "WhenOpened": "2026-01-22T03:56:26.73Z",
- "EditorCaption": ""
- },
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "HediffCompProperties_ProductionQueue.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs",
+ "RelativeDocumentMoniker": "Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs",
+ "RelativeToolTip": "Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAMAAAASAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T09:30:17.721Z",
+ "EditorCaption": ""
+ },
{
"$type": "Document",
"DocumentIndex": 1,
+ "Title": "HediffComp_ProductionQueue.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs",
+ "RelativeDocumentMoniker": "Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs",
+ "RelativeToolTip": "Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAOEAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T09:01:06.335Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "CompProperties_AutoMechCarrier.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs",
+ "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs",
+ "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAACUAAAAdAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T09:00:42.285Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "CompOpenCustomUI.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\EventSystem\\CompOpenCustomUI.cs",
+ "RelativeDocumentMoniker": "EventSystem\\CompOpenCustomUI.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\EventSystem\\CompOpenCustomUI.cs",
+ "RelativeToolTip": "EventSystem\\CompOpenCustomUI.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T08:22:11.975Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "CompAbilityEffect_GatherUnit.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs",
+ "RelativeDocumentMoniker": "Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs",
+ "RelativeToolTip": "Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T07:31:57.322Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
"Title": "CompAutoMechCarrier.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
- "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
+ "ViewState": "AgIAAEgCAAAAAAAAAAAewFsCAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-22T03:56:27.144Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 3,
+ "DocumentIndex": 24,
+ "Title": "AutoMechCarrierUtils.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs",
+ "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs",
+ "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABgAAABBAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T07:07:38.083Z"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "CompProducedByMechCarrier.cs",
+ "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
+ "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
+ "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
+ "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs",
+ "ViewState": "AgIAACsAAAAAAAAAAAAUwEAAAAArAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2026-01-22T03:56:26.73Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 8,
"Title": "DamageWorker_ExplosionWithTerrain.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageWorker_ExplosionWithTerrain.cs",
"RelativeDocumentMoniker": "Damage\\DamageWorker_ExplosionWithTerrain.cs",
@@ -128,12 +227,11 @@
"RelativeToolTip": "Damage\\DamageWorker_ExplosionWithTerrain.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAFAAAAAbAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
- "WhenOpened": "2026-01-22T03:13:00.366Z",
- "EditorCaption": ""
+ "WhenOpened": "2026-01-22T03:13:00.366Z"
},
{
"$type": "Document",
- "DocumentIndex": 4,
+ "DocumentIndex": 9,
"Title": "Building_ArachnaeGravEngine.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
"RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs",
@@ -141,12 +239,11 @@
"RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAXAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
- "WhenOpened": "2026-01-22T03:12:54.988Z",
- "EditorCaption": ""
+ "WhenOpened": "2026-01-22T03:12:54.988Z"
},
{
"$type": "Document",
- "DocumentIndex": 2,
+ "DocumentIndex": 7,
"Title": "DamageDefExtension_TerrainCover.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageDefExtension_TerrainCover.cs",
"RelativeDocumentMoniker": "Damage\\DamageDefExtension_TerrainCover.cs",
@@ -154,12 +251,11 @@
"RelativeToolTip": "Damage\\DamageDefExtension_TerrainCover.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAwAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
- "WhenOpened": "2026-01-22T03:12:51.315Z",
- "EditorCaption": ""
+ "WhenOpened": "2026-01-22T03:12:51.315Z"
},
{
"$type": "Document",
- "DocumentIndex": 5,
+ "DocumentIndex": 10,
"Title": "ThinkNode_ConditionalShouldExtract.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs",
@@ -167,12 +263,11 @@
"RelativeToolTip": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs",
"ViewState": "AgIAACMAAAAAAAAAAAAewEwAAAANAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
- "WhenOpened": "2026-01-21T16:03:09.823Z",
- "EditorCaption": ""
+ "WhenOpened": "2026-01-21T16:03:09.823Z"
},
{
"$type": "Document",
- "DocumentIndex": 6,
+ "DocumentIndex": 11,
"Title": "JobGiver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\JobGiver_ExtractHoney.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobGiver_ExtractHoney.cs",
@@ -184,7 +279,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 9,
+ "DocumentIndex": 14,
"Title": "CompHoneyProduction_Animal.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_HoneyProduction_Animal\\CompHoneyProduction_Animal.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_HoneyProduction_Animal\\CompHoneyProduction_Animal.cs",
@@ -196,7 +291,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 10,
+ "DocumentIndex": 15,
"Title": "CompAdvancedTraining.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_TrainingWork\\CompAdvancedTraining.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_TrainingWork\\CompAdvancedTraining.cs",
@@ -208,7 +303,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 8,
+ "DocumentIndex": 13,
"Title": "Need_HoneyProduction.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs",
"RelativeDocumentMoniker": "Needs\\Need_HoneyProduction.cs",
@@ -220,7 +315,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 11,
+ "DocumentIndex": 16,
"Title": "ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs",
@@ -232,7 +327,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 7,
+ "DocumentIndex": 12,
"Title": "JobDriver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\JobDriver_ExtractHoney.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobDriver_ExtractHoney.cs",
@@ -244,7 +339,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 15,
+ "DocumentIndex": 20,
"Title": "JobGiver_Cleaner.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\JobGiver_Cleaner.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\JobGiver_Cleaner.cs",
@@ -256,7 +351,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 14,
+ "DocumentIndex": 19,
"Title": "WorkGiver_ArachnaeClean.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ArachnaeClean.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ArachnaeClean.cs",
@@ -268,7 +363,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 12,
+ "DocumentIndex": 17,
"Title": "JobGiver_Grower.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\JobGiver_Grower.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\JobGiver_Grower.cs",
@@ -280,7 +375,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 13,
+ "DocumentIndex": 18,
"Title": "ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs",
@@ -292,7 +387,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 17,
+ "DocumentIndex": 22,
"Title": "WorkGiver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ExtractHoney.cs",
@@ -304,7 +399,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 18,
+ "DocumentIndex": 23,
"Title": "WorkGiver_FeedWithHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_FeedWithHoney.cs",
@@ -316,7 +411,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 16,
+ "DocumentIndex": 21,
"Title": "ARA_DefOf.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs",
"RelativeDocumentMoniker": "ARA_DefOf.cs",
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index 0e93099..4728668 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -286,6 +286,8 @@
+
+
diff --git a/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs
new file mode 100644
index 0000000..6745385
--- /dev/null
+++ b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs
@@ -0,0 +1,313 @@
+using RimWorld;
+using System.Collections.Generic;
+using Verse;
+using System.Linq;
+
+namespace ArachnaeSwarm
+{
+ ///
+ /// HediffComp_ProductionQueue的属性类
+ ///
+ public class HediffCompProperties_ProductionQueue : HediffCompProperties
+ {
+ // 生产队列定义
+ public List productionQueue = new List();
+
+ // 生产队列是否可以通过代码动态修改
+ public bool allowDynamicModification = true;
+
+ // 是否启用调试日志
+ public bool debugLogging = false;
+
+ // ===== 新增:控制信息显示的字段 =====
+ // 是否在Hediff描述中显示生产能力信息
+ public bool showProductionInfoInHediff = true;
+
+ // 信息标题(可翻译)
+ public string infoTitle = "ProductionQueue_InfoTitle"; // 默认值
+
+ // 信息格式字符串(可翻译)
+ // 可用变量: {UNIT} - 单位名称, {COUNT} - 可生产数量
+ public string infoFormat = "ProductionQueue_InfoFormat"; // 默认值
+
+ // 当生产队列为空时显示的信息(可翻译)
+ public string emptyQueueInfo = "ProductionQueue_EmptyInfo";
+
+ // 信息分隔符(可翻译)
+ public string infoSeparator = "\n";
+
+ // 是否在信息中显示单位成本(如果设置了成本)
+ public bool showCostInInfo = true;
+
+ // 成本信息格式(可翻译)
+ public string costInfoFormat = "ProductionQueue_CostFormat"; // {COST} - 成本数量
+
+ // 是否在信息中显示冷却时间(如果设置了冷却时间)
+ public bool showCooldownInInfo = false;
+
+ // 冷却时间信息格式(可翻译)
+ public string cooldownInfoFormat = "ProductionQueue_CooldownFormat"; // {COOLDOWN} - 冷却时间描述
+
+ // 是否显示条件信息(如果条目有条件限制)
+ public bool showConditionInfo = false;
+
+ // 条件已满足时的信息(可翻译)
+ public string conditionMetInfo = "ProductionQueue_ConditionMet";
+
+ // 条件未满足时的信息(可翻译)
+ public string conditionNotMetInfo = "ProductionQueue_ConditionNotMet";
+
+ // 是否在信息末尾添加额外说明(如果有customInfo字段)
+ public bool showCustomInfo = true;
+
+ // 自定义信息格式(可翻译)
+ public string customInfoFormat = "ProductionQueue_CustomInfoFormat"; // {CUSTOMINFO} - 自定义信息
+
+ public HediffCompProperties_ProductionQueue()
+ {
+ compClass = typeof(HediffComp_ProductionQueue);
+ }
+
+ public override IEnumerable ConfigErrors(HediffDef parentDef)
+ {
+ foreach (var error in base.ConfigErrors(parentDef))
+ {
+ yield return error;
+ }
+
+ // 验证生产队列
+ if (productionQueue == null || productionQueue.Count == 0)
+ {
+ yield return $"{parentDef.defName}: HediffCompProperties_ProductionQueue的生产队列为空";
+ }
+ else
+ {
+ for (int i = 0; i < productionQueue.Count; i++)
+ {
+ var entry = productionQueue[i];
+ if (entry.pawnKind == null)
+ {
+ yield return $"{parentDef.defName}: 生产队列条目 {i} 缺少pawnKind定义";
+ }
+ if (entry.count <= 0)
+ {
+ yield return $"{parentDef.defName}: 生产队列条目 {entry.pawnKind?.defName ?? "未知"} 的数量必须大于0";
+ }
+ }
+ }
+ }
+
+ ///
+ /// 获取生产能力信息的字符串
+ ///
+ public string GetProductionInfoString(Pawn pawn = null)
+ {
+ // 如果不显示信息,返回空字符串
+ if (!showProductionInfoInHediff || productionQueue == null || productionQueue.Count == 0)
+ {
+ return "";
+ }
+
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+
+ // 添加标题
+ if (!string.IsNullOrEmpty(infoTitle))
+ {
+ sb.AppendLine(infoTitle.Translate());
+ }
+
+ bool hasAnyEntry = false;
+
+ foreach (var entry in productionQueue)
+ {
+ if (entry.pawnKind == null)
+ continue;
+
+ // 检查条件是否满足
+ bool conditionsMet = true;
+ string conditionReason = "";
+
+ if (pawn != null && !entry.conditions.NullOrEmpty())
+ {
+ // 检查所有条件
+ foreach (var condition in entry.conditions)
+ {
+ string reason;
+ if (!condition.IsMet(out reason))
+ {
+ conditionsMet = false;
+ conditionReason = reason;
+ break;
+ }
+ }
+ }
+
+ // 构建条目信息
+ string entryInfo = BuildEntryInfo(entry, pawn, conditionsMet, conditionReason);
+ if (!string.IsNullOrEmpty(entryInfo))
+ {
+ sb.Append(entryInfo);
+ sb.Append(infoSeparator);
+ hasAnyEntry = true;
+ }
+ }
+
+ // 如果没有有效的条目
+ if (!hasAnyEntry)
+ {
+ return emptyQueueInfo.Translate();
+ }
+
+ // 移除最后一个分隔符
+ if (sb.Length > 0 && sb.ToString().EndsWith(infoSeparator))
+ {
+ sb.Length -= infoSeparator.Length;
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// 构建单个条目的信息
+ ///
+ private string BuildEntryInfo(PawnProductionEntry entry, Pawn pawn, bool conditionsMet, string conditionReason)
+ {
+ // 如果条件不满足且设置了隐藏不可用的条目,返回空字符串
+ if (!conditionsMet && !showConditionInfo)
+ {
+ return "";
+ }
+
+ System.Text.StringBuilder entrySb = new System.Text.StringBuilder();
+
+ // 基本格式:单位名称 x 数量
+ string baseInfo = infoFormat.Translate(
+ "UNIT".Translate(entry.pawnKind.LabelCap),
+ "COUNT".Translate(entry.count)
+ );
+
+ entrySb.Append(baseInfo);
+
+ // 添加成本信息
+ if (showCostInInfo && entry.cost.HasValue && entry.cost.Value > 0)
+ {
+ string costInfo = costInfoFormat.Translate("COST".Translate(entry.cost.Value));
+ entrySb.Append(" ").Append(costInfo);
+ }
+
+ // 添加冷却时间信息
+ if (showCooldownInInfo && entry.cooldownTicks.HasValue && entry.cooldownTicks.Value > 0)
+ {
+ string cooldownDesc = entry.cooldownTicks.Value.ToStringTicksToPeriod();
+ string cooldownInfo = cooldownInfoFormat.Translate("COOLDOWN".Translate(cooldownDesc));
+ entrySb.Append(" ").Append(cooldownInfo);
+ }
+
+ // 添加条件状态信息
+ if (showConditionInfo)
+ {
+ if (conditionsMet)
+ {
+ string metInfo = conditionMetInfo.Translate();
+ entrySb.Append(" ").Append(metInfo);
+ }
+ else
+ {
+ string notMetInfo = conditionNotMetInfo.Translate("REASON".Translate(conditionReason));
+ entrySb.Append(" ").Append(notMetInfo);
+ }
+ }
+
+ // 添加自定义信息
+ if (showCustomInfo && !string.IsNullOrEmpty(entry.customInfo))
+ {
+ string customInfo = customInfoFormat.Translate("CUSTOMINFO".Translate(entry.customInfo));
+ entrySb.Append(" ").Append(customInfo);
+ }
+
+ return entrySb.ToString();
+ }
+
+ ///
+ /// 合并多个生产队列
+ ///
+ public static List MergeProductionQueues(List> queues)
+ {
+ var mergedQueue = new List();
+ var entryMap = new Dictionary();
+
+ foreach (var queue in queues)
+ {
+ if (queue == null)
+ continue;
+
+ foreach (var entry in queue)
+ {
+ if (entry.pawnKind == null)
+ continue;
+
+ if (entryMap.TryGetValue(entry.pawnKind, out var existingEntry))
+ {
+ // 合并相同PawnKindDef的条目
+ existingEntry.count += entry.count;
+
+ // 使用较小的成本(如果有指定)
+ if (entry.cost.HasValue && (!existingEntry.cost.HasValue || entry.cost.Value < existingEntry.cost.Value))
+ {
+ existingEntry.cost = entry.cost;
+ }
+
+ // 使用较短的冷却时间(如果有指定)
+ if (entry.cooldownTicks.HasValue && (!existingEntry.cooldownTicks.HasValue || entry.cooldownTicks.Value < existingEntry.cooldownTicks.Value))
+ {
+ existingEntry.cooldownTicks = entry.cooldownTicks;
+ }
+ }
+ else
+ {
+ // 创建新条目
+ var newEntry = new PawnProductionEntry
+ {
+ pawnKind = entry.pawnKind,
+ count = entry.count,
+ cost = entry.cost,
+ cooldownTicks = entry.cooldownTicks,
+ conditions = entry.conditions?.ToList(), // 复制条件列表
+ customInfo = entry.customInfo
+ };
+ entryMap[entry.pawnKind] = newEntry;
+ mergedQueue.Add(newEntry);
+ }
+ }
+ }
+
+ return mergedQueue;
+ }
+
+ ///
+ /// 获取配置统计信息
+ ///
+ public string GetConfigInfo()
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+ sb.AppendLine("=== HediffCompProperties_ProductionQueue 配置 ===");
+ sb.AppendLine($"显示生产信息: {showProductionInfoInHediff}");
+ sb.AppendLine($"显示成本信息: {showCostInInfo}");
+ sb.AppendLine($"显示冷却信息: {showCooldownInInfo}");
+ sb.AppendLine($"显示条件信息: {showConditionInfo}");
+ sb.AppendLine($"显示自定义信息: {showCustomInfo}");
+ sb.AppendLine($"允许动态修改: {allowDynamicModification}");
+ sb.AppendLine($"生产队列条目数: {productionQueue?.Count ?? 0}");
+
+ if (productionQueue != null && productionQueue.Count > 0)
+ {
+ foreach (var entry in productionQueue)
+ {
+ sb.AppendLine($" • {entry.pawnKind?.defName ?? "NULL"}: {entry.count} 个");
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs
new file mode 100644
index 0000000..113dedf
--- /dev/null
+++ b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs
@@ -0,0 +1,273 @@
+using RimWorld;
+using System.Collections.Generic;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ ///
+ /// 定义生产队列的HediffComp
+ /// 允许通过Hediff为CompAutoMechCarrier提供生产队列定义
+ ///
+ public class HediffComp_ProductionQueue : HediffComp
+ {
+ public HediffCompProperties_ProductionQueue Props =>
+ (HediffCompProperties_ProductionQueue)props;
+
+ ///
+ /// 获取Hediff的描述信息(显示在Hediff详情中)
+ ///
+ public override string CompTipStringExtra
+ {
+ get
+ {
+ // 获取生产能力信息
+ string productionInfo = GetProductionInfoString();
+
+ if (!string.IsNullOrEmpty(productionInfo))
+ {
+ return productionInfo;
+ }
+
+ return base.CompTipStringExtra;
+ }
+ }
+
+ ///
+ /// 获取Hediff的完整描述信息
+ ///
+ public override string CompDescriptionExtra
+ {
+ get
+ {
+ // 也可以在这里添加生产能力信息
+ string productionInfo = GetProductionInfoString();
+
+ if (!string.IsNullOrEmpty(productionInfo))
+ {
+ // 将生产能力信息添加到描述中
+ string baseDescription = base.CompDescriptionExtra ?? "";
+
+ if (!string.IsNullOrEmpty(baseDescription))
+ {
+ return baseDescription + "\n\n" + productionInfo;
+ }
+ else
+ {
+ return productionInfo;
+ }
+ }
+
+ return base.CompDescriptionExtra;
+ }
+ }
+
+ ///
+ /// 获取生产能力信息字符串
+ ///
+ public string GetProductionInfoString()
+ {
+ if (Props == null)
+ return "";
+
+ // 获取当前Pawn(如果适用)
+ Pawn pawn = null;
+ if (parent != null && parent.pawn != null)
+ {
+ pawn = parent.pawn;
+ }
+
+ return Props.GetProductionInfoString(pawn);
+ }
+
+ ///
+ /// 获取生产队列定义
+ ///
+ public List GetProductionQueue()
+ {
+ return Props?.productionQueue ?? new List();
+ }
+
+ ///
+ /// 获取可用的生产队列
+ /// 可以根据条件进行过滤
+ ///
+ public List GetAvailableProductionQueue(Pawn pawn)
+ {
+ var queue = GetProductionQueue();
+ var availableQueue = new List();
+
+ foreach (var entry in queue)
+ {
+ // 检查前置条件
+ if (CheckEntryConditions(entry, pawn))
+ {
+ availableQueue.Add(entry);
+ }
+ }
+
+ return availableQueue;
+ }
+
+ ///
+ /// 检查条目条件是否满足
+ ///
+ private bool CheckEntryConditions(PawnProductionEntry entry, Pawn pawn)
+ {
+ // 检查自定义条件
+ if (!entry.conditions.NullOrEmpty())
+ {
+ foreach (var condition in entry.conditions)
+ {
+ string reason;
+ if (!condition.IsMet(out reason))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// 根据PawnKindDef查找生产队列条目
+ ///
+ public PawnProductionEntry GetEntryForPawnKind(PawnKindDef pawnKindDef)
+ {
+ var queue = GetProductionQueue();
+ return queue?.Find(entry => entry.pawnKind == pawnKindDef);
+ }
+
+ ///
+ /// 添加新的生产队列条目
+ ///
+ public void AddProductionEntry(PawnProductionEntry entry)
+ {
+ var queue = GetProductionQueue();
+ if (queue == null)
+ return;
+
+ queue.Add(entry);
+ }
+
+ ///
+ /// 移除生产队列条目
+ ///
+ public bool RemoveProductionEntry(PawnKindDef pawnKindDef)
+ {
+ var queue = GetProductionQueue();
+ if (queue == null)
+ return false;
+
+ return queue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0;
+ }
+
+ ///
+ /// 更新生产队列条目
+ ///
+ public bool UpdateProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry)
+ {
+ var queue = GetProductionQueue();
+ if (queue == null)
+ return false;
+
+ for (int i = 0; i < queue.Count; i++)
+ {
+ if (queue[i].pawnKind == pawnKindDef)
+ {
+ queue[i] = newEntry;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 获取调试信息
+ ///
+ public string GetDebugInfo()
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+ sb.AppendLine($"=== HediffComp_ProductionQueue 调试信息 ===");
+ sb.AppendLine($"Hediff: {parent.def.defName}");
+ sb.AppendLine($"显示生产信息: {Props.showProductionInfoInHediff}");
+ sb.AppendLine($"生产队列条目数: {GetProductionQueue()?.Count ?? 0}");
+
+ // 显示生产信息字符串
+ string productionInfo = GetProductionInfoString();
+ if (!string.IsNullOrEmpty(productionInfo))
+ {
+ sb.AppendLine($"生产信息:\n{productionInfo}");
+ }
+
+ var queue = GetProductionQueue();
+ if (queue != null && queue.Count > 0)
+ {
+ sb.AppendLine($"详细条目:");
+ foreach (var entry in queue)
+ {
+ sb.AppendLine($" • {entry.pawnKind?.label ?? "NULL"}: {entry.count} 个");
+ if (entry.cost.HasValue)
+ sb.AppendLine($" 成本: {entry.cost.Value}");
+ if (entry.cooldownTicks.HasValue)
+ sb.AppendLine($" 冷却时间: {entry.cooldownTicks.Value.ToStringTicksToPeriod()}");
+ if (!string.IsNullOrEmpty(entry.customInfo))
+ sb.AppendLine($" 自定义信息: {entry.customInfo}");
+ }
+ }
+ else
+ {
+ sb.AppendLine(" 生产队列为空");
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// 获取统计信息
+ ///
+ public string GetStatistics()
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+
+ var queue = GetProductionQueue();
+ if (queue != null && queue.Count > 0)
+ {
+ sb.AppendLine($"此状态提供以下生产能力:");
+
+ foreach (var entry in queue)
+ {
+ if (entry.pawnKind == null)
+ continue;
+
+ string entryInfo = $" • {entry.pawnKind.label}: 最多 {entry.count} 个";
+
+ if (entry.cost.HasValue)
+ {
+ entryInfo += $", 每个消耗 {entry.cost.Value} 资源";
+ }
+
+ if (entry.cooldownTicks.HasValue)
+ {
+ string cooldownDesc = entry.cooldownTicks.Value.ToStringTicksToPeriod();
+ entryInfo += $", 冷却时间 {cooldownDesc}";
+ }
+
+ if (!string.IsNullOrEmpty(entry.customInfo))
+ {
+ entryInfo += $" ({entry.customInfo})";
+ }
+
+ sb.AppendLine(entryInfo);
+ }
+ }
+ else
+ {
+ sb.AppendLine("此状态不提供生产能力");
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs
index d550143..8e13249 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs
@@ -53,9 +53,234 @@ namespace ArachnaeSwarm
}
#endregion
+ #region Custom Follow Position
+ private IntVec3? customFollowPosition = null;
+ private Map customFollowPositionMap = null;
+ private object customPositionLock = new object();
+
+ ///
+ /// 获取或设置自定义跟随位置
+ /// 如果此位置不为空,生成的单位将以此位置而非父单位位置为跟随中心点
+ ///
+ public IntVec3? CustomFollowPosition
+ {
+ get
+ {
+ lock (customPositionLock)
+ {
+ return customFollowPosition;
+ }
+ }
+ set
+ {
+ lock (customPositionLock)
+ {
+ customFollowPosition = value;
+ if (value.HasValue && parent != null && parent.Spawned)
+ {
+ customFollowPositionMap = parent.Map;
+ }
+ else
+ {
+ customFollowPositionMap = null;
+ }
+
+ // 通知所有已生成的单位更新他们的跟随位置
+ NotifyFollowPositionChanged();
+ }
+ }
+ }
+
+ ///
+ /// 检查自定义位置是否有效(位置不为空且在正确的地图上)
+ ///
+ public bool HasValidCustomFollowPosition
+ {
+ get
+ {
+ if (!customFollowPosition.HasValue || customFollowPositionMap == null)
+ return false;
+
+ // 如果父单位已销毁或不在同一地图,自定义位置也无效
+ if (parent == null || parent.Destroyed || !parent.Spawned)
+ return false;
+
+ return customFollowPositionMap == parent.Map;
+ }
+ }
+
+ ///
+ /// 获取有效的跟随位置
+ /// 优先返回自定义位置,如果无效则返回父单位位置
+ ///
+ public IntVec3 GetEffectiveFollowPosition()
+ {
+ if (HasValidCustomFollowPosition)
+ {
+ return customFollowPosition.Value;
+ }
+
+ // 返回父单位位置
+ if (parent != null && parent.Spawned)
+ {
+ if (parent is Building building)
+ {
+ return building.InteractionCell;
+ }
+ return parent.Position;
+ }
+
+ return IntVec3.Invalid;
+ }
+
+ ///
+ /// 获取跟随位置的地图
+ ///
+ public Map GetFollowPositionMap()
+ {
+ if (HasValidCustomFollowPosition)
+ {
+ return customFollowPositionMap;
+ }
+
+ if (parent != null && parent.Spawned)
+ {
+ return parent.Map;
+ }
+
+ return null;
+ }
+
+ ///
+ /// 通知所有已生成的单位跟随位置已改变
+ ///
+ private void NotifyFollowPositionChanged()
+ {
+ if (SpawnedPawns == null || !SpawnedPawns.Any())
+ return;
+
+ // 清理无效的Pawn引用
+ SpawnedPawns.RemoveAll(p => p == null || p.Destroyed);
+
+ // 通知每个Pawn的CompProducedByMechCarrier
+ foreach (Pawn spawnedPawn in SpawnedPawns)
+ {
+ if (spawnedPawn == null || spawnedPawn.Destroyed || !spawnedPawn.Spawned)
+ continue;
+
+ var producedComp = spawnedPawn.TryGetComp();
+ if (producedComp != null)
+ {
+ producedComp.TryUpdateProducerStatus();
+ }
+ }
+ }
+
+ ///
+ /// 清空自定义跟随位置
+ ///
+ public void ClearCustomFollowPosition()
+ {
+ CustomFollowPosition = null;
+ }
+
+ ///
+ /// 设置自定义跟随位置
+ ///
+ /// 新的跟随位置
+ /// 是否设置成功
+ public bool SetCustomFollowPosition(IntVec3 position)
+ {
+ if (parent == null || !parent.Spawned)
+ return false;
+
+ if (!position.InBounds(parent.Map))
+ return false;
+
+ CustomFollowPosition = position;
+ return true;
+ }
+
+ ///
+ /// 临时设置自定义跟随位置(在一段时间后自动清除)
+ ///
+ /// 临时位置
+ /// 持续时间(tick)
+ public void SetTemporaryFollowPosition(IntVec3 position, int durationTicks)
+ {
+ if (!SetCustomFollowPosition(position))
+ return;
+
+ // 启动定时器清除临时位置
+ StartPositionClearTimer(durationTicks);
+ }
+
+ private void StartPositionClearTimer(int durationTicks)
+ {
+ // 这里可以使用TickManager来安排定时清除
+ // 简单实现:记录时间并在Tick中检查
+ temporaryPositionExpiryTick = Find.TickManager.TicksGame + durationTicks;
+ }
+ #endregion
+
+ #region Temporary Position Timer
+ private int temporaryPositionExpiryTick = -1;
+
+ private void CheckTemporaryPositionExpiry()
+ {
+ if (temporaryPositionExpiryTick > 0 &&
+ Find.TickManager.TicksGame >= temporaryPositionExpiryTick &&
+ customFollowPosition.HasValue)
+ {
+ ClearCustomFollowPosition();
+ temporaryPositionExpiryTick = -1;
+ }
+ }
+ #endregion
+
public CompProperties_AutoMechCarrier AutoProps => (CompProperties_AutoMechCarrier)props;
- private int TotalPawnCapacity => AutoProps.productionQueue.Sum(e => e.count);
+ // 缓存的合并生产队列
+ private List cachedProductionQueue = null;
+ private int lastProductionQueueUpdateTick = -1;
+ private const int PRODUCTION_QUEUE_CACHE_TICKS = 30; // 30 tick缓存
+
+ ///
+ /// 获取合并后的生产队列
+ /// 包括从HediffComp扫描的和动态添加的
+ ///
+ public List GetProductionQueue()
+ {
+ // 使用缓存提高性能
+ if (cachedProductionQueue != null &&
+ Find.TickManager.TicksGame - lastProductionQueueUpdateTick < PRODUCTION_QUEUE_CACHE_TICKS)
+ {
+ return cachedProductionQueue;
+ }
+
+ // 获取Pawn引用
+ var pawn = parent as Pawn;
+
+ // 从AutoProps获取合并后的生产队列
+ cachedProductionQueue = AutoProps.GetMergedProductionQueue(pawn);
+ lastProductionQueueUpdateTick = Find.TickManager.TicksGame;
+
+ return cachedProductionQueue;
+ }
+
+ ///
+ /// 强制刷新生产队列缓存
+ ///
+ public void RefreshProductionQueue()
+ {
+ cachedProductionQueue = null;
+ lastProductionQueueUpdateTick = -1;
+ }
+
+ ///
+ /// 获取总容量
+ ///
+ private int TotalPawnCapacity => GetProductionQueue().Sum(e => e.count);
private int LiveSpawnedPawnsCount(PawnKindDef kind)
{
@@ -70,7 +295,11 @@ namespace ArachnaeSwarm
if (CooldownTicksRemaining > 0)
return "CooldownTime".Translate() + " " + CooldownTicksRemaining.ToStringSecondsFromTicks();
- PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
+ var productionQueue = GetProductionQueue();
+ PawnProductionEntry entry = productionQueue.FirstOrDefault(e => e.pawnKind == kind);
+ if (entry == null)
+ return "生产队列中未找到指定的PawnKindDef";
+
int cost = entry.cost ?? Props.costPerPawn;
if (!AutoProps.freeProduction && InnerContainer.TotalStackCountOfDef(Props.fixedIngredient) < cost)
@@ -100,7 +329,22 @@ namespace ArachnaeSwarm
// 初始化生产者信息
producedComp.Initialize(parent, this);
- GenSpawn.Spawn(pawn, parent.Position, parent.Map);
+ // 生成位置:使用自定义跟随位置(如果有效),否则使用父单位位置
+ IntVec3 spawnPosition;
+ Map spawnMap;
+
+ if (HasValidCustomFollowPosition)
+ {
+ spawnPosition = customFollowPosition.Value;
+ spawnMap = customFollowPositionMap;
+ }
+ else
+ {
+ spawnPosition = parent.Position;
+ spawnMap = parent.Map;
+ }
+
+ GenSpawn.Spawn(pawn, spawnPosition, spawnMap);
SpawnedPawns.Add(pawn);
if (parent is Pawn p && p.GetLord() != null)
@@ -108,7 +352,8 @@ namespace ArachnaeSwarm
if (!AutoProps.freeProduction)
{
- PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
+ var productionQueue = GetProductionQueue();
+ PawnProductionEntry entry = productionQueue.First(e => e.pawnKind == kind);
int costLeft = entry.cost ?? Props.costPerPawn;
List things = new List(InnerContainer);
@@ -121,7 +366,7 @@ namespace ArachnaeSwarm
}
}
- PawnProductionEntry spawnEntry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
+ var spawnEntry = GetProductionQueue().First(e => e.pawnKind == kind);
CooldownTicksRemaining = spawnEntry.cooldownTicks ?? Props.cooldownTicks;
if (Props.spawnedMechEffecter != null)
@@ -140,6 +385,9 @@ namespace ArachnaeSwarm
public override void CompTick()
{
base.CompTick();
+
+ // 检查临时位置是否过期
+ CheckTemporaryPositionExpiry();
if (parent.IsHashIntervalTick(60)) // 每秒检查一次
{
@@ -149,9 +397,16 @@ namespace ArachnaeSwarm
return; // 有Hediff,停止生产
}
+ // 获取当前生产队列
+ var productionQueue = GetProductionQueue();
+ if (productionQueue == null || productionQueue.Count == 0)
+ {
+ return; // 生产队列为空,不进行生产
+ }
+
// 1. 先检查是否满员
bool isFull = true;
- foreach (var entry in AutoProps.productionQueue)
+ foreach (var entry in productionQueue)
{
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{
@@ -169,7 +424,7 @@ namespace ArachnaeSwarm
if (CooldownTicksRemaining > 0) return;
// 3. 寻找空位并生产
- foreach (var entry in AutoProps.productionQueue)
+ foreach (var entry in productionQueue)
{
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{
@@ -183,6 +438,89 @@ namespace ArachnaeSwarm
}
}
+ ///
+ /// 添加动态生产队列条目
+ ///
+ public bool AddProductionEntry(PawnProductionEntry entry)
+ {
+ if (entry == null || entry.pawnKind == null)
+ return false;
+
+ AutoProps.AddDynamicProductionEntry(entry);
+ RefreshProductionQueue();
+
+ if (AutoProps.debugLogging)
+ Log.Message($"[CompAutoMechCarrier] 添加生产队列条目: {entry.pawnKind.label} x{entry.count}");
+
+ return true;
+ }
+
+ ///
+ /// 移除动态生产队列条目
+ ///
+ public bool RemoveProductionEntry(PawnKindDef pawnKindDef)
+ {
+ if (pawnKindDef == null)
+ return false;
+
+ bool result = AutoProps.RemoveDynamicProductionEntry(pawnKindDef);
+ if (result)
+ {
+ RefreshProductionQueue();
+
+ if (AutoProps.debugLogging)
+ Log.Message($"[CompAutoMechCarrier] 移除生产队列条目: {pawnKindDef.label}");
+ }
+
+ return result;
+ }
+
+ ///
+ /// 更新动态生产队列条目
+ ///
+ public bool UpdateProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry)
+ {
+ if (pawnKindDef == null || newEntry == null)
+ return false;
+
+ bool result = AutoProps.UpdateDynamicProductionEntry(pawnKindDef, newEntry);
+ if (result)
+ {
+ RefreshProductionQueue();
+
+ if (AutoProps.debugLogging)
+ Log.Message($"[CompAutoMechCarrier] 更新生产队列条目: {pawnKindDef.label}");
+ }
+
+ return result;
+ }
+
+ ///
+ /// 清除所有动态生产队列
+ ///
+ public void ClearDynamicProductionQueue()
+ {
+ AutoProps.ClearDynamicProductionQueue();
+ RefreshProductionQueue();
+
+ if (AutoProps.debugLogging)
+ Log.Message("[CompAutoMechCarrier] 清除所有动态生产队列");
+ }
+
+ ///
+ /// 扫描Hediff并更新生产队列
+ ///
+ public void ScanAndUpdateProductionQueue()
+ {
+ RefreshProductionQueue();
+
+ if (AutoProps.debugLogging)
+ {
+ var productionQueue = GetProductionQueue();
+ Log.Message($"[CompAutoMechCarrier] 扫描Hediff完成,生产队列条目数: {productionQueue.Count}");
+ }
+ }
+
public override IEnumerable CompGetGizmosExtra()
{
// 移除所有Gizmo逻辑
@@ -194,9 +532,16 @@ namespace ArachnaeSwarm
SpawnedPawns.RemoveAll(p => p == null || p.Destroyed);
string text = "Pawns: " + SpawnedPawns.Count + " / " + TotalPawnCapacity;
- foreach (var entry in AutoProps.productionQueue)
+ var productionQueue = GetProductionQueue();
+ foreach (var entry in productionQueue)
{
text += $"\n- {entry.pawnKind.LabelCap}: {LiveSpawnedPawnsCount(entry.pawnKind)} / {entry.count}";
+
+ // 显示自定义信息
+ if (entry.customInfo != null)
+ {
+ text += $" ({entry.customInfo})";
+ }
}
if (CooldownTicksRemaining > 0)
@@ -208,7 +553,93 @@ namespace ArachnaeSwarm
{
text += "\n" + base.CompInspectStringExtra();
}
+
+ // 显示自定义跟随位置信息
+ if (HasValidCustomFollowPosition)
+ {
+ text += $"\nCustom Follow Position: {customFollowPosition.Value}";
+ if (temporaryPositionExpiryTick > 0)
+ {
+ int remainingTicks = temporaryPositionExpiryTick - Find.TickManager.TicksGame;
+ if (remainingTicks > 0)
+ {
+ text += $"\nTemporary Position (expires in: {remainingTicks.ToStringSecondsFromTicks()})";
+ }
+ }
+ }
+
return text;
}
+
+ ///
+ /// 获取调试信息
+ ///
+ public string GetDebugInfo()
+ {
+ var pawn = parent as Pawn;
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+ sb.AppendLine("=== CompAutoMechCarrier 调试信息 ===");
+
+ // CompAutoMechCarrier基本信息
+ sb.AppendLine($"父单位: {parent?.LabelCap ?? "NULL"}");
+ sb.AppendLine($"自定义跟随位置: {CustomFollowPosition}");
+ sb.AppendLine($"有效跟随位置: {GetEffectiveFollowPosition()}");
+ sb.AppendLine($"临时位置过期tick: {temporaryPositionExpiryTick}");
+
+ // 已生成的Pawn
+ sb.AppendLine($"已生成Pawn数: {SpawnedPawns?.Count ?? 0}");
+ if (SpawnedPawns != null && SpawnedPawns.Count > 0)
+ {
+ foreach (var spawnedPawn in SpawnedPawns)
+ {
+ if (spawnedPawn != null && !spawnedPawn.Destroyed)
+ {
+ sb.AppendLine($" • {spawnedPawn.LabelCap} ({spawnedPawn.kindDef?.label ?? "未知"})");
+ }
+ }
+ }
+
+ // 冷却时间
+ sb.AppendLine($"冷却时间剩余: {CooldownTicksRemaining}");
+
+ return sb.ToString();
+ }
+
+ public override void PostExposeData()
+ {
+ base.PostExposeData();
+
+ // 保存自定义跟随位置
+ Scribe_Values.Look(ref customFollowPosition, "customFollowPosition");
+ Scribe_Values.Look(ref temporaryPositionExpiryTick, "temporaryPositionExpiryTick", -1);
+
+ // 注意:Map不能直接序列化,需要在PostLoadInit中重新获取
+ if (Scribe.mode == LoadSaveMode.LoadingVars)
+ {
+ customFollowPositionMap = parent?.Map;
+ }
+ }
+
+ public override void PostSpawnSetup(bool respawningAfterLoad)
+ {
+ base.PostSpawnSetup(respawningAfterLoad);
+
+ // 确保地图引用正确
+ if (respawningAfterLoad)
+ {
+ customFollowPositionMap = parent?.Map;
+
+ // 如果自定义位置无效,清除它
+ if (customFollowPosition.HasValue &&
+ (customFollowPositionMap == null ||
+ !customFollowPosition.Value.InBounds(customFollowPositionMap)))
+ {
+ ClearCustomFollowPosition();
+ }
+ }
+
+ // 初始化生产队列缓存
+ RefreshProductionQueue();
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs
index a1fe812..a64ff52 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs
@@ -12,8 +12,14 @@ namespace ArachnaeSwarm
// 如果单位拥有这个Hediff,则停止生产
public HediffDef disableHediff;
- // 定义生产队列
- public List productionQueue = new List();
+ // 从HediffComp获取的生产队列(通过代码动态设置)
+ public List DynamicProductionQueue = new List();
+
+ // 是否启用调试日志
+ public bool debugLogging = false;
+
+ // 扫描Hediff并获取生产队列
+ public bool ScanHediffsForProductionQueue = true;
public CompProperties_AutoMechCarrier()
{
@@ -28,27 +34,132 @@ namespace ArachnaeSwarm
yield return error;
}
- if (productionQueue.NullOrEmpty())
- {
- yield return "CompProperties_AutoMechCarrier must have at least one entry in productionQueue.";
- }
+ // 不再要求必须有生产队列,因为可以通过HediffComp动态添加
+ // 生产队列可以在运行时动态设置
}
public override void ResolveReferences(ThingDef parentDef)
{
base.ResolveReferences(parentDef);
+
// Prevent division by zero if costPerPawn is not set, which the base game AI might try to access.
if (costPerPawn <= 0)
{
costPerPawn = 1;
}
- // 如果spawnPawnKind为空(因为我们用了新的队列系统),
- // 就从队列里取第一个作为“假”值,以防止基类方法在生成Gizmo标签时出错。
- if (spawnPawnKind == null && !productionQueue.NullOrEmpty())
+ // 如果spawnPawnKind为空,我们不再设置默认值
+ // 因为现在生产队列是动态的
+ }
+
+ ///
+ /// 获取合并后的生产队列
+ /// 包括从HediffComp扫描的和动态添加的
+ ///
+ public List GetMergedProductionQueue(Pawn pawn)
+ {
+ var queuesToMerge = new List>();
+
+ // 1. 添加动态生产队列
+ if (DynamicProductionQueue != null && DynamicProductionQueue.Count > 0)
{
- spawnPawnKind = productionQueue[0].pawnKind;
+ queuesToMerge.Add(DynamicProductionQueue);
}
+
+ // 2. 扫描HediffComp获取生产队列
+ if (ScanHediffsForProductionQueue && pawn != null && pawn.health != null)
+ {
+ var hediffQueues = GetProductionQueueFromHediffs(pawn);
+ if (hediffQueues != null && hediffQueues.Count > 0)
+ {
+ queuesToMerge.Add(hediffQueues);
+ }
+ }
+
+ // 合并所有队列
+ return HediffCompProperties_ProductionQueue.MergeProductionQueues(queuesToMerge);
+ }
+
+ ///
+ /// 从HediffComp获取生产队列
+ ///
+ private List GetProductionQueueFromHediffs(Pawn pawn)
+ {
+ var productionQueue = new List();
+
+ if (pawn == null || pawn.health == null || pawn.health.hediffSet == null)
+ return productionQueue;
+
+ // 扫描所有Hediff,查找具有HediffComp_ProductionQueue的
+ foreach (var hediff in pawn.health.hediffSet.hediffs)
+ {
+ if (hediff == null)
+ continue;
+
+ // 检查Hediff是否包含HediffComp_ProductionQueue
+ var productionComp = hediff.TryGetComp();
+ if (productionComp != null)
+ {
+ var queueFromHediff = productionComp.GetAvailableProductionQueue(pawn);
+ if (queueFromHediff != null && queueFromHediff.Count > 0)
+ {
+ productionQueue.AddRange(queueFromHediff);
+ }
+ }
+ }
+
+ return productionQueue;
+ }
+
+ ///
+ /// 添加动态生产队列条目
+ ///
+ public void AddDynamicProductionEntry(PawnProductionEntry entry)
+ {
+ if (DynamicProductionQueue == null)
+ DynamicProductionQueue = new List();
+
+ DynamicProductionQueue.Add(entry);
+ }
+
+ ///
+ /// 移除动态生产队列条目
+ ///
+ public bool RemoveDynamicProductionEntry(PawnKindDef pawnKindDef)
+ {
+ if (DynamicProductionQueue == null)
+ return false;
+
+ return DynamicProductionQueue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0;
+ }
+
+ ///
+ /// 更新动态生产队列条目
+ ///
+ public bool UpdateDynamicProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry)
+ {
+ if (DynamicProductionQueue == null)
+ return false;
+
+ for (int i = 0; i < DynamicProductionQueue.Count; i++)
+ {
+ if (DynamicProductionQueue[i].pawnKind == pawnKindDef)
+ {
+ DynamicProductionQueue[i] = newEntry;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 清除所有动态生产队列
+ ///
+ public void ClearDynamicProductionQueue()
+ {
+ if (DynamicProductionQueue != null)
+ DynamicProductionQueue.Clear();
}
}
-}
\ No newline at end of file
+}
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs
index b8e8c9e..6d709c0 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs
@@ -1,4 +1,7 @@
+using RimWorld;
+using System.Collections.Generic;
using Verse;
+using System.Linq;
namespace ArachnaeSwarm
{
@@ -19,5 +22,98 @@ namespace ArachnaeSwarm
// Optional: specific cost for this entry. If not set, the parent comp's costPerPawn is used.
public int? cost;
+
+ // Optional: custom information for display
+ public string customInfo;
+
+ // Optional: conditions that must be met for this entry to be available
+ public List conditions;
+
+ // Optional: priority (lower number = higher priority)
+ public int priority = 0;
+
+ // Optional: weight for random selection (if multiple entries can be produced simultaneously)
+ public float weight = 1.0f;
+
+ // Optional: whether this entry is enabled (can be toggled)
+ public bool enabled = true;
+
+ // Optional: tech requirements
+ public ResearchProjectDef requiredResearch;
+
+ // Optional: required skill level (if parent is a pawn)
+ public SkillDef requiredSkill;
+ public int requiredSkillLevel = 0;
+
+ ///
+ /// 检查所有条件是否满足
+ ///
+ public bool AreConditionsMet(Pawn pawn, out string reason)
+ {
+ reason = "";
+
+ // 检查是否启用
+ if (!enabled)
+ {
+ reason = "此生产条目已禁用";
+ return false;
+ }
+
+ // 检查科技需求
+ if (requiredResearch != null && !requiredResearch.IsFinished)
+ {
+ reason = $"需要研究: {requiredResearch.label}";
+ return false;
+ }
+
+ // 检查技能需求
+ if (requiredSkill != null && pawn != null && pawn.skills != null)
+ {
+ var skill = pawn.skills.GetSkill(requiredSkill);
+ if (skill == null || skill.Level < requiredSkillLevel)
+ {
+ reason = $"需要{requiredSkill.label}技能等级: {requiredSkillLevel}";
+ return false;
+ }
+ }
+
+ // 检查自定义条件
+ if (!conditions.NullOrEmpty())
+ {
+ foreach (var condition in conditions)
+ {
+ string conditionReason;
+ if (!condition.IsMet(out conditionReason))
+ {
+ reason = conditionReason;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// 复制条目
+ ///
+ public PawnProductionEntry Copy()
+ {
+ return new PawnProductionEntry
+ {
+ pawnKind = pawnKind,
+ count = count,
+ cooldownTicks = cooldownTicks,
+ cost = cost,
+ customInfo = customInfo,
+ conditions = conditions?.ToList(), // 深拷贝条件列表
+ priority = priority,
+ weight = weight,
+ enabled = enabled,
+ requiredResearch = requiredResearch,
+ requiredSkill = requiredSkill,
+ requiredSkillLevel = requiredSkillLevel
+ };
+ }
}
-}
\ No newline at end of file
+}