This commit is contained in:
2026-01-22 17:30:46 +08:00
parent 0dfcb8545d
commit 6c08ea4598
13 changed files with 1471 additions and 115 deletions

Binary file not shown.

View File

@@ -91,6 +91,36 @@
</li> </li>
</comps> </comps>
</AbilityDef> </AbilityDef>
<AbilityDef>
<defName>ARA_Suicide_Ability</defName>
<label>自杀</label>
<description>只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability</iconPath>
<cooldownTicksRange>1</cooldownTicksRange>
<aiCanUse>false</aiCanUse>
<displayOrder>9900</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>24</range>
<warmupTime>15</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetable>false</targetable>
<targetParams>
<canTargetSelf>true</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityDestroyOwnBodyPart">
<bodyPartsToDestroy>
<li>Brain</li>
</bodyPartsToDestroy>
</li>
</comps>
</AbilityDef>
<!-- 女皇 --> <!-- 女皇 -->
<AbilityDef> <AbilityDef>
@@ -532,6 +562,45 @@
</li> --> </li> -->
</comps> </comps>
</AbilityDef> </AbilityDef>
<AbilityDef>
<defName>ARA_Baneling_Suicide_Ability</defName>
<label>良性自爆</label>
<description>阿拉克涅爆裂种在不使强腐蚀酸活化的情况下发生自爆,这种自爆只会造成轻微的伤害,不会产生酸雾,但是依然留下相同面积的菌毯。</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability</iconPath>
<cooldownTicksRange>1</cooldownTicksRange>
<aiCanUse>false</aiCanUse>
<displayOrder>9900</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<statBases>
<Ability_EffectRadius>3.9</Ability_EffectRadius>
</statBases>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>24</range>
<warmupTime>2</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetable>false</targetable>
<targetParams>
<canTargetSelf>true</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="CompProperties_AbilityExplosion">
<damageAmount>1</damageAmount>
<damageDef>ARA_AcidBomb</damageDef>
<explosionRadius>3.9</explosionRadius>
<armorPenetration>0</armorPenetration>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityDestroyOwnBodyPart">
<bodyPartsToDestroy>
<li>Brain</li>
</bodyPartsToDestroy>
</li>
</comps>
</AbilityDef>
<!-- 王虫 --> <!-- 王虫 -->
<AbilityDef> <AbilityDef>
<defName>ARA_Smokepop_Creeper_Ability_On</defName> <defName>ARA_Smokepop_Creeper_Ability_On</defName>
@@ -1592,33 +1661,4 @@
</AbilityDef> </AbilityDef>
<!-- 杂项 --> <!-- 杂项 -->
<AbilityDef>
<defName>ARA_Suicide_Ability</defName>
<label>自杀</label>
<description>只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability</iconPath>
<cooldownTicksRange>1</cooldownTicksRange>
<aiCanUse>false</aiCanUse>
<displayOrder>9900</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>24</range>
<warmupTime>15</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetable>false</targetable>
<targetParams>
<canTargetSelf>true</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityDestroyOwnBodyPart">
<bodyPartsToDestroy>
<li>Brain</li>
</bodyPartsToDestroy>
</li>
</comps>
</AbilityDef>
</Defs> </Defs>

View File

@@ -63,6 +63,15 @@
<li>ARA_Myrmecocystus_Production_Fuel</li> <li>ARA_Myrmecocystus_Production_Fuel</li>
</hediffs> </hediffs>
</li> </li>
<li Class="ArachnaeSwarm.HediffCompProperties_ProductionQueue">
<productionQueue>
<li>
<pawnKind>ArachnaeBase_Race_Scavenger</pawnKind>
<count>2</count>
<cooldownTicks>5000</cooldownTicks>
</li>
</productionQueue>
</li>
</comps> </comps>
</HediffDef> </HediffDef>
<AbilityDef> <AbilityDef>

View File

@@ -549,6 +549,9 @@
</dessicatedBodyGraphicData> </dessicatedBodyGraphicData>
</li> </li>
</lifeStages> </lifeStages>
<abilities>
<li>ARA_Baneling_Suicide_Ability</li>
</abilities>
</PawnKindDef> </PawnKindDef>
<PawnKindDef Name="ArachnaeBase_Race_Acidcut" ParentName="ARA_InsectKindBase"> <PawnKindDef Name="ArachnaeBase_Race_Acidcut" ParentName="ARA_InsectKindBase">

View File

@@ -779,18 +779,6 @@
<li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier"> <li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier">
<freeProduction>true</freeProduction> <freeProduction>true</freeProduction>
<disableHediff>ARA_RaceBaseSwarmProduceSwitchHediff</disableHediff> <disableHediff>ARA_RaceBaseSwarmProduceSwitchHediff</disableHediff>
<fixedIngredient>ARA_InsectJelly</fixedIngredient>
<maxIngredientCount>1</maxIngredientCount>
<startingIngredientCount>1</startingIngredientCount>
<costPerPawn>1</costPerPawn>
<cooldownTicks>9999</cooldownTicks>
<productionQueue>
<li>
<pawnKind>ArachnaeBase_Race_Scavenger</pawnKind>
<count>2</count>
<cooldownTicks>5000</cooldownTicks>
</li>
</productionQueue>
<spawnEffecter>CocoonDestroyed</spawnEffecter> <spawnEffecter>CocoonDestroyed</spawnEffecter>
</li> </li>
<li Class="ArachnaeSwarm.CompProperties_NodeSwarmLifetime"> <li Class="ArachnaeSwarm.CompProperties_NodeSwarmLifetime">
@@ -1446,16 +1434,11 @@
<li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier"> <li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier">
<freeProduction>true</freeProduction> <freeProduction>true</freeProduction>
<disableHediff>ARA_RaceBaseSwarmProduceSwitchHediff</disableHediff> <disableHediff>ARA_RaceBaseSwarmProduceSwitchHediff</disableHediff>
<fixedIngredient>ARA_InsectJelly</fixedIngredient>
<maxIngredientCount>1</maxIngredientCount>
<startingIngredientCount>1</startingIngredientCount>
<costPerPawn>1</costPerPawn>
<cooldownTicks>9999</cooldownTicks>
<productionQueue> <productionQueue>
<li> <li>
<pawnKind>ArachnaeBase_Race_Baneling</pawnKind> <pawnKind>ArachnaeBase_Race_Baneling</pawnKind>
<count>6</count> <count>6</count>
<cooldownTicks>800</cooldownTicks> <cooldownTicks>600</cooldownTicks>
</li> </li>
</productionQueue> </productionQueue>
<spawnEffecter>CocoonDestroyed</spawnEffecter> <spawnEffecter>CocoonDestroyed</spawnEffecter>

View File

@@ -3,27 +3,47 @@
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", "WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [ "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}", "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:pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.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}" "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}" "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}" "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}" "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}" "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}", "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}" "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": [ "DocumentGroupContainers": [
@@ -86,41 +110,116 @@
"DocumentGroups": [ "DocumentGroups": [
{ {
"DockedWidth": 200, "DockedWidth": 200,
"SelectedChildIndex": 0, "SelectedChildIndex": 1,
"Children": [ "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", "$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" "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", "$type": "Document",
"DocumentIndex": 1, "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", "Title": "CompAutoMechCarrier.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\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", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\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", "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "ViewState": "AgIAAEgCAAAAAAAAAAAewFsCAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-22T03:56:27.144Z", "WhenOpened": "2026-01-22T03:56:27.144Z",
"EditorCaption": "" "EditorCaption": ""
}, },
{ {
"$type": "Document", "$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", "Title": "DamageWorker_ExplosionWithTerrain.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageWorker_ExplosionWithTerrain.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageWorker_ExplosionWithTerrain.cs",
"RelativeDocumentMoniker": "Damage\\DamageWorker_ExplosionWithTerrain.cs", "RelativeDocumentMoniker": "Damage\\DamageWorker_ExplosionWithTerrain.cs",
@@ -128,12 +227,11 @@
"RelativeToolTip": "Damage\\DamageWorker_ExplosionWithTerrain.cs", "RelativeToolTip": "Damage\\DamageWorker_ExplosionWithTerrain.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAFAAAAAbAAAAAAAAAA==", "ViewState": "AgIAAAAAAAAAAAAAAAAAAFAAAAAbAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-22T03:13:00.366Z", "WhenOpened": "2026-01-22T03:13:00.366Z"
"EditorCaption": ""
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 4, "DocumentIndex": 9,
"Title": "Building_ArachnaeGravEngine.cs", "Title": "Building_ArachnaeGravEngine.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
"RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs", "RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs",
@@ -141,12 +239,11 @@
"RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs", "RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAXAAAAAAAAAA==", "ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAXAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-22T03:12:54.988Z", "WhenOpened": "2026-01-22T03:12:54.988Z"
"EditorCaption": ""
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 2, "DocumentIndex": 7,
"Title": "DamageDefExtension_TerrainCover.cs", "Title": "DamageDefExtension_TerrainCover.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageDefExtension_TerrainCover.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageDefExtension_TerrainCover.cs",
"RelativeDocumentMoniker": "Damage\\DamageDefExtension_TerrainCover.cs", "RelativeDocumentMoniker": "Damage\\DamageDefExtension_TerrainCover.cs",
@@ -154,12 +251,11 @@
"RelativeToolTip": "Damage\\DamageDefExtension_TerrainCover.cs", "RelativeToolTip": "Damage\\DamageDefExtension_TerrainCover.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAwAAAAAAAAAA==", "ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAwAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-22T03:12:51.315Z", "WhenOpened": "2026-01-22T03:12:51.315Z"
"EditorCaption": ""
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 5, "DocumentIndex": 10,
"Title": "ThinkNode_ConditionalShouldExtract.cs", "Title": "ThinkNode_ConditionalShouldExtract.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs",
@@ -167,12 +263,11 @@
"RelativeToolTip": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs", "RelativeToolTip": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs",
"ViewState": "AgIAACMAAAAAAAAAAAAewEwAAAANAAAAAAAAAA==", "ViewState": "AgIAACMAAAAAAAAAAAAewEwAAAANAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-21T16:03:09.823Z", "WhenOpened": "2026-01-21T16:03:09.823Z"
"EditorCaption": ""
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 6, "DocumentIndex": 11,
"Title": "JobGiver_ExtractHoney.cs", "Title": "JobGiver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobGiver_ExtractHoney.cs",
@@ -184,7 +279,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 9, "DocumentIndex": 14,
"Title": "CompHoneyProduction_Animal.cs", "Title": "CompHoneyProduction_Animal.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_HoneyProduction_Animal\\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", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_HoneyProduction_Animal\\CompHoneyProduction_Animal.cs",
@@ -196,7 +291,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 10, "DocumentIndex": 15,
"Title": "CompAdvancedTraining.cs", "Title": "CompAdvancedTraining.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_TrainingWork\\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", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_TrainingWork\\CompAdvancedTraining.cs",
@@ -208,7 +303,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 8, "DocumentIndex": 13,
"Title": "Need_HoneyProduction.cs", "Title": "Need_HoneyProduction.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs",
"RelativeDocumentMoniker": "Needs\\Need_HoneyProduction.cs", "RelativeDocumentMoniker": "Needs\\Need_HoneyProduction.cs",
@@ -220,7 +315,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 11, "DocumentIndex": 16,
"Title": "ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs", "Title": "ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs",
@@ -232,7 +327,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 7, "DocumentIndex": 12,
"Title": "JobDriver_ExtractHoney.cs", "Title": "JobDriver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobDriver_ExtractHoney.cs",
@@ -244,7 +339,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 15, "DocumentIndex": 20,
"Title": "JobGiver_Cleaner.cs", "Title": "JobGiver_Cleaner.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\JobGiver_Cleaner.cs",
@@ -256,7 +351,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 14, "DocumentIndex": 19,
"Title": "WorkGiver_ArachnaeClean.cs", "Title": "WorkGiver_ArachnaeClean.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ArachnaeClean.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ArachnaeClean.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ArachnaeClean.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ArachnaeClean.cs",
@@ -268,7 +363,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 12, "DocumentIndex": 17,
"Title": "JobGiver_Grower.cs", "Title": "JobGiver_Grower.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\JobGiver_Grower.cs",
@@ -280,7 +375,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 13, "DocumentIndex": 18,
"Title": "ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs", "Title": "ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\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", "RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs",
@@ -292,7 +387,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 17, "DocumentIndex": 22,
"Title": "WorkGiver_ExtractHoney.cs", "Title": "WorkGiver_ExtractHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ExtractHoney.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ExtractHoney.cs",
@@ -304,7 +399,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 18, "DocumentIndex": 23,
"Title": "WorkGiver_FeedWithHoney.cs", "Title": "WorkGiver_FeedWithHoney.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_FeedWithHoney.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_FeedWithHoney.cs",
@@ -316,7 +411,7 @@
}, },
{ {
"$type": "Document", "$type": "Document",
"DocumentIndex": 16, "DocumentIndex": 21,
"Title": "ARA_DefOf.cs", "Title": "ARA_DefOf.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs",
"RelativeDocumentMoniker": "ARA_DefOf.cs", "RelativeDocumentMoniker": "ARA_DefOf.cs",

View File

@@ -286,6 +286,8 @@
<Compile Include="Hediffs\ARA_HiveMind\HediffComp_HiveMindMaster.cs" /> <Compile Include="Hediffs\ARA_HiveMind\HediffComp_HiveMindMaster.cs" />
<Compile Include="Hediffs\ARA_HiveMind\Hediff_HiveMindDrone.cs" /> <Compile Include="Hediffs\ARA_HiveMind\Hediff_HiveMindDrone.cs" />
<Compile Include="Hediffs\ARA_HiveMind\Hediff_HiveMindMaster.cs" /> <Compile Include="Hediffs\ARA_HiveMind\Hediff_HiveMindMaster.cs" />
<Compile Include="Hediffs\ARA_ProductionQueue\HediffCompProperties_ProductionQueue.cs" />
<Compile Include="Hediffs\ARA_ProductionQueue\HediffComp_ProductionQueue.cs" />
<Compile Include="Hediffs\DRM_HediffCurseFlame\Hediff_CurseFlame.cs" /> <Compile Include="Hediffs\DRM_HediffCurseFlame\Hediff_CurseFlame.cs" />
<Compile Include="Hediffs\HediffComp_LifespanDisplay.cs" /> <Compile Include="Hediffs\HediffComp_LifespanDisplay.cs" />
<Compile Include="Hediffs\HediffComp_SpawnPawnOnRemoved.cs" /> <Compile Include="Hediffs\HediffComp_SpawnPawnOnRemoved.cs" />

View File

@@ -0,0 +1,313 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using System.Linq;
namespace ArachnaeSwarm
{
/// <summary>
/// HediffComp_ProductionQueue的属性类
/// </summary>
public class HediffCompProperties_ProductionQueue : HediffCompProperties
{
// 生产队列定义
public List<PawnProductionEntry> productionQueue = new List<PawnProductionEntry>();
// 生产队列是否可以通过代码动态修改
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<string> 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";
}
}
}
}
/// <summary>
/// 获取生产能力信息的字符串
/// </summary>
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();
}
/// <summary>
/// 构建单个条目的信息
/// </summary>
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();
}
/// <summary>
/// 合并多个生产队列
/// </summary>
public static List<PawnProductionEntry> MergeProductionQueues(List<List<PawnProductionEntry>> queues)
{
var mergedQueue = new List<PawnProductionEntry>();
var entryMap = new Dictionary<PawnKindDef, PawnProductionEntry>();
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;
}
/// <summary>
/// 获取配置统计信息
/// </summary>
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();
}
}
}

View File

@@ -0,0 +1,273 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// 定义生产队列的HediffComp
/// 允许通过Hediff为CompAutoMechCarrier提供生产队列定义
/// </summary>
public class HediffComp_ProductionQueue : HediffComp
{
public HediffCompProperties_ProductionQueue Props =>
(HediffCompProperties_ProductionQueue)props;
/// <summary>
/// 获取Hediff的描述信息显示在Hediff详情中
/// </summary>
public override string CompTipStringExtra
{
get
{
// 获取生产能力信息
string productionInfo = GetProductionInfoString();
if (!string.IsNullOrEmpty(productionInfo))
{
return productionInfo;
}
return base.CompTipStringExtra;
}
}
/// <summary>
/// 获取Hediff的完整描述信息
/// </summary>
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;
}
}
/// <summary>
/// 获取生产能力信息字符串
/// </summary>
public string GetProductionInfoString()
{
if (Props == null)
return "";
// 获取当前Pawn如果适用
Pawn pawn = null;
if (parent != null && parent.pawn != null)
{
pawn = parent.pawn;
}
return Props.GetProductionInfoString(pawn);
}
/// <summary>
/// 获取生产队列定义
/// </summary>
public List<PawnProductionEntry> GetProductionQueue()
{
return Props?.productionQueue ?? new List<PawnProductionEntry>();
}
/// <summary>
/// 获取可用的生产队列
/// 可以根据条件进行过滤
/// </summary>
public List<PawnProductionEntry> GetAvailableProductionQueue(Pawn pawn)
{
var queue = GetProductionQueue();
var availableQueue = new List<PawnProductionEntry>();
foreach (var entry in queue)
{
// 检查前置条件
if (CheckEntryConditions(entry, pawn))
{
availableQueue.Add(entry);
}
}
return availableQueue;
}
/// <summary>
/// 检查条目条件是否满足
/// </summary>
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;
}
/// <summary>
/// 根据PawnKindDef查找生产队列条目
/// </summary>
public PawnProductionEntry GetEntryForPawnKind(PawnKindDef pawnKindDef)
{
var queue = GetProductionQueue();
return queue?.Find(entry => entry.pawnKind == pawnKindDef);
}
/// <summary>
/// 添加新的生产队列条目
/// </summary>
public void AddProductionEntry(PawnProductionEntry entry)
{
var queue = GetProductionQueue();
if (queue == null)
return;
queue.Add(entry);
}
/// <summary>
/// 移除生产队列条目
/// </summary>
public bool RemoveProductionEntry(PawnKindDef pawnKindDef)
{
var queue = GetProductionQueue();
if (queue == null)
return false;
return queue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0;
}
/// <summary>
/// 更新生产队列条目
/// </summary>
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;
}
/// <summary>
/// 获取调试信息
/// </summary>
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();
}
/// <summary>
/// 获取统计信息
/// </summary>
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();
}
}
}

View File

@@ -53,9 +53,234 @@ namespace ArachnaeSwarm
} }
#endregion #endregion
#region Custom Follow Position
private IntVec3? customFollowPosition = null;
private Map customFollowPositionMap = null;
private object customPositionLock = new object();
/// <summary>
/// 获取或设置自定义跟随位置
/// 如果此位置不为空,生成的单位将以此位置而非父单位位置为跟随中心点
/// </summary>
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();
}
}
}
/// <summary>
/// 检查自定义位置是否有效(位置不为空且在正确的地图上)
/// </summary>
public bool HasValidCustomFollowPosition
{
get
{
if (!customFollowPosition.HasValue || customFollowPositionMap == null)
return false;
// 如果父单位已销毁或不在同一地图,自定义位置也无效
if (parent == null || parent.Destroyed || !parent.Spawned)
return false;
return customFollowPositionMap == parent.Map;
}
}
/// <summary>
/// 获取有效的跟随位置
/// 优先返回自定义位置,如果无效则返回父单位位置
/// </summary>
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;
}
/// <summary>
/// 获取跟随位置的地图
/// </summary>
public Map GetFollowPositionMap()
{
if (HasValidCustomFollowPosition)
{
return customFollowPositionMap;
}
if (parent != null && parent.Spawned)
{
return parent.Map;
}
return null;
}
/// <summary>
/// 通知所有已生成的单位跟随位置已改变
/// </summary>
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<CompProducedByMechCarrier>();
if (producedComp != null)
{
producedComp.TryUpdateProducerStatus();
}
}
}
/// <summary>
/// 清空自定义跟随位置
/// </summary>
public void ClearCustomFollowPosition()
{
CustomFollowPosition = null;
}
/// <summary>
/// 设置自定义跟随位置
/// </summary>
/// <param name="position">新的跟随位置</param>
/// <returns>是否设置成功</returns>
public bool SetCustomFollowPosition(IntVec3 position)
{
if (parent == null || !parent.Spawned)
return false;
if (!position.InBounds(parent.Map))
return false;
CustomFollowPosition = position;
return true;
}
/// <summary>
/// 临时设置自定义跟随位置(在一段时间后自动清除)
/// </summary>
/// <param name="position">临时位置</param>
/// <param name="durationTicks">持续时间tick</param>
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; public CompProperties_AutoMechCarrier AutoProps => (CompProperties_AutoMechCarrier)props;
private int TotalPawnCapacity => AutoProps.productionQueue.Sum(e => e.count); // 缓存的合并生产队列
private List<PawnProductionEntry> cachedProductionQueue = null;
private int lastProductionQueueUpdateTick = -1;
private const int PRODUCTION_QUEUE_CACHE_TICKS = 30; // 30 tick缓存
/// <summary>
/// 获取合并后的生产队列
/// 包括从HediffComp扫描的和动态添加的
/// </summary>
public List<PawnProductionEntry> 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;
}
/// <summary>
/// 强制刷新生产队列缓存
/// </summary>
public void RefreshProductionQueue()
{
cachedProductionQueue = null;
lastProductionQueueUpdateTick = -1;
}
/// <summary>
/// 获取总容量
/// </summary>
private int TotalPawnCapacity => GetProductionQueue().Sum(e => e.count);
private int LiveSpawnedPawnsCount(PawnKindDef kind) private int LiveSpawnedPawnsCount(PawnKindDef kind)
{ {
@@ -70,7 +295,11 @@ namespace ArachnaeSwarm
if (CooldownTicksRemaining > 0) if (CooldownTicksRemaining > 0)
return "CooldownTime".Translate() + " " + CooldownTicksRemaining.ToStringSecondsFromTicks(); 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; int cost = entry.cost ?? Props.costPerPawn;
if (!AutoProps.freeProduction && InnerContainer.TotalStackCountOfDef(Props.fixedIngredient) < cost) if (!AutoProps.freeProduction && InnerContainer.TotalStackCountOfDef(Props.fixedIngredient) < cost)
@@ -100,7 +329,22 @@ namespace ArachnaeSwarm
// 初始化生产者信息 // 初始化生产者信息
producedComp.Initialize(parent, this); 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); SpawnedPawns.Add(pawn);
if (parent is Pawn p && p.GetLord() != null) if (parent is Pawn p && p.GetLord() != null)
@@ -108,7 +352,8 @@ namespace ArachnaeSwarm
if (!AutoProps.freeProduction) 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; int costLeft = entry.cost ?? Props.costPerPawn;
List<Thing> things = new List<Thing>(InnerContainer); List<Thing> things = new List<Thing>(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; CooldownTicksRemaining = spawnEntry.cooldownTicks ?? Props.cooldownTicks;
if (Props.spawnedMechEffecter != null) if (Props.spawnedMechEffecter != null)
@@ -140,6 +385,9 @@ namespace ArachnaeSwarm
public override void CompTick() public override void CompTick()
{ {
base.CompTick(); base.CompTick();
// 检查临时位置是否过期
CheckTemporaryPositionExpiry();
if (parent.IsHashIntervalTick(60)) // 每秒检查一次 if (parent.IsHashIntervalTick(60)) // 每秒检查一次
{ {
@@ -149,9 +397,16 @@ namespace ArachnaeSwarm
return; // 有Hediff停止生产 return; // 有Hediff停止生产
} }
// 获取当前生产队列
var productionQueue = GetProductionQueue();
if (productionQueue == null || productionQueue.Count == 0)
{
return; // 生产队列为空,不进行生产
}
// 1. 先检查是否满员 // 1. 先检查是否满员
bool isFull = true; bool isFull = true;
foreach (var entry in AutoProps.productionQueue) foreach (var entry in productionQueue)
{ {
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count) if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{ {
@@ -169,7 +424,7 @@ namespace ArachnaeSwarm
if (CooldownTicksRemaining > 0) return; if (CooldownTicksRemaining > 0) return;
// 3. 寻找空位并生产 // 3. 寻找空位并生产
foreach (var entry in AutoProps.productionQueue) foreach (var entry in productionQueue)
{ {
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count) if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{ {
@@ -183,6 +438,89 @@ namespace ArachnaeSwarm
} }
} }
/// <summary>
/// 添加动态生产队列条目
/// </summary>
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;
}
/// <summary>
/// 移除动态生产队列条目
/// </summary>
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;
}
/// <summary>
/// 更新动态生产队列条目
/// </summary>
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;
}
/// <summary>
/// 清除所有动态生产队列
/// </summary>
public void ClearDynamicProductionQueue()
{
AutoProps.ClearDynamicProductionQueue();
RefreshProductionQueue();
if (AutoProps.debugLogging)
Log.Message("[CompAutoMechCarrier] 清除所有动态生产队列");
}
/// <summary>
/// 扫描Hediff并更新生产队列
/// </summary>
public void ScanAndUpdateProductionQueue()
{
RefreshProductionQueue();
if (AutoProps.debugLogging)
{
var productionQueue = GetProductionQueue();
Log.Message($"[CompAutoMechCarrier] 扫描Hediff完成生产队列条目数: {productionQueue.Count}");
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra() public override IEnumerable<Gizmo> CompGetGizmosExtra()
{ {
// 移除所有Gizmo逻辑 // 移除所有Gizmo逻辑
@@ -194,9 +532,16 @@ namespace ArachnaeSwarm
SpawnedPawns.RemoveAll(p => p == null || p.Destroyed); SpawnedPawns.RemoveAll(p => p == null || p.Destroyed);
string text = "Pawns: " + SpawnedPawns.Count + " / " + TotalPawnCapacity; 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}"; text += $"\n- {entry.pawnKind.LabelCap}: {LiveSpawnedPawnsCount(entry.pawnKind)} / {entry.count}";
// 显示自定义信息
if (entry.customInfo != null)
{
text += $" ({entry.customInfo})";
}
} }
if (CooldownTicksRemaining > 0) if (CooldownTicksRemaining > 0)
@@ -208,7 +553,93 @@ namespace ArachnaeSwarm
{ {
text += "\n" + base.CompInspectStringExtra(); 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; return text;
} }
/// <summary>
/// 获取调试信息
/// </summary>
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();
}
} }
} }

View File

@@ -12,8 +12,14 @@ namespace ArachnaeSwarm
// 如果单位拥有这个Hediff则停止生产 // 如果单位拥有这个Hediff则停止生产
public HediffDef disableHediff; public HediffDef disableHediff;
// 定义生产队列 // 从HediffComp获取的生产队列通过代码动态设置
public List<PawnProductionEntry> productionQueue = new List<PawnProductionEntry>(); public List<PawnProductionEntry> DynamicProductionQueue = new List<PawnProductionEntry>();
// 是否启用调试日志
public bool debugLogging = false;
// 扫描Hediff并获取生产队列
public bool ScanHediffsForProductionQueue = true;
public CompProperties_AutoMechCarrier() public CompProperties_AutoMechCarrier()
{ {
@@ -28,27 +34,132 @@ namespace ArachnaeSwarm
yield return error; yield return error;
} }
if (productionQueue.NullOrEmpty()) // 不再要求必须有生产队列因为可以通过HediffComp动态添加
{ // 生产队列可以在运行时动态设置
yield return "CompProperties_AutoMechCarrier must have at least one entry in productionQueue.";
}
} }
public override void ResolveReferences(ThingDef parentDef) public override void ResolveReferences(ThingDef parentDef)
{ {
base.ResolveReferences(parentDef); base.ResolveReferences(parentDef);
// Prevent division by zero if costPerPawn is not set, which the base game AI might try to access. // Prevent division by zero if costPerPawn is not set, which the base game AI might try to access.
if (costPerPawn <= 0) if (costPerPawn <= 0)
{ {
costPerPawn = 1; costPerPawn = 1;
} }
// 如果spawnPawnKind为空(因为我们用了新的队列系统), // 如果spawnPawnKind为空,我们不再设置默认值
// 就从队列里取第一个作为“假”值以防止基类方法在生成Gizmo标签时出错。 // 因为现在生产队列是动态的
if (spawnPawnKind == null && !productionQueue.NullOrEmpty()) }
/// <summary>
/// 获取合并后的生产队列
/// 包括从HediffComp扫描的和动态添加的
/// </summary>
public List<PawnProductionEntry> GetMergedProductionQueue(Pawn pawn)
{
var queuesToMerge = new List<List<PawnProductionEntry>>();
// 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);
}
/// <summary>
/// 从HediffComp获取生产队列
/// </summary>
private List<PawnProductionEntry> GetProductionQueueFromHediffs(Pawn pawn)
{
var productionQueue = new List<PawnProductionEntry>();
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<HediffComp_ProductionQueue>();
if (productionComp != null)
{
var queueFromHediff = productionComp.GetAvailableProductionQueue(pawn);
if (queueFromHediff != null && queueFromHediff.Count > 0)
{
productionQueue.AddRange(queueFromHediff);
}
}
}
return productionQueue;
}
/// <summary>
/// 添加动态生产队列条目
/// </summary>
public void AddDynamicProductionEntry(PawnProductionEntry entry)
{
if (DynamicProductionQueue == null)
DynamicProductionQueue = new List<PawnProductionEntry>();
DynamicProductionQueue.Add(entry);
}
/// <summary>
/// 移除动态生产队列条目
/// </summary>
public bool RemoveDynamicProductionEntry(PawnKindDef pawnKindDef)
{
if (DynamicProductionQueue == null)
return false;
return DynamicProductionQueue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0;
}
/// <summary>
/// 更新动态生产队列条目
/// </summary>
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;
}
/// <summary>
/// 清除所有动态生产队列
/// </summary>
public void ClearDynamicProductionQueue()
{
if (DynamicProductionQueue != null)
DynamicProductionQueue.Clear();
} }
} }
} }

View File

@@ -1,4 +1,7 @@
using RimWorld;
using System.Collections.Generic;
using Verse; using Verse;
using System.Linq;
namespace ArachnaeSwarm namespace ArachnaeSwarm
{ {
@@ -19,5 +22,98 @@ namespace ArachnaeSwarm
// Optional: specific cost for this entry. If not set, the parent comp's costPerPawn is used. // Optional: specific cost for this entry. If not set, the parent comp's costPerPawn is used.
public int? cost; 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<Condition> 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;
/// <summary>
/// 检查所有条件是否满足
/// </summary>
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;
}
/// <summary>
/// 复制条目
/// </summary>
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
};
}
} }
} }