精华提取茧,蓝图卵和附带的所有修改

This commit is contained in:
Tourswen
2025-10-15 02:41:20 +08:00
parent a9c95142af
commit 417b87498f
41 changed files with 1262 additions and 235 deletions

Binary file not shown.

View File

@@ -39,7 +39,8 @@
<cooldownTicksRange>601</cooldownTicksRange>
<hostile>false</hostile>
<showOnCharacterCard>true</showOnCharacterCard>
<displayGizmoWhileUndrafted>false</displayGizmoWhileUndrafted>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<aiCanUse>false</aiCanUse>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
@@ -68,7 +69,8 @@
<cooldownTicksRange>601</cooldownTicksRange>
<hostile>false</hostile>
<showOnCharacterCard>true</showOnCharacterCard>
<displayGizmoWhileUndrafted>false</displayGizmoWhileUndrafted>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<aiCanUse>false</aiCanUse>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>

View File

@@ -214,6 +214,27 @@
</comps>
</AbilityDef>
<AbilityDef ParentName="ARA_EggSpew_Base">
<defName>ARA_EggSpew_Techprint</defName>
<label>生育基因试验卵</label>
<description>从卵巢中排出一颗特殊的虫卵,它无法孵化任何督虫,而是可以孵化一些特定的科技蓝图,阿拉克涅女皇种可以通过与其交互将其激活。\n\n该虫卵需要使用大量精华素维持工作并且能研究什么以其落地时的研究完成度为准那些尚未解锁的科技将无法孵化其蓝图。</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_EggSpew_Huge</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_EggSac_Techprint</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityShowTemperatureRange">
<temperatureCheckBuilding>ARA_InteractiveEggSac_Techprint</temperatureCheckBuilding>
<customLabel>温度要求</customLabel>
<showCurrentTemperature>true</showCurrentTemperature>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_5ESS</requiredResearch>
<failMessage>需要科技 节点ESS-5"精华萃取" 以解锁技能</failMessage>
</li>
</comps>
</AbilityDef>
<!-- T0 -->
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_Cocoon_Cloth</defName>

View File

@@ -9,6 +9,7 @@
<pawnSingular>colonist</pawnSingular>
<pawnsPlural>colonists</pawnsPlural>
<techLevel>Animal</techLevel>
<categoryTag>ARA_New_Hive</categoryTag>
<backstoryFilters>
<li>
<categories>

View File

@@ -19,4 +19,12 @@
<reportString>entering TargetA.</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef>
<!-- 搬运俘虏到燃料转化罐的工作定义 -->
<JobDef>
<defName>ARA_CarryPrisonerToRefuelingVat</defName>
<driverClass>ArachnaeSwarm.JobDriver_CarryPrisonerToRefuelingVat</driverClass>
<reportString>将 TargetA 带到 TargetB.</reportString>
<suspendable>false</suspendable>
</JobDef>
</Defs>

View File

@@ -22,4 +22,11 @@
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef>
<JobDef>
<defName>ARA_StartResearchProduction</defName>
<driverClass>ArachnaeSwarm.JobDriver_StartResearchProduction</driverClass>
<reportString>正在启动孵化 TargetA.</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef>
</Defs>

View File

@@ -62,6 +62,7 @@
<abilities>
<li>ARA_BindDrone</li>
<li>ARA_AcidSprayBurst_Queen</li>
<li>ARA_EggSpew_Techprint</li>
<li>ARA_TumorSpew</li>
</abilities>
</PawnKindDef>

View File

@@ -68,7 +68,7 @@
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>30</count>
@@ -122,7 +122,7 @@
<costList>
<Plasteel>20</Plasteel>
<ARA_Activated_Bacterium>30</ARA_Activated_Bacterium>
<ARA_Carapace>30</ARA_Carapace>
<ARA_Gene_Essence>30</ARA_Gene_Essence>
</costList>
</ThingDef>
<RecipeDef ParentName="ARA_SurgeryInstallImplantBase">
@@ -146,7 +146,7 @@
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>20</count>
@@ -204,7 +204,7 @@
</recipeMaker>
<costList>
<ARA_Activated_Bacterium>15</ARA_Activated_Bacterium>
<ARA_Carapace>20</ARA_Carapace>
<ARA_Gene_Essence>20</ARA_Gene_Essence>
</costList>
</ThingDef>
<RecipeDef ParentName="ARA_SurgeryInstallImplantBase">
@@ -227,7 +227,7 @@
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>5</count>
@@ -270,7 +270,7 @@
</recipeMaker>
<costList>
<ARA_Activated_Bacterium>1</ARA_Activated_Bacterium>
<ARA_Carapace>5</ARA_Carapace>
<ARA_Gene_Essence>5</ARA_Gene_Essence>
</costList>
</ThingDef>
<RecipeDef ParentName="ARA_SurgeryInstallImplantBase">
@@ -278,14 +278,14 @@
<label>甲壳增殖</label>
<description>以甲壳素为阿拉克涅虫族的甲壳进行加厚,获得额外的防御力。</description>
<descriptionHyperlinks>
<HediffDef>ARA_Carapace_Shell_Hediff</HediffDef>
<HediffDef>ARA_Gene_Essence_Shell_Hediff</HediffDef>
</descriptionHyperlinks>
<jobString>正在实施定向变异</jobString>
<ingredients>
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>25</count>
@@ -293,17 +293,17 @@
</ingredients>
<fixedIngredientFilter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</fixedIngredientFilter>
<appliedOnFixedBodyParts>
<li>ARA_Chitin_Shell</li>
</appliedOnFixedBodyParts>
<addsHediff>ARA_Carapace_Shell_Hediff</addsHediff>
<addsHediff>ARA_Gene_Essence_Shell_Hediff</addsHediff>
<researchPrerequisite>ARA_Technology_1EVO</researchPrerequisite>
</RecipeDef>
<HediffDef ParentName="AddedBodyPartBase">
<defName>ARA_Carapace_Shell_Hediff</defName>
<defName>ARA_Gene_Essence_Shell_Hediff</defName>
<label>甲壳增殖</label>
<description>这只阿拉克涅虫族的甲壳以甲壳素进行了增厚,获得了额外防御力。</description>
<hediffClass>Hediff_Implant</hediffClass>
@@ -325,7 +325,7 @@
<maxSeverity>1</maxSeverity> <!-- 最大层数,可以根据需要调整 -->
</HediffDef>
<ThingDef ParentName="ARA_BodyPartProstheticBase">
<defName>ARA_Carapace_Shell</defName>
<defName>ARA_Gene_Essence_Shell</defName>
<label>甲壳增殖</label>
<description>阿拉克涅虫族的反应甲壳可以使其免受一次外来伤害,但是随后这块甲片就会弹开,不再给予防御力。该手术不需要制作部件,可以直接在阿拉克涅督虫身上实施。</description>
<descriptionHyperlinks>
@@ -335,7 +335,7 @@
<researchPrerequisite>ARA_Technology_1EVO</researchPrerequisite>
</recipeMaker>
<costList>
<ARA_Carapace>25</ARA_Carapace>
<ARA_Gene_Essence>25</ARA_Gene_Essence>
</costList>
</ThingDef>
@@ -360,7 +360,7 @@
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>20</count>
@@ -415,7 +415,7 @@
<researchPrerequisite>ARA_Technology_6EVO</researchPrerequisite>
</recipeMaker>
<costList>
<ARA_Carapace>20</ARA_Carapace>
<ARA_Gene_Essence>20</ARA_Gene_Essence>
<ARA_Activated_Bacterium>6</ARA_Activated_Bacterium>
</costList>
</ThingDef>
@@ -439,7 +439,7 @@
<li>
<filter>
<thingDefs>
<li>ARA_Carapace</li>
<li>ARA_Gene_Essence</li>
</thingDefs>
</filter>
<count>20</count>
@@ -526,7 +526,7 @@
<researchPrerequisite>ARA_Technology_3EVO</researchPrerequisite>
</recipeMaker>
<costList>
<ARA_Carapace>20</ARA_Carapace>
<ARA_Gene_Essence>20</ARA_Gene_Essence>
<ARA_Activated_Bacterium>6</ARA_Activated_Bacterium>
</costList>
</ThingDef>

View File

@@ -5,33 +5,48 @@
<tab>ARA_ResearchTab</tab>
<heldByFactionCategoryTags Inherit="False" />
</ResearchProjectDef>
<ResearchProjectDef Abstract="True" Name="ARA_techBase_Needtechprint" ParentName="ARA_techBase">
<techLevel>Animal</techLevel>
<tab>ARA_ResearchTab</tab>
<techprintCount>1</techprintCount>
<techprintCommonality>0</techprintCommonality>
<techprintMarketValue>1</techprintMarketValue>
<heldByFactionCategoryTags>
<li>ARA_New_Hive</li>
</heldByFactionCategoryTags>
</ResearchProjectDef>
<!-- 女皇工艺进化 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Base_Technology</defName>
<label>基础基因序列获取</label>
<description>解锁虫群的基础科技,允许孵化基本的辅虫和武装器官</description>
<description>解锁虫群的基础科技,允许孵化基本的辅虫和武装器官。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>100</baseCost>
<researchViewX>0.00</researchViewX>
<researchViewY>3.20</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_1WMT</defName>
<label>节点WMT-1"突破"</label>
<description>允许女皇种和工艺种进化到下一个阶段。</description>
<description>允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>3000</baseCost>
<researchViewX>4.50</researchViewX>
<researchViewY>3.20</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<techprintCount>1</techprintCount>
<techprintCommonality>0</techprintCommonality>
<techprintMarketValue>1</techprintMarketValue>
<heldByFactionCategoryTags>
<li>ARA_New_Hive</li>
</heldByFactionCategoryTags>
<prerequisites>
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_2WMT</defName>
<label>节点WMT-2"突破2"</label>
<description>允许女皇种和工艺种进化到下一个阶段。</description>
<description>允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>7000</baseCost>
<researchViewX>9.00</researchViewX>
<researchViewY>3.20</researchViewY>
@@ -128,18 +143,18 @@
<label>节点THD-1"灵能闪电"</label>
<description>允许工艺种孵化新的灵能闪电系武器。</description>
<baseCost>2500</baseCost>
<researchViewX>8.50</researchViewX>
<researchViewY>2.10</researchViewY>
<researchViewX>7.50</researchViewX>
<researchViewY>2.70</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_6KYC</li>
</prerequisites>
</ResearchProjectDef>
<!-- 孵化发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_1KYC</defName>
<label>节点KYC-1"战士虫"</label>
<description>允许女皇种孵化新的虫族——战士种。</description>
<description>允许女皇种孵化新的虫族——战士种。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>150</baseCost>
<researchViewX>1.00</researchViewX>
<researchViewY>5.40</researchViewY>
@@ -148,10 +163,10 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_4KYC</defName>
<label>节点KYC-4"原虫"</label>
<description>允许女皇种孵化新的虫族——原虫种,一种可以寄生在别的种族身上以控制它们的特殊督虫。</description>
<description>允许女皇种孵化新的虫族——原虫种,一种可以寄生在别的种族身上以控制它们的特殊督虫。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>200</baseCost>
<researchViewX>1.00</researchViewX>
<researchViewY>4.90</researchViewY>
@@ -160,10 +175,10 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_2KYC</defName>
<label>节点KYC-2"飞行翼膜"</label>
<description>允许女皇种孵化新的虫族——空天种,敏捷而致命的精锐虫族,拥有以飞行姿态穿梭于战场的能力。</description>
<description>允许女皇种孵化新的虫族——空天种,敏捷而致命的精锐虫族,拥有以飞行姿态穿梭于战场的能力。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>1600</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>4.30</researchViewY>
@@ -172,10 +187,10 @@
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_5KYC</defName>
<label>节点KYC-5"巨甲"</label>
<description>允许女皇种孵化新的虫族——浓雾种,一种拥有厚重甲壳的大型督虫,可以释放烟雾、阻燃剂和召唤虫族增援的信息素以协助虫群进行集群冲击。</description>
<description>允许女皇种孵化新的虫族——浓雾种,一种拥有厚重甲壳的大型督虫,可以释放烟雾、阻燃剂和召唤虫族增援的信息素以协助虫群进行集群冲击。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>800</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>4.80</researchViewY>
@@ -184,22 +199,22 @@
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_6KYC</defName>
<label>节点KYC-6"灵脑"</label>
<description>允许女皇种孵化新的虫族——织域种,一种寿命长且拥有强大灵能的特殊虫族,不仅能协助虫群的科研工作,也是一个强大的施法者。</description>
<description>允许女皇种孵化新的虫族——织域种,一种寿命长且拥有强大灵能的特殊虫族,不仅能协助虫群的科研工作,也是一个强大的施法者。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>800</baseCost>
<researchViewX>7.50</researchViewX>
<researchViewX>6.50</researchViewX>
<researchViewY>2.70</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_7KYC</defName>
<label>节点KYC-7"亲卫"</label>
<description>允许女皇种孵化新的虫族——禁卫种,一种寿命较其他虫族更长的精锐虫族,拥有优秀的远程作战能力和社交能力,同时也可以作为指挥官指挥虫群。</description>
<description>允许女皇种孵化新的虫族——禁卫种,一种寿命较其他虫族更长的精锐虫族,拥有优秀的远程作战能力和社交能力,同时也可以作为指挥官指挥虫群。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>2800</baseCost>
<researchViewX>10.00</researchViewX>
<researchViewY>3.80</researchViewY>
@@ -343,7 +358,7 @@
<label>节点MEL-2"骨鞭"</label>
<description>允许工艺种孵化新的武器。</description>
<baseCost>600</baseCost>
<researchViewX>6.50</researchViewX>
<researchViewX>5.50</researchViewX>
<researchViewY>2.70</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
@@ -366,6 +381,18 @@
</prerequisites>
</ResearchProjectDef>
<!-- 建筑发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_5ESS</defName>
<label>节点ESS-5"精华萃取"</label>
<description>允许阿拉克涅虫群建造特殊的活体建筑,将俘虏投入以产出精华素。</description>
<baseCost>250</baseCost>
<researchViewX>1.00</researchViewX>
<researchViewY>4.40</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_1NPT</defName>
<label>节点NPT-1"中央塔"</label>
@@ -453,7 +480,7 @@
<li>ARA_Technology_2NPT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_4NPT</defName>
<label>节点NPT-4"孵化池"</label>
<description>允许虫族建造孵化池。一种专用于批量生产虫族的孵化场地。孵化池的孵化效率比孵化茧更高。</description>
@@ -534,10 +561,10 @@
</prerequisites>
</ResearchProjectDef>
<!-- 进化发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_1VTE</defName>
<label>节点VTE-1"护卫者"</label>
<description>允许盾头种进行定向进化,抛弃其产出甲壳素和建造建筑的能力以换取战斗能力、移动能力和冲撞攻击的技能。</description>
<description>允许盾头种进行定向进化,抛弃其产出甲壳素和建造建筑的能力以换取战斗能力、移动能力和冲撞攻击的技能。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>1200</baseCost>
<researchViewX>6.50</researchViewX>
<researchViewY>4.80</researchViewY>
@@ -549,10 +576,10 @@
<li>ARA_Technology_5KYC</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_1MED</defName>
<label>节点MED-1"疗愈种"</label>
<description>允许蜜罐种进行定向进化,以强化其自身的医疗能力并解锁孵化医药茧的技能。</description>
<description>允许蜜罐种进行定向进化,以强化其自身的医疗能力并解锁孵化医药茧的技能。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>1200</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>2.10</researchViewY>
@@ -561,10 +588,10 @@
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_4CLO</defName>
<label>节点CLO-4"追猎种"</label>
<description>允许战士种进行定向进化,牺牲其使用远程武器的能力以换取强大的近战和永久隐身的能力。</description>
<description>允许战士种进行定向进化,牺牲其使用远程武器的能力以换取强大的近战和永久隐身的能力。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>1800</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>5.30</researchViewY>
@@ -576,10 +603,10 @@
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_1BAC</defName>
<label>节点BAC-1"育菌种"</label>
<description>允许迷雾种进行定向进化,牺牲其护甲和喷射信息素的能力以换成生产虫群所需高级资源"活化钜菌"的能力。</description>
<description>允许迷雾种进行定向进化,牺牲其护甲和喷射信息素的能力以换成生产虫群所需高级资源"活化钜菌"的能力。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>1000</baseCost>
<researchViewX>7.50</researchViewX>
<researchViewY>3.80</researchViewY>
@@ -589,10 +616,10 @@
<li>ARA_Technology_5KYC</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
<defName>ARA_Technology_6LOD</defName>
<label>节点LOD-6"巢之主"</label>
<description>允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量天巢种的能力。</description>
<description>允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量天巢种的能力。\n\n阿拉克涅虫群所有需要蓝图的科技其蓝图只能通过女皇种的基因试验卵获取。</description>
<baseCost>3500</baseCost>
<researchViewX>10.00</researchViewX>
<researchViewY>5.30</researchViewY>
@@ -610,11 +637,11 @@
<label>节点EVO-1"初级进化"</label>
<description>允许实行新的阿拉克涅进化手术,使得阿拉克涅虫族获得更大的营养储存能力和更厚的甲壳。</description>
<baseCost>250</baseCost>
<researchViewX>1.00</researchViewX>
<researchViewX>2.00</researchViewX>
<researchViewY>4.40</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Base_Technology</li>
<li>ARA_Technology_5ESS</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
@@ -625,6 +652,9 @@
<researchViewX>6.50</researchViewX>
<researchViewY>4.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_2KYC</li>
</prerequisites>
@@ -637,6 +667,9 @@
<researchViewX>6.50</researchViewX>
<researchViewY>1.50</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_8VXI</li>
</prerequisites>
@@ -649,6 +682,9 @@
<researchViewX>7.50</researchViewX>
<researchViewY>4.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_1VTE</li>
</prerequisites>
@@ -661,6 +697,9 @@
<researchViewX>6.50</researchViewX>
<researchViewY>5.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_4CLO</li>
</prerequisites>
@@ -673,6 +712,9 @@
<researchViewX>7.50</researchViewX>
<researchViewY>4.80</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_1VTE</li>
</prerequisites>
@@ -685,6 +727,9 @@
<researchViewX>10.00</researchViewX>
<researchViewY>4.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding> <!-- ARA_MorphableResearchBench-->
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<hiddenPrerequisites>
<li>ARA_Technology_5EVO</li>
</hiddenPrerequisites>
@@ -700,6 +745,9 @@
<researchViewX>11.00</researchViewX>
<researchViewY>4.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding> <!-- ARA_MorphableResearchBench-->
<hiddenPrerequisites>
<li>ARA_Technology_5ESS</li>
</hiddenPrerequisites>
<prerequisites>
<li>ARA_Technology_2WMT</li>
</prerequisites>

View File

@@ -165,4 +165,34 @@
<allowedArchonexusCount>80</allowedArchonexusCount>
<possessionCount>50</possessionCount>
</ThingDef>
<ThingDef ParentName="ResourceBase">
<defName>ARA_Gene_Essence</defName>
<label>精华素</label>
<description>由一只小型辅虫——阿拉克涅精华种——保存在体内的异族遗传物质,非常脆弱,通常由精华提取腔从俘虏身上获取,是阿拉克涅虫群重要的资源之一。</description>
<graphicData>
<texPath>ArachnaeSwarm/Item/ARA_Gene_Essence</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>0.9</drawSize>
</graphicData>
<genericMarketSellable>false</genericMarketSellable>
<soundInteract>Standard_Drop</soundInteract>
<soundDrop>Standard_Drop</soundDrop>
<useHitPoints>true</useHitPoints>
<healthAffectsPrice>false</healthAffectsPrice>
<stackLimit>30</stackLimit>
<statBases>
<MarketValue>120</MarketValue>
<MaxHitPoints>10</MaxHitPoints>
<Mass>0.01</Mass>
</statBases>
<thingCategories>
<li>ResourcesRaw</li>
</thingCategories>
<burnableByRecipe>false</burnableByRecipe>
<smeltable>false</smeltable>
<terrainAffordanceNeeded>Medium</terrainAffordanceNeeded>
<allowedArchonexusCount>80</allowedArchonexusCount>
<possessionCount>50</possessionCount>
</ThingDef>
</Defs>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<ThingDef Name="ARA_InteractiveEggSac_Base" ParentName="BuildingNaturalBase" Abstract="True">
<thingClass>Building</thingClass>
@@ -492,8 +492,58 @@
</comps>
</ThingDef>
<!-- 科技 -->
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_Proj_EggSac_Techprint</defName>
<projectile>
<spawnsThingDef>ARA_InteractiveEggSac_Techprint</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_Cocoon_Base">
<defName>ARA_InteractiveEggSac_Techprint</defName>
<label>阿拉克涅基因试验卵</label>
<description>一个脆弱、易燃、黏滑的囊状物,它无法孵化任何督虫,而是可以孵化一些特定的科技蓝图,阿拉克涅女皇种可以通过与其交互将其激活。\n\n该虫卵需要使用大量精华素维持工作并且能研究的项目以其落地时的研究完成度为准那些尚未解锁的科技将无法孵化其蓝图。</description>
<statBases>
<MarketValue>2000</MarketValue>
</statBases>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>500</fuelCapacity>
<fuelLabel>精华素</fuelLabel>
<fuelFilter>
<thingDefs>
<li>ARA_Gene_Essence</li>
</thingDefs>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>0.02</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- 研究生产组件 -->
<li Class="ArachnaeSwarm.CompProperties_ResearchProducer">
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<destroyOnSpawn>true</destroyOnSpawn>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<nutritionPerResearchPoint>0.06</nutritionPerResearchPoint>
<productionTicksPerResearchPoint>30</productionTicksPerResearchPoint>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-30</minSafeTemperature>
<maxSafeTemperature>55</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<ThingDef Name="ARA_Cocoon_Base" ParentName="BuildingBase" Abstract="True">
<thingClass>Building</thingClass>
<graphicData>
@@ -728,7 +778,7 @@
<statBases>
<MarketValue>5000</MarketValue>
</statBases>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
@@ -983,7 +1033,7 @@
<statBases>
<MarketValue>10000</MarketValue>
</statBases>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
@@ -1082,6 +1132,7 @@
<label>阿拉克涅孵化茧 医药</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅蜜罐种所诞之卵,内含孵化一组医疗用品或化学品的营养物质,可以通过阿拉克涅蜜罐种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为0~12°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_Medicine</ThingDef>
<ThingDef>ARA_PheromoneSolvent</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>

View File

@@ -104,7 +104,7 @@
<ThingDef ParentName="BuildingBase">
<defName>ARA_GrowthVat</defName>
<label>阿拉克涅消化茧</label>
<description>阿拉克涅虫群用来存放和消化猎物的茧,那些被扔进茧中的倒霉鬼将逐渐被酸蚀溶解,从而为阿拉克涅营养供给塔网络提供额外的生物质传输效率和孵化速度。</description>
<description>阿拉克涅虫群用来存放和消化猎物的茧,那些被扔进茧中的倒霉鬼将逐渐被酸蚀溶解,从而为阿拉克涅营养供给塔网络提供额外的生物质传输效率和孵化速度一个网络内最大可启用15个消化茧</description>
<thingClass>ArachnaeSwarm.Building_NutrientVat</thingClass>
<containedPawnsSelectable>true</containedPawnsSelectable>
<tickerType>Normal</tickerType>
@@ -182,7 +182,7 @@
<li>ARA_BioforgeIncubator</li>
<li>ARA_BioforgeIncubator_Thing</li>
</linkableBuildings>
<maxSimultaneous>10</maxSimultaneous>
<maxSimultaneous>15</maxSimultaneous>
<maxDistance>20</maxDistance>
<statOffsets>
<NutrientTransmissionEfficiency>0.05</NutrientTransmissionEfficiency>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<ThingDef ParentName="BuildingBase">
<defName>ARA_RefuelingVat</defName>
<label>精华提取腔</label>
<description>一个特殊的活体建筑,可以置入阿拉克涅虫群的俘虏,使用缓慢而痛苦的方式提取其遗传物质,将其转换为精华素以供虫群使用。\n\n——怎么采集的你别问。</description>
<thingClass>ArachnaeSwarm.Building_RefuelingVat</thingClass>
<containedPawnsSelectable>true</containedPawnsSelectable>
<tickerType>Normal</tickerType>
<descriptionHyperlinks>
<ThingDef>ARA_Gene_Essence</ThingDef>
</descriptionHyperlinks>
<uiIconPath>ArachnaeSwarm/Building/ARA_RefuelingVat_Icon</uiIconPath>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_RefuelingVat</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(2,2)</drawSize>
<shadowData>
<volume>(1.25, 0.2, 0.5)</volume>
<offset>(0,0,-0.45)</offset>
</shadowData>
</graphicData>
<castEdgeShadows>false</castEdgeShadows>
<defaultPlacingRot>North</defaultPlacingRot>
<size>(2,2)</size>
<statBases>
<MaxHitPoints>500</MaxHitPoints>
<WorkToBuild>8000</WorkToBuild>
<Mass>30</Mass>
<Flammability>0.5</Flammability>
</statBases>
<costList>
<ARA_Carapace>20</ARA_Carapace>
<ARA_InsectJelly>3</ARA_InsectJelly>
</costList>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<pathCost>42</pathCost>
<blockWind>true</blockWind>
<drawerType>MapMeshAndRealTime</drawerType>
<fillPercent>0.5</fillPercent>
<canOverlapZones>false</canOverlapZones>
<designationCategory>ARA_Buildings</designationCategory>
<uiOrder>2200</uiOrder>
<hasInteractionCell>true</hasInteractionCell>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<inspectorTabs>
<li>ITab_BiosculpterNutritionStorage</li>
<li>ITab_Genes</li>
</inspectorTabs>
<researchPrerequisites>
<li>GrowthVats</li>
</researchPrerequisites>
<building>
<ai_chillDestination>false</ai_chillDestination>
<haulToContainerDuration>120</haulToContainerDuration>
<workTableRoomRole>Laboratory</workTableRoomRole>
<relatedTerrain>
<li>ARA_InsectCreep</li>
</relatedTerrain>
</building>
<constructionSkillPrerequisite>4</constructionSkillPrerequisite>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<comps>
<!-- 标准的 CompRefuelable -->
<li Class="CompProperties_Refuelable">
<fuelLabel>精华素</fuelLabel>
<fuelGizmoLabel>精华素</fuelGizmoLabel>
<fuelCapacity>20</fuelCapacity>
<fuelConsumptionRate>0</fuelConsumptionRate>
<consumeFuelOnlyWhenUsed>true</consumeFuelOnlyWhenUsed>
<autoRefuelPercent>0</autoRefuelPercent>
<initialAllowAutoRefuel>true</initialAllowAutoRefuel>
<showAllowAutoRefuelToggle>false</showAllowAutoRefuelToggle>
<fuelFilter>
<thingDefs>
<li>ARA_Gene_Essence</li>
</thingDefs>
</fuelFilter>
<targetFuelLevelConfigurable>false</targetFuelLevelConfigurable>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<canEjectFuel>true</canEjectFuel>
</li>
<!-- 燃料满了自动弹出 -->
<li Class="ArachnaeSwarm.CompProperties_AutoEjector">
<!-- 精确指定要监控的燃料组件 -->
<targetComp>CompRefuelable</targetComp>
<!-- 在燃料达到99%时弹出 -->
<ejectAtPercent>0.99</ejectAtPercent>
</li>
<li Class="ArachnaeSwarm.CompProperties_RefuelingVat">
<fuelProductionPerDay>5</fuelProductionPerDay> <!-- 每天生产20单位燃料 -->
<fuelProductionEfficiency>1</fuelProductionEfficiency> <!-- 150%效率 -->
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>3</spawnRadius>
</li>
</comps>
<modExtensions>
<li Class="ArachnaeSwarm.DefModExtension_NutrientVat">
<!-- 在这里配置您的顶部贴图 -->
<topGraphicPath>ArachnaeSwarm/Building/ARA_RefuelingVatTop</topGraphicPath>
<!-- 如果是单张贴图,使用 Graphic_Single -->
<graphicClass>Graphic_Multi</graphicClass>
</li>
</modExtensions>
<researchPrerequisites Inherit="False">
<li>ARA_Technology_5ESS</li>
</researchPrerequisites>
</ThingDef>
</Defs>

View File

@@ -51,13 +51,6 @@
<CasterDead>施法者已死亡</CasterDead>
<NoValidBodyParts>没有可破坏的身体部位</NoValidBodyParts>
<AssignCarryPrisoner>为囚犯/奴隶分配运送者</AssignCarryPrisoner>
<AssignCarryPrisonerDesc>选择一个虫群成员将囚犯或奴隶带到阿拉克涅消化茧中</AssignCarryPrisonerDesc>
<NoAvailableHiveCarriers>没有可用的虫群成员来携带囚犯</NoAvailableHiveCarriers>
<CarrierAssigned>已指派{0}将{1}运送到阿拉克涅消化茧</CarrierAssigned>
<NoAvailableCarriers>没有可用的虫群成员运送者</NoAvailableCarriers>
<NoPrisonersOrSlaves>没有可用的囚犯或奴隶</NoPrisonersOrSlaves>
<DisallowedItems>禁止物品</DisallowedItems>
<CannotUseDisallowedFuel>{0} 不能用作 {1} 的燃料</CannotUseDisallowedFuel>
@@ -68,4 +61,32 @@
<ARA_NeedCost_Insufficient>{0}不足</ARA_NeedCost_Insufficient>
<ARA_NeedCost_CanCast>可以施放</ARA_NeedCost_CanCast>
<PrisonerPlacedInRefuelingVat>已将{0}放入提取腔。</PrisonerPlacedInRefuelingVat>
<!-- 燃料转化罐相关翻译 -->
<FuelProduction>生产资源</FuelProduction>
<ProductionEfficiency>生产效率</ProductionEfficiency>
<FuelTankFull>资源已满</FuelTankFull>
<CurrentFuel>当前储存的资源</CurrentFuel>
<AcidDamageProgress>下次造成猎物损伤的进度</AcidDamageProgress>
<RefuelingVatIdle>建筑闲置 - 放入非虫族殖民者、俘虏和囚犯以生产燃料</RefuelingVatIdle>
<RefuelingStopped>生产已停止</RefuelingStopped>
<InsertPersonRefuelingVatDesc>选择一名殖民者、囚犯或奴隶,将其安置在提取腔中,他们会缓慢地受到伤害以产出资源。</InsertPersonRefuelingVatDesc>
<AssignCarryPrisoner>为囚犯/奴隶分配运送者</AssignCarryPrisoner>
<AssignCarryPrisonerDesc>选择一个虫群成员将囚犯或奴隶带到阿拉克涅建筑中</AssignCarryPrisonerDesc>
<NoAvailableHiveCarriers>没有可用的虫群成员来携带囚犯</NoAvailableHiveCarriers>
<CarrierAssigned>已指派{0}将{1}运送到活体建筑</CarrierAssigned>
<NoAvailableCarriers>没有可用的虫群成员运送者</NoAvailableCarriers>
<NoPrisonersOrSlaves>没有可用的囚犯或奴隶</NoPrisonersOrSlaves>
<!-- 研究生产系统翻译 -->
<StartResearchProduction>孵化{0}的蓝图</StartResearchProduction>
<ProducingTechprint>正在生成蓝图:{0}</ProducingTechprint>
<TechprintsToProduce>待生产的蓝图</TechprintsToProduce>
<ResearchAlreadyCompleted>该研究已完成</ResearchAlreadyCompleted>
<ARA_TechprintCount>产出 {0} 蓝图</ARA_TechprintCount>
<ARA_NeedSpecificArachnaeToStartResearchProduction>需要{0}才能开始研究生产</ARA_NeedSpecificArachnaeToStartResearchProduction>
<researchProjectsAvailable>可用的研究项目</researchProjectsAvailable>
<ARA_TechprintProductionComplete>生产完成:{0}个{1}{2}研究所需)</ARA_TechprintProductionComplete>
</LanguageData>

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1,18 +1,14 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"WorkspaceRootPath": "E:\\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\\thing_comps\\ara_compextraincubationinfo\\compextraincubationinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing_comps\\ara_compextraincubationinfo\\compextraincubationinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_compinteractiveproducer\\compinteractiveproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_compinteractiveproducer\\compinteractiveproducer.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\\thing_comps\\ara_compextraincubationinfo\\compproperties_extraincubationinfo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing_comps\\ara_compextraincubationinfo\\compproperties_extraincubationinfo.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\\building_comps\\ara_buildingterrainspawn\\compdelayedterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_buildingterrainspawn\\compdelayedterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_compinteractiveproducer\\compresearchproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_compinteractiveproducer\\compresearchproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@@ -22,48 +18,37 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 2,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "CompProperties_ExtraIncubationInfo.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_CompExtraIncubationInfo\\CompProperties_ExtraIncubationInfo.cs",
"RelativeDocumentMoniker": "Thing_Comps\\ARA_CompExtraIncubationInfo\\CompProperties_ExtraIncubationInfo.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_CompExtraIncubationInfo\\CompProperties_ExtraIncubationInfo.cs",
"RelativeToolTip": "Thing_Comps\\ARA_CompExtraIncubationInfo\\CompProperties_ExtraIncubationInfo.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-13T03:27:00.382Z"
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "CompExtraIncubationInfo.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_CompExtraIncubationInfo\\CompExtraIncubationInfo.cs",
"RelativeDocumentMoniker": "Thing_Comps\\ARA_CompExtraIncubationInfo\\CompExtraIncubationInfo.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_CompExtraIncubationInfo\\CompExtraIncubationInfo.cs",
"RelativeToolTip": "Thing_Comps\\ARA_CompExtraIncubationInfo\\CompExtraIncubationInfo.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAA==",
"Title": "CompInteractiveProducer.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompInteractiveProducer.cs",
"ViewState": "AgIAAEMBAAAAAAAAAAAswIQBAABUAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-13T03:26:37.426Z",
"WhenOpened": "2025-10-14T17:41:44.207Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "CompDelayedTerrainSpawn.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeToolTip": "Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ViewState": "AgIAAA4AAAAAAAAAAAAAwD0AAAAhAAAAAAAAAA==",
"DocumentIndex": 1,
"Title": "CompResearchProducer.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ViewState": "AgIAACkBAAAAAAAAAAAQwFYBAAApAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-12T15:30:31.391Z"
"WhenOpened": "2025-10-14T17:02:58.556Z",
"EditorCaption": ""
}
]
}

View File

@@ -100,6 +100,11 @@
<Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompAbilityEffect_AbilityShowSpawnablePawns.cs" />
<Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompProperties_AbilityShowSpawnablePawns.cs" />
<Compile Include="Buildings\Building_TurretGunHasSpeed.cs" />
<Compile Include="Building_Comps\ARA_Building_RefuelingVat\Building_RefuelingVat.cs" />
<Compile Include="Building_Comps\ARA_Building_RefuelingVat\CompProperties_RefuelingVat.cs" />
<Compile Include="Building_Comps\ARA_Building_RefuelingVat\CompRefuelingVat.cs" />
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\CompResearchProducer.cs" />
<Compile Include="Building_Comps\ARA_CompInteractiveProducer\JobDriver_StartResearchProduction.cs" />
<Compile Include="EventSystem\CompOpenCustomUI.cs" />
<Compile Include="EventSystem\Condition.cs" />
<Compile Include="EventSystem\DebugActions.cs" />
@@ -113,6 +118,7 @@
<Compile Include="EventSystem\EventVariableManager.cs" />
<Compile Include="EventSystem\Letter_EventChoice.cs" />
<Compile Include="EventSystem\QuestNode_Root_EventLetter.cs" />
<Compile Include="Jobs\JobDriver_CarryPrisonerToRefuelingVat.cs" />
<Compile Include="Verbs\Verb_ShootWithOffset.cs" />
<Compile Include="Abilities\ARA_ShowTemperatureRange\CompAbilityEffect_AbilityShowTemperatureRange.cs" />
<Compile Include="Abilities\ARA_ShowTemperatureRange\CompProperties_AbilityShowTemperatureRange.cs" />

View File

@@ -10,9 +10,11 @@ using Verse.AI;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public class Building_SacrificialFuelTank : Building_Enterable, IThingHolder, IThingHolderWithDrawnPawn
public class Building_RefuelingVat : Building_Enterable, IThingHolder, IThingHolderWithDrawnPawn
{
private CompRefuelable refuelableComp;
private CompRefuelable cachedRefuelableComp;
private CompRefuelingVat cachedRefuelingVatComp;
private CompAutoEjector cachedAutoEjectorComp;
private Graphic cachedTopGraphic;
// IThingHolderWithDrawnPawn implementation
@@ -20,10 +22,9 @@ namespace ArachnaeSwarm
public float HeldPawnBodyAngle => base.Rotation.AsAngle;
public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp;
// 燃料转换配置
private const float DAMAGE_TO_FUEL_RATIO = 0.1f; // 每点伤害转换为0.1燃料
private const float DAMAGE_INTERVAL_TICKS = 250; // 每250ticks造成一次伤害
private const float DAMAGE_PER_INTERVAL = 5f; // 每次间隔造成5点伤害
// 从 Comp 中获取属性
public float FuelProductionPerDay => RefuelingVatComp?.FuelProductionPerDay ?? 10f;
public float FuelProductionEfficiency => RefuelingVatComp?.FuelProductionEfficiency ?? 1f;
private Graphic TopGraphic
{
@@ -31,7 +32,7 @@ namespace ArachnaeSwarm
{
if (cachedTopGraphic == null)
{
var modExtension = def.GetModExtension<DefModExtension_SacrificialFuelTank>();
var modExtension = def.GetModExtension<DefModExtension_NutrientVat>();
if (modExtension != null && !modExtension.topGraphicPath.NullOrEmpty())
{
cachedTopGraphic = GraphicDatabase.Get(modExtension.graphicClass, modExtension.topGraphicPath, ShaderDatabase.Transparent, def.graphicData.drawSize, Color.white, Color.white);
@@ -41,77 +42,110 @@ namespace ArachnaeSwarm
}
}
public override Vector3 PawnDrawOffset => Vector3.zero;
public CompRefuelable RefuelableComp
{
get
{
if (refuelableComp == null)
if (cachedRefuelableComp == null)
{
refuelableComp = this.TryGetComp<CompRefuelable>();
cachedRefuelableComp = this.TryGetComp<CompRefuelable>();
}
return refuelableComp;
return cachedRefuelableComp;
}
}
public CompRefuelingVat RefuelingVatComp
{
get
{
if (cachedRefuelingVatComp == null)
{
cachedRefuelingVatComp = this.TryGetComp<CompRefuelingVat>();
}
return cachedRefuelingVatComp;
}
}
public override Vector3 PawnDrawOffset => Vector3.zero;
public CompAutoEjector AutoEjectorComp
{
get
{
if (cachedAutoEjectorComp == null)
{
cachedAutoEjectorComp = this.TryGetComp<CompAutoEjector>();
}
return cachedAutoEjectorComp;
}
}
public bool HasFuelCapacity => RefuelableComp != null && RefuelableComp.Fuel < RefuelableComp.Props.fuelCapacity;
public bool IsFuelFull => RefuelableComp != null && RefuelableComp.Fuel >= RefuelableComp.Props.fuelCapacity;
// 燃料生产速率每Tick
public float FuelProductionPerTick
{
get
{
if (selectedPawn != null && base.Working)
{
return (FuelProductionPerDay * FuelProductionEfficiency) / 60000f;
}
return 0f;
}
}
// 酸蚀伤害间隔每6000 tick约1/10天
private const int AcidDamageInterval = 6000;
private Dictionary<Pawn, int> pawnTickCounters = new Dictionary<Pawn, int>();
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
refuelableComp = this.TryGetComp<CompRefuelable>();
cachedRefuelableComp = this.TryGetComp<CompRefuelable>();
cachedRefuelingVatComp = this.TryGetComp<CompRefuelingVat>();
cachedAutoEjectorComp = this.TryGetComp<CompAutoEjector>();
}
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
if (mode != DestroyMode.WillReplace && selectedPawn != null && innerContainer.Contains(selectedPawn))
if (mode != DestroyMode.WillReplace)
{
Notify_PawnRemoved();
if (selectedPawn != null && innerContainer.Contains(selectedPawn))
{
Notify_PawnRemoved();
}
}
base.DeSpawn(mode);
}
// 造成伤害并转换为燃料
private void ApplySacrificialDamage(Pawn pawn)
private void ApplyAcidDamage(Pawn pawn)
{
try
{
if (pawn.Dead || pawn.Downed) return;
// 选择随机的身体部位
BodyPartRecord targetPart = GetRandomVulnerablePart(pawn);
if (targetPart == null) return;
// 造成伤害
DamageInfo damage = new DamageInfo(
DamageDefOf.Cut, // 使用切割伤害
DAMAGE_PER_INTERVAL,
0.5f, // 中等护甲穿透
-1f,
DamageDef acidDamageDef = DefDatabase<DamageDef>.GetNamed("AcidBurn") ?? DamageDefOf.Burn;
DamageInfo acidDamage = new DamageInfo(
acidDamageDef,
0.1f, // 每次0.1点伤害
2f, // 护甲穿透
-1f, // 随机角度
instigator: null,
hitPart: targetPart
);
float damageDealt = pawn.TakeDamage(damage).TotalDamageDealt;
// 将伤害转换为燃料
if (damageDealt > 0 && RefuelableComp != null)
{
float fuelToAdd = damageDealt * DAMAGE_TO_FUEL_RATIO;
RefuelableComp.Refuel(fuelToAdd);
}
// 如果pawn死亡停止处理
if (pawn.Dead)
{
OnPawnDied();
}
// 应用伤害
pawn.TakeDamage(acidDamage);
}
catch (Exception ex)
{
Log.Error($"Error applying sacrificial damage to {pawn}: {ex.Message}");
Log.Error($"Error applying acid damage to {pawn}: {ex.Message}");
}
}
private BodyPartRecord GetRandomVulnerablePart(Pawn pawn)
{
// 优先选择外部身体部位
@@ -121,11 +155,11 @@ namespace ArachnaeSwarm
part.def.hitPoints > 0)
.ToList();
return vulnerableParts.Count > 0 ? vulnerableParts.RandomElement() : pawn.RaceProps.body.corePart;
return vulnerableParts.Count > 0 ?
vulnerableParts.RandomElement() :
pawn.RaceProps.body.corePart;
}
private int damageTickCounter = 0;
protected override void Tick()
{
base.Tick();
@@ -136,39 +170,41 @@ namespace ArachnaeSwarm
return;
}
if (base.Working && selectedPawn != null && !selectedPawn.Dead)
if (base.Working && selectedPawn != null)
{
damageTickCounter++;
// 定期造成伤害
if (damageTickCounter >= DAMAGE_INTERVAL_TICKS)
// 酸蚀伤害逻辑
if (pawnTickCounters.TryGetValue(selectedPawn, out int tickCount))
{
ApplySacrificialDamage(selectedPawn);
damageTickCounter = 0;
tickCount++;
pawnTickCounters[selectedPawn] = tickCount;
if (tickCount >= AcidDamageInterval)
{
ApplyAcidDamage(selectedPawn);
pawnTickCounters[selectedPawn] = 0;
}
}
else
{
pawnTickCounters[selectedPawn] = 0;
}
// 检查pawn是否死亡
// 燃料生产逻辑
if (HasFuelCapacity)
{
float fuelToAdd = FuelProductionPerTick;
RefuelableComp.Refuel(fuelToAdd);
}
// 检查俘虏是否死亡
if (selectedPawn.Dead)
{
OnPawnDied();
Finish();
return;
}
}
}
private void OnPawnDied()
{
if (selectedPawn != null && innerContainer.Contains(selectedPawn))
{
// 弹出死亡的pawn
Notify_PawnRemoved();
innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _);
OnStop();
// 可以选择在这里添加一些效果,比如声音或信息
Messages.Message("SacrificialFuelTank_PawnDied".Translate(selectedPawn.LabelShort), this, MessageTypeDefOf.NeutralEvent);
}
}
public override AcceptanceReport CanAcceptPawn(Pawn pawn)
{
if (base.Working)
@@ -179,12 +215,7 @@ namespace ArachnaeSwarm
{
return "WaitingForPawn".Translate(selectedPawn.Named("PAWN"));
}
if (pawn.Dead || pawn.Downed)
{
return "PawnMustBeAlive".Translate();
}
// 禁止虫群成员
// 禁止置入虫群成员
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker))
@@ -192,11 +223,12 @@ namespace ArachnaeSwarm
return "PawnIsHiveMember".Translate(pawn.Named("PAWN"));
}
// 允许殖民者、囚犯和奴隶,但不能是任务寄宿者
// 允许殖民者、囚犯和奴隶
bool isColonist = pawn.IsColonist;
bool isPrisoner = pawn.IsPrisonerOfColony;
bool isSlave = pawn.IsSlaveOfColony;
// 允许殖民者、囚犯或奴隶,但不能是任务寄宿者
return (isColonist || isPrisoner || isSlave) && !pawn.IsQuestLodger();
}
@@ -212,7 +244,7 @@ namespace ArachnaeSwarm
if (innerContainer.TryAddOrTransfer(pawn))
{
startTick = Find.TickManager.TicksGame;
damageTickCounter = 0; // 重置伤害计数器
pawnTickCounters[pawn] = 0; // 初始化伤害计数器
}
if (deselected)
{
@@ -220,33 +252,50 @@ namespace ArachnaeSwarm
}
}
private void Finish()
{
if (selectedPawn != null && innerContainer.Contains(selectedPawn))
{
Notify_PawnRemoved();
innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _);
OnStop();
}
}
private void OnStop()
{
if (selectedPawn != null)
{
pawnTickCounters.Remove(selectedPawn);
}
selectedPawn = null;
startTick = -1;
damageTickCounter = 0;
}
private void Notify_PawnRemoved()
{
// 可以在这里添加音效
// 可以在这里添加音效
}
public override IEnumerable<Gizmo> GetGizmos()
{
// 原有的基础Gizmos
foreach (Gizmo gizmo in base.GetGizmos())
{
yield return gizmo;
}
if (!base.Working)
if (base.Working)
{
// 插入人员的操作
var insertCommand = new Command_Action
}
else
{
// 选择殖民者的操作
var command_Action = new Command_Action
{
defaultLabel = "InsertSacrificialPawn".Translate() + "...",
defaultDesc = "InsertSacrificialPawnDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Sacrifice"),
defaultLabel = "InsertPerson".Translate() + "...",
defaultDesc = "InsertPersonRefuelingVatDesc".Translate(),
icon = Building_GrowthVat.InsertPawnIcon.Texture,
action = () =>
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
@@ -266,19 +315,21 @@ namespace ArachnaeSwarm
};
if (!base.AnyAcceptablePawns)
{
insertCommand.Disable("NoViablePawns".Translate());
command_Action.Disable("NoViablePawns".Translate());
}
yield return insertCommand;
yield return command_Action;
// 指派搬运囚犯/奴隶的操作
var command_CarryPrisoner = new Command_Action
{
defaultLabel = "AssignCarryPrisoner".Translate() + "...",
defaultDesc = "AssignCarryPrisonerSacrificialDesc".Translate(),
defaultDesc = "AssignCarryPrisonerDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Attack"),
action = () =>
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
// 获取所有可接受的囚犯和奴隶
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
{
if (CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony))
@@ -291,6 +342,7 @@ namespace ArachnaeSwarm
));
}
}
if (!list.Any())
{
list.Add(new FloatMenuOption("NoPrisonersOrSlaves".Translate(), null));
@@ -299,6 +351,7 @@ namespace ArachnaeSwarm
}
};
// 检查是否有可用的囚犯/奴隶
bool hasPrisonersOrSlaves = base.Map.mapPawns.AllPawnsSpawned
.Any(p => CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony));
@@ -320,23 +373,43 @@ namespace ArachnaeSwarm
{
stringBuilder.AppendLineIfNotEmpty().Append("CasketContains".Translate().ToString() + ": " + selectedPawn.NameShortColored.Resolve());
// 显示燃料转换效率
if (RefuelableComp != null)
// 显示燃料生产信息
if (HasFuelCapacity)
{
stringBuilder.AppendLineIfNotEmpty().Append("FuelConversionRate".Translate() + ": " + (DAMAGE_TO_FUEL_RATIO * 100).ToString("F1") + "%");
stringBuilder.AppendLineIfNotEmpty().Append("CurrentFuel".Translate() + ": " + RefuelableComp.Fuel.ToString("F1") + " / " + RefuelableComp.Props.fuelCapacity.ToString("F1"));
stringBuilder.AppendLineIfNotEmpty().Append("FuelProduction".Translate() + ": " + FuelProductionPerDay.ToString("F1") + " per day");
stringBuilder.AppendLineIfNotEmpty().Append("ProductionEfficiency".Translate() + ": " + FuelProductionEfficiency.ToStringPercent());
// 显示当前燃料状态
if (RefuelableComp != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("CurrentFuel".Translate() + ": " + RefuelableComp.Fuel.ToString("F1") + " / " + RefuelableComp.Props.fuelCapacity);
}
}
else
{
stringBuilder.AppendLineIfNotEmpty().Append("FuelTankFull".Translate());
}
// 显示pawn的健康状态
if (selectedPawn.health.summaryHealth.SummaryHealthPercent < 1.0f)
// 显示酸蚀伤害信息
if (pawnTickCounters.TryGetValue(selectedPawn, out int tickCount))
{
stringBuilder.AppendLineIfNotEmpty().Append("PawnHealth".Translate() + ": " + selectedPawn.health.summaryHealth.SummaryHealthPercent.ToStringPercent());
float damageProgress = (float)tickCount / AcidDamageInterval;
stringBuilder.AppendLineIfNotEmpty().Append("AcidDamageProgress".Translate() + ": " + damageProgress.ToStringPercent());
}
}
else if (selectedPawn != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("WaitingForPawn".Translate(selectedPawn.Named("PAWN")).Resolve());
}
else
{
// 显示空闲状态信息
stringBuilder.AppendLineIfNotEmpty().Append("RefuelingVatIdle".Translate());
if (RefuelableComp != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("CurrentFuel".Translate() + ": " + RefuelableComp.Fuel.ToString("F1") + " / " + RefuelableComp.Props.fuelCapacity);
}
}
return stringBuilder.ToString();
}
@@ -355,7 +428,7 @@ namespace ArachnaeSwarm
AcceptanceReport acceptanceReport = CanAcceptPawn(selPawn);
if (acceptanceReport.Accepted)
{
yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("EnterSacrificialTank".Translate(this), () => SelectPawn(selPawn)), selPawn, this);
yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("EnterBuilding".Translate(this), () => SelectPawn(selPawn)), selPawn, this);
}
else if (!acceptanceReport.Reason.NullOrEmpty())
{
@@ -375,6 +448,7 @@ namespace ArachnaeSwarm
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
base.DrawAt(drawLoc, flip);
// 绘制顶部图形
if (TopGraphic != null)
{
TopGraphic.Draw(DrawPos + Altitudes.AltIncVect * 2f, base.Rotation, this);
@@ -387,11 +461,13 @@ namespace ArachnaeSwarm
return null;
if (!CanAcceptPawn(prisoner).Accepted)
return null;
JobDef carryJobDef = DefDatabase<JobDef>.GetNamed("ARA_CarryPrisonerToSacrificialTank");
// 创建搬运工作定义 - 使用新的 JobDef
JobDef carryJobDef = DefDatabase<JobDef>.GetNamed("ARA_CarryPrisonerToRefuelingVat");
if (carryJobDef == null)
{
Log.Error("ARA_CarryPrisonerToRefuelingVat JobDef not found!");
return null;
}
Job job = JobMaker.MakeJob(carryJobDef, prisoner, this);
job.count = 1;
return job;
@@ -401,10 +477,12 @@ namespace ArachnaeSwarm
{
foreach (Pawn pawn in base.Map.mapPawns.AllPawnsSpawned)
{
// 检查是否是虫群成员
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster))
{
// 检查是否能够工作且不是囚犯
if (pawn.workSettings != null && pawn.workSettings.WorkIsActive(WorkTypeDefOf.Hauling) &&
!pawn.Downed && !pawn.IsPrisoner && pawn.CanReach(this, PathEndMode.InteractionCell, Danger.Some))
{
@@ -418,15 +496,17 @@ namespace ArachnaeSwarm
{
if (prisoner == null)
return;
// 获取可用的搬运者
var availableCarriers = GetAvailableCarriers().ToList();
if (!availableCarriers.Any())
{
Messages.Message("NoAvailableHiveCarriers".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 创建浮动菜单选择搬运者
List<FloatMenuOption> options = new List<FloatMenuOption>();
foreach (Pawn carrier in availableCarriers)
{
options.Add(new FloatMenuOption(
@@ -444,7 +524,6 @@ namespace ArachnaeSwarm
Color.white
));
}
if (options.Any())
{
Find.WindowStack.Add(new FloatMenu(options));
@@ -454,5 +533,12 @@ namespace ArachnaeSwarm
Messages.Message("NoAvailableCarriers".Translate(), MessageTypeDefOf.RejectInput);
}
}
// 保存和加载数据
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref pawnTickCounters, "pawnTickCounters", LookMode.Reference, LookMode.Value);
}
}
}

View File

@@ -0,0 +1,16 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_RefuelingVat : CompProperties
{
public float fuelProductionPerDay = 10f;
public float fuelProductionEfficiency = 1f;
public CompProperties_RefuelingVat()
{
this.compClass = typeof(CompRefuelingVat);
}
}
}

View File

@@ -0,0 +1,20 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompRefuelingVat : ThingComp
{
public CompProperties_RefuelingVat Props => (CompProperties_RefuelingVat)props;
public float FuelProductionPerDay => Props.fuelProductionPerDay;
public float FuelProductionEfficiency => Props.fuelProductionEfficiency;
// 允许运行时修改效率(如果需要)
public void SetEfficiency(float newEfficiency)
{
// 如果需要运行时修改,可以在这里添加逻辑
// 注意:这会修改实例,不会影响 XML 定义
}
}
}

View File

@@ -319,7 +319,7 @@ namespace ArachnaeSwarm
yield return new FloatMenuOption(label, () =>
{
this._selectedProcess = process;
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StartInteractiveProduction"), parent);
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StartResearchProduction"), parent);
selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
});
}

View File

@@ -0,0 +1,482 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class CompProperties_ResearchProducer : CompProperties
{
public List<PawnKindDef> whitelist;
public bool destroyOnSpawn;
public float damagePerTickWhenUnfueled = 0.2f;
public float minNutritionToStart = 0.1f;
// 营养转换系数:研究点数 -> 营养
public float nutritionPerResearchPoint = 0.1f;
// 生产时间系数:研究点数 -> 生产时间ticks
public float productionTicksPerResearchPoint = 10f;
public CompProperties_ResearchProducer()
{
compClass = typeof(CompResearchProducer);
}
}
[StaticConstructorOnStartup]
public class CompResearchProducer : ThingComp
{
private ResearchProcessDef _selectedProcess;
private int productionUntilTick = -1;
private List<ResearchProcessDef> _cachedProcesses;
private int spawnTick = -1;
private const int COOLDOWN_TICKS = 120;
private CompRefuelableNutrition _fuelComp;
private static readonly Texture2D CancelIcon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
public bool InProduction => _selectedProcess != null;
public bool InCooldown => spawnTick > 0 && Find.TickManager.TicksGame < spawnTick + COOLDOWN_TICKS;
public CompProperties_ResearchProducer Props => (CompProperties_ResearchProducer)props;
// 生产进度0-1
public float ProductionProgress
{
get
{
if (!InProduction || productionUntilTick <= 0) return 0f;
int totalTicks = _selectedProcess.productionTicks;
int elapsedTicks = totalTicks - (productionUntilTick - Find.TickManager.TicksGame);
return Mathf.Clamp01((float)elapsedTicks / totalTicks);
}
}
// 自动生成的 ResearchProcessDef 列表
public List<ResearchProcessDef> Processes
{
get
{
if (_cachedProcesses == null)
{
BuildProcessList();
}
return _cachedProcesses;
}
}
private CompRefuelableNutrition FuelComp
{
get
{
if (_fuelComp == null) _fuelComp = parent.GetComp<CompRefuelableNutrition>();
return _fuelComp;
}
}
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
_fuelComp = parent.GetComp<CompRefuelableNutrition>();
BuildProcessList();
if (!respawningAfterLoad)
{
spawnTick = Find.TickManager.TicksGame;
}
}
public override void PostExposeData()
{
base.PostExposeData();
// 序列化 selectedProcess 的 researchDef
ResearchProjectDef selectedProcessResearchDef = _selectedProcess?.researchDef;
Scribe_Defs.Look(ref selectedProcessResearchDef, "selectedProcessResearchDef");
Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1);
Scribe_Values.Look(ref spawnTick, "spawnTick", -1);
// 加载时重建 selectedProcess
if (Scribe.mode == LoadSaveMode.LoadingVars && selectedProcessResearchDef != null)
{
if (_cachedProcesses == null)
{
BuildProcessList();
}
_selectedProcess = Processes.FirstOrDefault(p => p.researchDef == selectedProcessResearchDef);
if (_selectedProcess == null)
{
Log.Warning($"Could not find ResearchProcessDef for {selectedProcessResearchDef.defName} after loading. Resetting production.");
ResetProduction();
}
else if (productionUntilTick > 0)
{
if (Find.TickManager.TicksGame >= productionUntilTick)
{
Log.Warning($"Production time already passed for {selectedProcessResearchDef.defName}. Finishing immediately.");
FinishProduction();
}
else if (productionUntilTick - Find.TickManager.TicksGame > _selectedProcess.productionTicks * 10)
{
Log.Warning($"Abnormal production time detected for {selectedProcessResearchDef.defName}. Recalculating.");
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
}
}
}
}
// 扫描 ARA_ResearchTab 下所有需要 techprint 的研究项目
private void BuildProcessList()
{
_cachedProcesses = new List<ResearchProcessDef>();
// 获取 ARA_ResearchTab 的 ResearchTabDef
ResearchTabDef araResearchTab = DefDatabase<ResearchTabDef>.GetNamedSilentFail("ARA_ResearchTab");
if (araResearchTab == null)
{
Log.Warning("ARA_ResearchTab not found. No research processes will be available.");
return;
}
int totalScanned = 0;
int araTabCount = 0;
int techprintCount = 0;
int prerequisitesMetCount = 0;
// 扫描所有研究项目
foreach (ResearchProjectDef researchDef in DefDatabase<ResearchProjectDef>.AllDefs)
{
totalScanned++;
// 检查是否在 ARA_ResearchTab 下 - 使用 ResearchTabDef 比较
if (researchDef.tab == araResearchTab)
{
araTabCount++;
// 检查是否需要 techprint
if (researchDef.TechprintCount > 0)
{
techprintCount++;
// 检查前置条件是否满足
if (!ArePrerequisitesMet(researchDef))
{
continue; // 前置条件不满足,跳过这个研究项目
}
prerequisitesMetCount++;
// 根据命名规则构建 techprint 的 defName
string techprintDefName = "Techprint_" + researchDef.defName;
ThingDef techprintDef = DefDatabase<ThingDef>.GetNamedSilentFail(techprintDefName);
if (techprintDef != null)
{
// 计算营养消耗和生产时间
float nutritionCost = researchDef.baseCost * Props.nutritionPerResearchPoint;
int productionTicks = Mathf.RoundToInt(researchDef.baseCost * Props.productionTicksPerResearchPoint);
ResearchProcessDef process = new ResearchProcessDef
{
researchDef = researchDef,
techprintDef = techprintDef,
productionTicks = productionTicks,
totalNutritionNeeded = nutritionCost,
techprintCount = researchDef.TechprintCount
};
_cachedProcesses.Add(process);
}
else
{
Log.Warning($"Techprint ThingDef not found for research project {researchDef.defName}. Expected defName: {techprintDefName}");
}
}
}
}
// 按研究项目名称排序
_cachedProcesses.SortBy(p => p.researchDef.label);
// 记录详细的扫描结果
Log.Message($"Research production scanner: Scanned {totalScanned} research projects, " +
$"{araTabCount} in ARA_ResearchTab, " +
$"{techprintCount} require techprints, " +
$"{prerequisitesMetCount} have prerequisites met, " +
$"{_cachedProcesses.Count} available for production");
}
// 检查研究项目的前置条件是否满足
private bool ArePrerequisitesMet(ResearchProjectDef researchDef)
{
// 检查 prerequisites
if (researchDef.prerequisites != null)
{
foreach (var prerequisite in researchDef.prerequisites)
{
if (!prerequisite.IsFinished)
{
return false; // 有一个前置研究未完成
}
}
}
// 检查 hiddenPrerequisites
if (researchDef.hiddenPrerequisites != null)
{
foreach (var hiddenPrerequisite in researchDef.hiddenPrerequisites)
{
if (!hiddenPrerequisite.IsFinished)
{
return false; // 有一个隐藏前置研究未完成
}
}
}
return true; // 所有前置条件都满足
}
public override void CompTick()
{
base.CompTick();
if (InProduction && productionUntilTick > 0)
{
if (productionUntilTick <= 0)
{
Log.Error($"Invalid productionUntilTick: {productionUntilTick}. Resetting production.");
ResetProduction();
return;
}
if (FuelComp == null) return;
bool hasFuel = FuelComp.HasFuel;
// 营养归零时持续伤害建筑
if (!hasFuel)
{
parent.TakeDamage(new DamageInfo(DamageDefOf.Rotting, Props.damagePerTickWhenUnfueled));
return;
}
// 检查生产是否完成
if (productionUntilTick > 0 && Find.TickManager.TicksGame >= productionUntilTick)
{
FinishProduction();
}
}
}
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
{
if (InCooldown)
{
int remainingTicks = (spawnTick + COOLDOWN_TICKS) - Find.TickManager.TicksGame;
yield return new FloatMenuOption($"ARA_CocoonCooldown".Translate(remainingTicks.ToStringTicksToPeriod()), null);
yield break;
}
if (InProduction || !selPawn.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly)) yield break;
if (Props.whitelist != null && !Props.whitelist.Contains(selPawn.kindDef)) yield break;
if (FuelComp == null) yield break;
if (!FuelComp.HasFuel || FuelComp.NutritionStored < Props.minNutritionToStart)
{
yield return new FloatMenuOption("CannotStartProduction".Translate() + ": " + "NoFuel".Translate(), null);
yield break;
}
foreach (var process in Processes)
{
float nutritionCost = process.totalNutritionNeeded;
string label = "StartResearchProduction".Translate(process.researchDef.label) + " " +
"ARA_ProductionCost".Translate(nutritionCost.ToString("F0")) + " ->" +
"ARA_TechprintCount".Translate(process.techprintCount);
// 检查研究是否已经完成
if (process.researchDef.IsFinished)
{
yield return new FloatMenuOption(label + " (" + "ResearchAlreadyCompleted".Translate() + ")", null);
}
else
{
yield return new FloatMenuOption(label, () =>
{
this._selectedProcess = process;
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StartResearchProduction"), parent);
selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
});
}
}
}
public void StartProduction()
{
if (InCooldown)
{
Log.Warning("Attempted to start production during cooldown period.");
return;
}
if (_selectedProcess == null) return;
productionUntilTick = Find.TickManager.TicksGame + _selectedProcess.productionTicks;
float nutritionPerDay = (_selectedProcess.totalNutritionNeeded / _selectedProcess.productionTicks) * 60000f;
FuelComp.currentConsumptionRate = nutritionPerDay;
}
private void FinishProduction()
{
if (_selectedProcess == null)
{
Log.Warning("FinishProduction called but _selectedProcess is null. Resetting.");
ResetProduction();
return;
}
try
{
// 生成科技蓝图
Thing techprint = ThingMaker.MakeThing(_selectedProcess.techprintDef);
techprint.stackCount = _selectedProcess.techprintCount;
GenPlace.TryPlaceThing(techprint, parent.Position, parent.Map, ThingPlaceMode.Near);
// 添加消息提示
string messageText = "ARA_TechprintProductionComplete".Translate(
_selectedProcess.techprintCount,
_selectedProcess.techprintDef.label,
_selectedProcess.researchDef.label
);
Messages.Message(messageText, parent, MessageTypeDefOf.PositiveEvent);
if (Props.destroyOnSpawn)
{
parent.Destroy(DestroyMode.Vanish);
}
}
catch (System.Exception ex)
{
Log.Error($"Error in FinishProduction: {ex.Message}");
}
finally
{
ResetProduction();
}
}
private void ResetProduction()
{
if (FuelComp != null) FuelComp.currentConsumptionRate = 0f;
_selectedProcess = null;
productionUntilTick = -1;
}
// 进度条显示
private string GetProgressBar(float progress, int barLength = 20)
{
int filledLength = Mathf.RoundToInt(progress * barLength);
int emptyLength = barLength - filledLength;
StringBuilder bar = new StringBuilder();
bar.Append("[");
for (int i = 0; i < filledLength; i++) bar.Append("█");
for (int i = 0; i < emptyLength; i++) bar.Append("-");
bar.Append("]");
return bar.ToString();
}
public override string CompInspectStringExtra()
{
if (InCooldown)
{
int remainingTicks = (spawnTick + COOLDOWN_TICKS) - Find.TickManager.TicksGame;
return "ARA_CocoonCooldown".Translate(remainingTicks.ToStringTicksToPeriod());
}
if (InProduction)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("ProducingTechprint".Translate(this._selectedProcess.researchDef.label));
float progress = ProductionProgress;
int remainingTicks = productionUntilTick - Find.TickManager.TicksGame;
sb.AppendLine("Progress".Translate() + ": " + GetProgressBar(progress) + " " + progress.ToStringPercent("F0"));
sb.AppendLine("TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod());
sb.AppendLine("TechprintsToProduce".Translate() + ": " + _selectedProcess.techprintCount);
return sb.ToString().TrimEnd();
}
if (!InProduction)
{
int availableProcesses = Processes.Count(p => !p.researchDef.IsFinished);
string allowedRaces = "";
if (Props.whitelist != null && Props.whitelist.Count > 0)
{
var raceNames = Props.whitelist.Select(pkd => pkd.LabelCap).Distinct();
allowedRaces = string.Join(", ", raceNames);
}
else
{
allowedRaces = "ARA_AnyArachnaeRace".Translate();
}
return "ARA_NeedSpecificArachnaeToStartResearchProduction".Translate(allowedRaces) +
$" ({availableProcesses} " + "researchProjectsAvailable".Translate() + ")";
}
return null;
}
public override void PostDraw()
{
base.PostDraw();
if (InProduction)
{
Vector3 drawPos = parent.DrawPos;
drawPos.y += 0.15f;
float progress = ProductionProgress;
GenDraw.DrawFillableBar(new GenDraw.FillableBarRequest
{
center = drawPos,
size = new Vector2(1f, 0.15f),
fillPercent = progress,
filledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.green),
unfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(Color.gray),
margin = 0.1f,
rotation = Rot4.North
});
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
foreach (var g in base.CompGetGizmosExtra()) yield return g;
if (InCooldown) yield break;
if (InProduction)
{
yield return new Command_Action
{
defaultLabel = "CommandCancelProduction".Translate(),
icon = CancelIcon,
action = () => ResetProduction()
};
if (Prefs.DevMode)
{
yield return new Command_Action
{
defaultLabel = "Debug: Force Finish",
action = () => FinishProduction()
};
}
}
}
}
// 研究进程定义类
public class ResearchProcessDef
{
public ResearchProjectDef researchDef;
public ThingDef techprintDef;
public int productionTicks;
public float totalNutritionNeeded;
public int techprintCount;
}
}

View File

@@ -0,0 +1,46 @@
using System.Collections.Generic;
using RimWorld;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class JobDriver_StartResearchProduction : JobDriver
{
private const TargetIndex BuildingInd = TargetIndex.A;
protected Building Building => (Building)job.GetTarget(BuildingInd).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return pawn.Reserve(Building, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
{
// 检查目标建筑是否有效
this.FailOnDespawnedNullOrForbidden(BuildingInd);
this.FailOnBurningImmobile(BuildingInd);
// 第一步:走到建筑
yield return Toils_Goto.GotoThing(BuildingInd, PathEndMode.InteractionCell);
// 第二步:启动生产
Toil work = ToilMaker.MakeToil("MakeNewToils");
work.initAction = delegate
{
var comp = Building.GetComp<CompResearchProducer>();
if (comp != null)
{
comp.StartProduction();
}
else
{
Log.Error($"CompResearchProducer not found on {Building.Label}");
}
};
work.defaultCompleteMode = ToilCompleteMode.Instant;
yield return work;
}
}
}

View File

@@ -1,16 +0,0 @@
using System;
using Verse;
namespace ArachnaeSwarm
{
public class DefModExtension_SacrificialFuelTank : DefModExtension
{
public string topGraphicPath;
public Type graphicClass = typeof(Graphic_Multi);
// 可配置的伤害和燃料转换参数
public float damageToFuelRatio = 0.1f;
public int damageIntervalTicks = 250;
public float damagePerInterval = 5f;
}
}

View File

@@ -2,15 +2,16 @@ using System;
using System.Linq;
using RimWorld;
using Verse;
using UnityEngine;
namespace ArachnaeSwarm
{
// Properties for the new component
public class CompProperties_AutoEjector : CompProperties
{
public int checkInterval = 250; // Check roughly every 4 seconds
public float ejectAtPercent = 1.0f; // Eject when fuel reaches this percentage of max capacity (1.0 = 100%)
public Type targetComp = typeof(CompRefuelable); // The specific CompRefuelable class to target, can be overridden in XML
public int checkInterval = 250;
public float ejectAtPercent = 1.0f;
public Type targetComp = typeof(CompRefuelable);
public bool allowEjectedFuel = true; // 新增:控制弹出的燃料是否允许操作
public CompProperties_AutoEjector()
{
@@ -18,7 +19,6 @@ namespace ArachnaeSwarm
}
}
// The component logic
public class CompAutoEjector : ThingComp
{
private CompProperties_AutoEjector Props => (CompProperties_AutoEjector)this.props;
@@ -28,7 +28,6 @@ namespace ArachnaeSwarm
{
base.PostSpawnSetup(respawningAfterLoad);
// Find the specific refuelable component specified in XML
this.refuelableComp = this.parent.GetComps<CompRefuelable>()
.FirstOrDefault(comp => comp.GetType() == this.Props.targetComp);
@@ -42,17 +41,47 @@ namespace ArachnaeSwarm
{
base.CompTick();
// Check if we have a valid refuelable comp and it's time to check
if (this.refuelableComp != null &&
this.parent.IsHashIntervalTick(this.Props.checkInterval))
{
// Check if fuel has reached or exceeded the configured percentage of the MAX capacity
if (this.refuelableComp.FuelPercentOfMax >= this.Props.ejectAtPercent)
{
// Call the public EjectFuel() method.
this.refuelableComp.EjectFuel();
// 使用自定义的弹出方法
EjectFuelWithoutForbid();
}
}
}
/// <summary>
/// 自定义弹出燃料方法,弹出的物品允许操作
/// </summary>
private void EjectFuelWithoutForbid()
{
var props = refuelableComp.Props;
ThingDef thingDef = props.fuelFilter.AllowedThingDefs.First();
int num = Mathf.FloorToInt(refuelableComp.Fuel);
while (num > 0)
{
Thing thing = ThingMaker.MakeThing(thingDef);
thing.stackCount = Mathf.Min(num, thingDef.stackLimit);
num -= thing.stackCount;
// 放置物品
GenPlace.TryPlaceThing(thing, parent.Position, parent.Map, ThingPlaceMode.Near);
// 根据配置决定是否允许操作
if (Props.allowEjectedFuel)
{
thing.SetForbidden(false); // 允许操作
}
}
// 重置燃料并发送信号
typeof(CompRefuelable).GetField("fuel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
?.SetValue(refuelableComp, 0f);
parent.BroadcastCompSignal("RanOutOfFuel");
}
}
}
}

View File

@@ -0,0 +1,64 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class JobDriver_CarryPrisonerToRefuelingVat : JobDriver
{
private const TargetIndex PrisonerInd = TargetIndex.A;
private const TargetIndex VatInd = TargetIndex.B;
protected Pawn Prisoner => (Pawn)job.GetTarget(PrisonerInd).Thing;
protected Building_RefuelingVat Vat => (Building_RefuelingVat)job.GetTarget(VatInd).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return pawn.Reserve(Prisoner, job, 1, -1, null, errorOnFailed)
&& pawn.Reserve(Vat, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
{
// 验证目标
this.FailOnDestroyedOrNull(PrisonerInd);
this.FailOnDestroyedOrNull(VatInd);
this.FailOn(() => !Vat.CanAcceptPawn(Prisoner).Accepted);
// 1. 前往囚犯位置
yield return Toils_Goto.GotoThing(PrisonerInd, PathEndMode.OnCell)
.FailOn(() => Prisoner.IsInRefuelingVat())
.FailOnSomeonePhysicallyInteracting(PrisonerInd);
// 2. 开始搬运囚犯
yield return Toils_Haul.StartCarryThing(PrisonerInd);
// 3. 前往燃料转化罐
yield return Toils_Goto.GotoThing(VatInd, PathEndMode.InteractionCell);
// 4. 将囚犯放入燃料转化罐
yield return new Toil
{
initAction = () =>
{
if (Vat.CanAcceptPawn(Prisoner).Accepted)
{
Vat.TryAcceptPawn(Prisoner);
Messages.Message("PrisonerPlacedInRefuelingVat".Translate(Prisoner.LabelShort), MessageTypeDefOf.NeutralEvent);
}
},
defaultCompleteMode = ToilCompleteMode.Instant
};
}
}
// 扩展方法检查pawn是否在燃料转化罐中
public static class RefuelingVatPawnExtensions
{
public static bool IsInRefuelingVat(this Pawn pawn)
{
return pawn?.Spawned == false && pawn.ParentHolder is Building_RefuelingVat;
}
}
}

View File

@@ -11,4 +11,4 @@ namespace ArachnaeSwarm
// 公开属性,供其他组件读取
public List<ThingDef> CocoonDefs => Props.cocoonDefs;
}
}
}