1
This commit is contained in:
Binary file not shown.
@@ -312,7 +312,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_6VXI</requiredResearch>
|
||||
<failMessage>需要科技 节点VXI-6"酸囊" 以解锁技能</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -394,7 +393,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_5PAV</requiredResearch>
|
||||
<failMessage>需要科技 节点PAV-5"毒刺" 以解锁技能</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -440,7 +438,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_6VXI</requiredResearch>
|
||||
<failMessage>需要科技 节点VXI-6"酸囊" 以解锁技能</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -934,7 +931,7 @@
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
|
||||
<!-- 疗愈 -->
|
||||
<!-- 蜜罐 -->
|
||||
<AbilityDef>
|
||||
<defName>ARA_MimicNematode_Needle_Fire</defName>
|
||||
<label>拟线种寄生针</label>
|
||||
@@ -975,7 +972,6 @@
|
||||
</li> -->
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_2MED</requiredResearch>
|
||||
<failMessage>需要科技 节点MED-2"拟线寄生" 以解锁技能</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -993,6 +989,86 @@
|
||||
<speed>40</speed>
|
||||
</projectile>
|
||||
</ThingDef>
|
||||
<AbilityDef>
|
||||
<defName>ARA_FireSpew</defName>
|
||||
<label>爆燃火焰</label>
|
||||
<description>爆燃种经过短暂蓄力后,向前大范围地喷出火焰。这种火焰喷射距离不是太长,但是可以形成一道致密的火墙。</description>
|
||||
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_FireSpew</iconPath>
|
||||
<cooldownTicksRange>5000</cooldownTicksRange>
|
||||
<aiCanUse>true</aiCanUse>
|
||||
<ai_IsIncendiary>true</ai_IsIncendiary>
|
||||
<sendMessageOnCooldownComplete>true</sendMessageOnCooldownComplete>
|
||||
<warmupStartSound>FireSpew_Warmup</warmupStartSound>
|
||||
<charges>3</charges>
|
||||
<cooldownPerCharge>true</cooldownPerCharge>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<range>10</range>
|
||||
<warmupTime>1</warmupTime>
|
||||
<soundCast>FireSpew_Resolve</soundCast>
|
||||
<targetParams>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
|
||||
<customLabel>饮食</customLabel>
|
||||
<showProgressBar>true</showProgressBar>
|
||||
<needDef>Food</needDef>
|
||||
<needCost>0.25</needCost>
|
||||
<failMessage>营养值不足,需要进食</failMessage>
|
||||
</li>
|
||||
<li Class="CompProperties_AbilityFireSpew">
|
||||
<range>10</range>
|
||||
<lineWidthEnd>35</lineWidthEnd>
|
||||
<filthDef>Filth_FlammableBile</filthDef>
|
||||
<effecterDef>Fire_Spew</effecterDef>
|
||||
<canHitFilledCells>true</canHitFilledCells>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
<AbilityDef>
|
||||
<defName>ARA_Dissolver_Touch</defName>
|
||||
<label>溶脂强酸</label>
|
||||
<description>在极近的范围内向目标泼洒溶脂强酸,目标的器官会快速分解,变成大量的虫蜜。因为准头很差,无法用于战场上,只能对不反抗的目标使用。</description>
|
||||
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Fighter_Invisibility_jump</iconPath>
|
||||
<cooldownTicksRange>1000</cooldownTicksRange>
|
||||
<charges>3</charges>
|
||||
<cooldownPerCharge>true</cooldownPerCharge>
|
||||
<hostile>false</hostile>
|
||||
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
|
||||
<stunTargetWhileCasting>true</stunTargetWhileCasting>
|
||||
<aiCanUse>true</aiCanUse>
|
||||
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
|
||||
<jobDef>CastAbilityOnThingMelee</jobDef>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbilityTouch</verbClass>
|
||||
<violent>false</violent>
|
||||
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
|
||||
<warmupTime>0.5</warmupTime>
|
||||
<range>-1</range>
|
||||
<requireLineOfSight>false</requireLineOfSight>
|
||||
<soundCast>AcidSpray_Resolve</soundCast>
|
||||
<targetParams>
|
||||
<canTargetPawns>true</canTargetPawns>
|
||||
<onlyTargetColonistsOrPrisonersOrSlaves>true</onlyTargetColonistsOrPrisonersOrSlaves>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
|
||||
<customLabel>饮食</customLabel>
|
||||
<showProgressBar>true</showProgressBar>
|
||||
<needDef>Food</needDef>
|
||||
<needCost>0.1</needCost>
|
||||
<failMessage>营养值不足,需要进食</failMessage>
|
||||
</li>
|
||||
<li Class="CompProperties_AbilityGiveHediff">
|
||||
<compClass>CompAbilityEffect_GiveHediff</compClass>
|
||||
<hediffDef>ARA_Dissolver_Touch_Damage</hediffDef>
|
||||
<replaceExisting>true</replaceExisting>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
|
||||
<!-- 追猎 -->
|
||||
<AbilityDef>
|
||||
@@ -1066,46 +1142,6 @@
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
|
||||
<!-- 爆燃 -->
|
||||
<AbilityDef>
|
||||
<defName>ARA_FireSpew</defName>
|
||||
<label>爆燃火焰</label>
|
||||
<description>爆燃种经过短暂蓄力后,向前大范围地喷出火焰。这种火焰喷射距离不是太长,但是可以形成一道致密的火墙。</description>
|
||||
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_FireSpew</iconPath>
|
||||
<cooldownTicksRange>5000</cooldownTicksRange>
|
||||
<aiCanUse>true</aiCanUse>
|
||||
<ai_IsIncendiary>true</ai_IsIncendiary>
|
||||
<sendMessageOnCooldownComplete>true</sendMessageOnCooldownComplete>
|
||||
<warmupStartSound>FireSpew_Warmup</warmupStartSound>
|
||||
<charges>3</charges>
|
||||
<cooldownPerCharge>true</cooldownPerCharge>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<range>10</range>
|
||||
<warmupTime>1</warmupTime>
|
||||
<soundCast>FireSpew_Resolve</soundCast>
|
||||
<targetParams>
|
||||
<canTargetLocations>true</canTargetLocations>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
|
||||
<customLabel>饮食</customLabel>
|
||||
<showProgressBar>true</showProgressBar>
|
||||
<needDef>Food</needDef>
|
||||
<needCost>0.25</needCost>
|
||||
<failMessage>营养值不足,需要进食</failMessage>
|
||||
</li>
|
||||
<li Class="CompProperties_AbilityFireSpew">
|
||||
<range>10</range>
|
||||
<lineWidthEnd>35</lineWidthEnd>
|
||||
<filthDef>Filth_FlammableBile</filthDef>
|
||||
<effecterDef>Fire_Spew</effecterDef>
|
||||
<canHitFilledCells>true</canHitFilledCells>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
|
||||
<!-- 畸变 -->
|
||||
<AbilityDef>
|
||||
<defName>ARA_Genestealer_ExtractGene</defName>
|
||||
|
||||
@@ -55,12 +55,14 @@
|
||||
<abilityDefs>
|
||||
<li>ARA_Myrmecocystus_Production_Medicine</li>
|
||||
<li>ARA_Myrmecocystus_Production_Fuel</li>
|
||||
<li>ARA_Myrmecocystus_Production_Dissolver</li>
|
||||
</abilityDefs>
|
||||
</li>
|
||||
<li Class="HediffCompProperties_RemoveIfOtherHediff">
|
||||
<hediffs>
|
||||
<li>ARA_Myrmecocystus_Production_Medicine</li>
|
||||
<li>ARA_Myrmecocystus_Production_Fuel</li>
|
||||
<li>ARA_Myrmecocystus_Production_Dissolver</li>
|
||||
</hediffs>
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_ProductionQueue">
|
||||
@@ -118,7 +120,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_1MED</requiredResearch>
|
||||
<failMessage>需要科技 节点MED-1"疗愈种" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -172,7 +173,7 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
@@ -259,7 +260,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_8FEL</requiredResearch>
|
||||
<failMessage>需要科技 节点FEL-8"爆燃腔" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -314,7 +314,7 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
@@ -366,6 +366,100 @@
|
||||
</li>
|
||||
</comps>
|
||||
</HediffDef>
|
||||
<AbilityDef>
|
||||
<defName>ARA_Myrmecocystus_Production_Dissolver</defName>
|
||||
<label>蜜罐种转换——强酸分解</label>
|
||||
<description>使蜜罐种发生内驱性进化,使其获得额外的溶解能力,可以向非虫族囚犯、奴隶释放溶脂酸,这会持续使其损失身体部位以产生虫蜜。\n\n该进化方向不提供辅虫。</description>
|
||||
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Myrmecocystus_Production_Dissolver</iconPath>
|
||||
<cooldownTicksRange>1800</cooldownTicksRange>
|
||||
<hostile>false</hostile>
|
||||
<groupAbility>true</groupAbility>
|
||||
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
|
||||
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
|
||||
<aiCanUse>false</aiCanUse>
|
||||
<ai_IsOffensive>true</ai_IsOffensive>
|
||||
<targetRequired>false</targetRequired>
|
||||
<jobDef>CastAbilityOnThing</jobDef>
|
||||
<verbProperties>
|
||||
<verbClass>Verb_CastAbility</verbClass>
|
||||
<range>1</range>
|
||||
<warmupTime>12</warmupTime>
|
||||
<soundCast>AcidSpray_Resolve</soundCast>
|
||||
<violent>false</violent>
|
||||
<targetable>false</targetable>
|
||||
<targetParams>
|
||||
<canTargetSelf>True</canTargetSelf>
|
||||
</targetParams>
|
||||
</verbProperties>
|
||||
<comps>
|
||||
<li Class="CompProperties_AbilityGiveHediff">
|
||||
<compClass>CompAbilityEffect_GiveHediff</compClass>
|
||||
<hediffDef>ARA_Myrmecocystus_Production_Dissolver</hediffDef>
|
||||
<onlyApplyToSelf>True</onlyApplyToSelf>
|
||||
<replaceExisting>true</replaceExisting>
|
||||
<severity>1</severity>
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_7ACD_T</requiredResearch>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
<HediffDef>
|
||||
<defName>ARA_Myrmecocystus_Production_Dissolver</defName>
|
||||
<label>亚种-溶脂种</label>
|
||||
<description>这只阿拉克涅蜜罐种已经获得拔耀,可以通过在极近距离喷涂溶脂酸将可憎的敌人变成美味的食物。</description>
|
||||
<descriptionHyperlinks>
|
||||
<ThingDef>Chemfuel</ThingDef>
|
||||
</descriptionHyperlinks>
|
||||
<hediffClass>HediffWithComps</hediffClass>
|
||||
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
|
||||
<isBad>false</isBad>
|
||||
<scenarioCanAdd>false</scenarioCanAdd>
|
||||
<maxSeverity>1.0</maxSeverity>
|
||||
<renderNodeProperties>
|
||||
<li>
|
||||
<nodeClass>PawnRenderNode_AttachmentHead</nodeClass>
|
||||
<workerClass>PawnRenderNodeWorker_FlipWhenCrawling</workerClass>
|
||||
<texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Myrmecocystus_Addons_Dissolver</texPath>
|
||||
<parentTagDef>Body</parentTagDef>
|
||||
<useSkinShader>false</useSkinShader>
|
||||
<useRottenColor>false</useRottenColor>
|
||||
<rotDrawMode>Fresh, Rotting</rotDrawMode>
|
||||
<drawData>
|
||||
<dataNorth>
|
||||
<offset>(0, 0, -0.05)</offset>
|
||||
<layer>120</layer>
|
||||
</dataNorth>
|
||||
<dataEast>
|
||||
<offset>(0, 0, -0.05)</offset>
|
||||
</dataEast>
|
||||
<dataSouth>
|
||||
<offset>(0, 0, -0.05)</offset>
|
||||
</dataSouth>
|
||||
<dataWest>
|
||||
<offset>(0, 0, -0.05)</offset>
|
||||
</dataWest>
|
||||
<defaultData>
|
||||
<layer>-40</layer>
|
||||
</defaultData>
|
||||
</drawData>
|
||||
</li>
|
||||
</renderNodeProperties>
|
||||
<stages>
|
||||
<li>
|
||||
<enablesNeeds>
|
||||
<li>ARA_HoneyProduction</li>
|
||||
</enablesNeeds>
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="HediffCompProperties_GiveAbility">
|
||||
<abilityDefs>
|
||||
<li>ARA_Dissolver_Touch</li>
|
||||
</abilityDefs>
|
||||
</li>
|
||||
</comps>
|
||||
</HediffDef>
|
||||
|
||||
<!-- 战士种 -->
|
||||
<HediffDef>
|
||||
@@ -470,7 +564,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_4CLO</requiredResearch>
|
||||
<failMessage>需要科技 节点CLO-4"追猎种" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -555,7 +648,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_5STL</requiredResearch>
|
||||
<failMessage>需要科技 节点STL-5"基因窃取" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -692,7 +784,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_1BAC</requiredResearch>
|
||||
<failMessage>需要科技 节点BAC-1"育菌种" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -714,7 +805,7 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
@@ -796,7 +887,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_3CRP</requiredResearch>
|
||||
<failMessage>需要科技 节点CRP-3"菌毯铺设" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -994,7 +1084,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_1VTE</requiredResearch>
|
||||
<failMessage>需要科技 节点VTE-1"护卫者" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -1106,7 +1195,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_3CON</requiredResearch>
|
||||
<failMessage>需要科技 节点CON-3"建造者" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -1134,7 +1222,7 @@
|
||||
</li>
|
||||
</productionQueue>
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
@@ -1292,7 +1380,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_6LOD</requiredResearch>
|
||||
<failMessage>需要科技 节点LOD-6"巢之主" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -1415,7 +1502,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_9WID</requiredResearch>
|
||||
<failMessage>需要科技 节点WID-9"磁暴" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
@@ -1576,7 +1662,6 @@
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
|
||||
<requiredResearch>ARA_Technology_9NAV</requiredResearch>
|
||||
<failMessage>需要科技 节点NAV-9"领航使者" 以解锁进化</failMessage>
|
||||
</li>
|
||||
</comps>
|
||||
</AbilityDef>
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
</li>
|
||||
</renderNodeProperties>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
@@ -261,7 +261,7 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.MoharHediffs.HediffCompProperties_Spawner">
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
|
||||
@@ -633,4 +633,73 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<HediffDef>
|
||||
<defName>ARA_Dissolver_Touch_Damage</defName>
|
||||
<label>溶脂酸</label>
|
||||
<labelNoun>溶脂酸</labelNoun>
|
||||
<description>阿拉克涅溶脂种向这个目标喷洒了大量的溶脂酸,其身躯很快就会变成胶状的虫蜜。\n\n真可怜。</description>
|
||||
<descriptionHyperlinks>
|
||||
<ThingDef>ARA_InsectJelly</ThingDef>
|
||||
</descriptionHyperlinks>
|
||||
<defaultLabelColor>(1, 1, 0.8)</defaultLabelColor>
|
||||
<hediffClass>HediffWithComps</hediffClass>
|
||||
<stages>
|
||||
<li>
|
||||
<statOffsets>
|
||||
<PawnBeauty>-1</PawnBeauty>
|
||||
<MoveSpeed>-3</MoveSpeed>
|
||||
</statOffsets>
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_Spawner">
|
||||
<!--
|
||||
==================================================
|
||||
基础设置 (Basic Settings)
|
||||
==================================================
|
||||
-->
|
||||
<!-- [DEBUG] 如果为true,则为此组件启用详细的调试日志记录。 -->
|
||||
<debug>false</debug>
|
||||
<!-- 要生成的物品的ThingDef。 -->
|
||||
<thingToSpawn>ARA_InsectJelly</thingToSpawn>
|
||||
<!-- 每次生成的基础物品数量。 -->
|
||||
<spawnCount>30</spawnCount>
|
||||
<!--
|
||||
==================================================
|
||||
生成周期 (Spawning Interval)
|
||||
==================================================
|
||||
-->
|
||||
<!-- 下一次生成事件发生前的最少天数。 -->
|
||||
<minDaysB4Next>0.1</minDaysB4Next>
|
||||
<!-- 下一次生成事件发生前的最大天数。 -->
|
||||
<maxDaysB4Next>0.1</maxDaysB4Next>
|
||||
<randomGrace>0</randomGrace>
|
||||
<!--
|
||||
==================================================
|
||||
与年龄相关的调整 (Age-Related Adjustments)
|
||||
==================================================
|
||||
-->
|
||||
<!-- 如果为true,生成数量将根据宿主的年龄进行调整。 -->
|
||||
<ageWeightedQuantity>false</ageWeightedQuantity>
|
||||
<!-- 如果为true且ageWeightedQuantity为true,则随着宿主年龄增长,生成数量变多。 -->
|
||||
<olderBiggerQuantity>true</olderBiggerQuantity>
|
||||
<!-- 如果为true且ageWeightedQuantity为true,则随年龄增长的数量缩放将是指数性的而非线性的。 -->
|
||||
<exponentialQuantity>true</exponentialQuantity>
|
||||
<!-- 指数级数量缩放的最大乘数,以防止出现荒谬的数字。 -->
|
||||
<exponentialRatioLimit>20</exponentialRatioLimit>
|
||||
<!--
|
||||
==================================================
|
||||
生成条件 (Spawning Conditions)
|
||||
==================================================
|
||||
-->
|
||||
<!-- 如果为true,当宿主Pawn饥饿时,生成将暂停。 -->
|
||||
<hungerRelative>false</hungerRelative>
|
||||
<!-- 如果为true,当宿主Pawn受伤时,生成将暂停。 -->
|
||||
<healthRelative>false</healthRelative>
|
||||
|
||||
<destroyRandomBodyPart>true</destroyRandomBodyPart>
|
||||
</li>
|
||||
</comps>
|
||||
</HediffDef>
|
||||
</Defs>
|
||||
@@ -235,7 +235,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_6_Flaw_Hediffs</defName>
|
||||
<label>凝血障碍</label>
|
||||
@@ -250,7 +249,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_7_Flaw_Hediffs</defName>
|
||||
<label>骨质疏松</label>
|
||||
@@ -267,7 +265,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_8_Flaw_Hediffs</defName>
|
||||
<label>免疫缺陷</label>
|
||||
@@ -305,7 +302,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<!-- 行动激素 增强版 -->
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_Elite_AdaptiveArmor</defName>
|
||||
@@ -327,7 +323,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<!-- 强壮肌肉 增强版 -->
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_Elite_BerserkGlands</defName>
|
||||
@@ -346,7 +341,6 @@
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
<!-- 中枢强化 增强版 -->
|
||||
<HediffDef>
|
||||
<defName>ARA_Incubator_Elite_PsychicResonance</defName>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase">
|
||||
<defName>ARA_Base_Technology</defName>
|
||||
<label>基础基因序列获取</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n解锁虫群的基础科技,允许孵化基本的辅虫和武装器官。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n解锁虫群的基础科技,允许孵化基本的辅虫和武装器官。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>100</baseCost>
|
||||
<researchViewX>0.00</researchViewX>
|
||||
<researchViewY>3.20</researchViewY>
|
||||
@@ -39,7 +39,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_1WMT</defName>
|
||||
<label>节点WMT-1"突破"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>3000</baseCost>
|
||||
<researchViewX>4.50</researchViewX>
|
||||
<researchViewY>3.20</researchViewY>
|
||||
@@ -56,7 +56,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_2WMT</defName>
|
||||
<label>节点WMT-2"突破2"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种和工艺种进化到下一个阶段。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>7000</baseCost>
|
||||
<researchViewX>9.00</researchViewX>
|
||||
<researchViewY>3.20</researchViewY> <!-- ARA_MorphableResearchBench-->
|
||||
@@ -169,7 +169,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_1KYC</defName>
|
||||
<label>节点KYC-1"战士虫"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——战士种。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——战士种。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>150</baseCost>
|
||||
<researchViewX>3.00</researchViewX>
|
||||
<researchViewY>4.80</researchViewY>
|
||||
@@ -180,7 +180,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_4KYC</defName>
|
||||
<label>节点KYC-4"原虫"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——原虫种,一种可以寄生在别的种族身上以控制它们的特殊督虫。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——原虫种,一种可以寄生在别的种族身上以控制它们的特殊督虫。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>200</baseCost>
|
||||
<researchViewX>3.00</researchViewX>
|
||||
<researchViewY>4.30</researchViewY>
|
||||
@@ -191,7 +191,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_2KYC</defName>
|
||||
<label>节点KYC-2"飞行翼膜"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——空天种,敏捷而致命的精锐虫族,拥有以飞行姿态穿梭于战场的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——空天种,敏捷而致命的精锐虫族,拥有以飞行姿态穿梭于战场的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1600</baseCost>
|
||||
<researchViewX>5.50</researchViewX>
|
||||
<researchViewY>4.30</researchViewY>
|
||||
@@ -205,7 +205,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_5KYC</defName>
|
||||
<label>节点KYC-5"巨甲"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——迷雾种,一种拥有厚重甲壳的大型督虫,可以释放烟雾、阻燃剂和召唤虫族增援的信息素以协助虫群进行集群冲击。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——迷雾种,一种拥有厚重甲壳的大型督虫,可以释放烟雾、阻燃剂和召唤虫族增援的信息素以协助虫群进行集群冲击。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>800</baseCost>
|
||||
<researchViewX>5.50</researchViewX>
|
||||
<researchViewY>4.80</researchViewY>
|
||||
@@ -219,7 +219,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_6KYC</defName>
|
||||
<label>节点KYC-6"灵脑"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——织域种,一种寿命长且拥有强大灵能的特殊虫族,不仅能协助虫群的科研工作,也是一个强大的施法者。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——织域种,一种寿命长且拥有强大灵能的特殊虫族,不仅能协助虫群的科研工作,也是一个强大的施法者。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>800</baseCost>
|
||||
<researchViewX>6.50</researchViewX>
|
||||
<researchViewY>2.70</researchViewY>
|
||||
@@ -233,7 +233,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_7KYC</defName>
|
||||
<label>节点KYC-7"亲卫"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——禁卫种,一种寿命较其他虫族更长的精锐虫族,拥有优秀的远程作战能力和社交能力,同时也可以作为指挥官指挥虫群。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——禁卫种,一种寿命较其他虫族更长的精锐虫族,拥有优秀的远程作战能力和社交能力,同时也可以作为指挥官指挥虫群。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>2800</baseCost>
|
||||
<researchViewX>10.00</researchViewX>
|
||||
<researchViewY>3.80</researchViewY>
|
||||
@@ -247,7 +247,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_6MEN</defName>
|
||||
<label>节点MEN-6"拟线"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——拟线体,一种出生时躯体便已经被阿拉克涅拟线种寄生的虫族,便宜廉价并且可以快速得到的炮灰,倒是没什么纪律性就是了。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的虫族——拟线体,一种出生时躯体便已经被阿拉克涅拟线种寄生的虫族,便宜廉价并且可以快速得到的炮灰,倒是没什么纪律性就是了。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1800</baseCost>
|
||||
<researchViewX>7.50</researchViewX>
|
||||
<researchViewY>2.10</researchViewY>
|
||||
@@ -572,7 +572,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_5STL</defName>
|
||||
<label>节点STL-5"基因窃取"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许战士种进行定向进化,抛弃其战斗技能以换取其从殖民者、囚犯和奴隶身上抽取和注入基因的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许战士种进行定向进化,抛弃其战斗技能以换取其从殖民者、囚犯和奴隶身上抽取和注入基因的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>500</baseCost>
|
||||
<researchViewX>4.00</researchViewX>
|
||||
<researchViewY>4.80</researchViewY>
|
||||
@@ -583,7 +583,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_1VTE</defName>
|
||||
<label>节点VTE-1"护卫者"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许盾头种进行定向进化,抛弃其产出甲壳素和建造建筑的能力以换取战斗能力、移动能力和冲撞攻击的技能。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许盾头种进行定向进化,抛弃其产出甲壳素和建造建筑的能力以换取战斗能力、移动能力和冲撞攻击的技能。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1200</baseCost>
|
||||
<researchViewX>6.50</researchViewX>
|
||||
<researchViewY>4.80</researchViewY>
|
||||
@@ -597,7 +597,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_1MED</defName>
|
||||
<label>节点MED-1"疗愈种"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许蜜罐种进行定向进化,抛弃生产虫蜜的能力,以强化其自身的医疗能力并定期产出药物。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许蜜罐种进行定向进化,抛弃生产虫蜜的能力,以强化其自身的医疗能力并定期产出药物。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1200</baseCost>
|
||||
<researchViewX>5.50</researchViewX>
|
||||
<researchViewY>2.10</researchViewY>
|
||||
@@ -608,7 +608,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_4CLO</defName>
|
||||
<label>节点CLO-4"追猎种"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许战士种进行定向进化,牺牲其使用远程武器的能力以换取强大的近战和永久隐身的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许战士种进行定向进化,牺牲其使用远程武器的能力以换取强大的近战和永久隐身的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1800</baseCost>
|
||||
<researchViewX>5.50</researchViewX>
|
||||
<researchViewY>5.30</researchViewY>
|
||||
@@ -622,7 +622,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_1BAC</defName>
|
||||
<label>节点BAC-1"育菌种"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许迷雾种进行定向进化,牺牲其护甲和喷射信息素的能力以换成生产虫群所需高级资源"活化钜菌"的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许迷雾种进行定向进化,牺牲其护甲和喷射信息素的能力以换成生产虫群所需高级资源"活化钜菌"的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1000</baseCost>
|
||||
<researchViewX>7.50</researchViewX>
|
||||
<researchViewY>3.80</researchViewY>
|
||||
@@ -634,7 +634,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_9WID</defName>
|
||||
<label>节点WID-9"磁暴"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量磁暴种的能力,这种虫群可以以自杀性攻击的方式释放EMP以对抗机械族。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量磁暴种的能力,这种虫群可以以自杀性攻击的方式释放EMP以对抗机械族。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1500</baseCost>
|
||||
<researchViewX>7.50</researchViewX>
|
||||
<researchViewY>1.50</researchViewY> <!-- ARA_MorphableResearchBench-->
|
||||
@@ -648,7 +648,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_6LOD</defName>
|
||||
<label>节点LOD-6"巢之主"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量天巢种的能力,这种飞行辅虫速度很快,并且在近战中很难缠。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许空天种进行定向进化,以牺牲高速和高空机动的能力换取向敌人投射大量天巢种的能力,这种飞行辅虫速度很快,并且在近战中很难缠。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>3500</baseCost>
|
||||
<researchViewX>10.00</researchViewX>
|
||||
<researchViewY>5.30</researchViewY> <!-- ARA_MorphableResearchBench-->
|
||||
@@ -662,7 +662,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_3CON</defName>
|
||||
<label>节点CON-3"建造者"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许盾头种进行定向进化,抛弃其防御能力以换取更强大的甲壳素产出能力和建造建筑的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许盾头种进行定向进化,抛弃其防御能力以换取更强大的甲壳素产出能力和建造建筑的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>300</baseCost>
|
||||
<researchViewX>2.00</researchViewX>
|
||||
<researchViewY>2.70</researchViewY>
|
||||
@@ -673,7 +673,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_8FEL</defName>
|
||||
<label>节点FEL-8"爆燃腔"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许蜜罐种进行定向进化,抛弃生产虫蜜的能力,以获得防御力增强、生产化合燃料和喷射火焰的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许蜜罐种进行定向进化,抛弃生产虫蜜的能力,以获得防御力增强、生产化合燃料和喷射火焰的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>300</baseCost>
|
||||
<researchViewX>2.00</researchViewX>
|
||||
<researchViewY>2.10</researchViewY>
|
||||
@@ -684,7 +684,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_3CRP</defName>
|
||||
<label>节点CRP-3"菌毯铺设"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许迷雾种进行定向进化,抛弃喷射信息素的能力,以获得防御力、移动速度的增强和大规模铺设菌毯的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许迷雾种进行定向进化,抛弃喷射信息素的能力,以获得防御力、移动速度的增强和大规模铺设菌毯的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>1300</baseCost>
|
||||
<researchViewX>7.50</researchViewX>
|
||||
<researchViewY>0.90</researchViewY>
|
||||
@@ -698,7 +698,7 @@
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_9NAV</defName>
|
||||
<label>节点NAV-9"领航使者"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许禁卫种进行定向进化,抛弃直接战斗能力和指挥地面虫群部队的能力,换取指挥空中兽虫群的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许禁卫种进行定向进化,抛弃直接战斗能力和指挥地面虫群部队的能力,换取指挥空中兽虫群的能力。\n\n阿拉克涅虫群所有需要蓝图的科技,都需要使用其触须分支特有的研究方式完成研究。</description>
|
||||
<baseCost>3500</baseCost>
|
||||
<researchViewX>11.00</researchViewX>
|
||||
<researchViewY>3.80</researchViewY>
|
||||
@@ -846,20 +846,6 @@
|
||||
</prerequisites>
|
||||
</ResearchProjectDef>
|
||||
<!-- 兽虫发展 -->
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_8SLA</defName>
|
||||
<label>节点SLA-8"暴戮之兽"</label>
|
||||
<description><color=#887E78><i>阿拉克涅虫群-主巢触须\n主巢触须的进化路径是包含于每一支虫群中的通用进化路径,它们奠定了虫群在生物学上的优越性。</i></color>\n\n允许女皇种孵化新的兽虫——暴屠种。\n\n阿拉克涅虫群所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<baseCost>3000</baseCost>
|
||||
<researchViewX>10.00</researchViewX>
|
||||
<researchViewY>5.80</researchViewY>
|
||||
<hiddenPrerequisites>
|
||||
<li>ARA_Technology_2HAG</li>
|
||||
</hiddenPrerequisites>
|
||||
<prerequisites>
|
||||
<li>ARA_Technology_2WMT</li>
|
||||
</prerequisites>
|
||||
</ResearchProjectDef>
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_4COV</defName>
|
||||
<label>节点COV-4"天巫兽群"</label>
|
||||
|
||||
@@ -9,4 +9,33 @@
|
||||
<researchViewX>16.00</researchViewX>
|
||||
<researchViewY>3.20</researchViewY>
|
||||
</ResearchProjectDef>
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_8SLA</defName>
|
||||
<label>节点SLA-8"暴戮之兽"</label>
|
||||
<description><color=#915A30><i>阿拉克涅虫群-泰坦触须\n泰坦触须是阿拉克涅虫群的主力军团,包含阿拉克涅虫群中最坚韧、最具有适应力的族群,承担在战场上维持战线的任务。这个分支下的虫群拥有均衡的攻防能力,擅长以硬碰硬的模式消灭对手。</i></color>\n\n允许女皇种孵化新的兽虫——暴屠种。\n\n阿拉克涅虫群 泰坦触须所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<baseCost>3000</baseCost>
|
||||
<researchViewX>10.00</researchViewX>
|
||||
<researchViewY>5.80</researchViewY>
|
||||
<hiddenPrerequisites>
|
||||
<li>ARA_Technology_2HAG</li>
|
||||
<li>ARA_Technology_2WMT</li>
|
||||
</hiddenPrerequisites>
|
||||
<prerequisites>
|
||||
<li>ARA_Titan_Base_Technology</li>
|
||||
</prerequisites>
|
||||
</ResearchProjectDef>
|
||||
<ResearchProjectDef ParentName="ARA_techBase_Needtechprint">
|
||||
<defName>ARA_Technology_7ACD_T</defName>
|
||||
<label>节点ACD-7"溶脂强酸"</label>
|
||||
<description><color=#915A30><i>阿拉克涅虫群-泰坦触须\n泰坦触须是阿拉克涅虫群的主力军团,包含阿拉克涅虫群中最坚韧、最具有适应力的族群,承担在战场上维持战线的任务。这个分支下的虫群拥有均衡的攻防能力,擅长以硬碰硬的模式消灭对手。</i></color>\n\n允许蜜罐种进行定向进化,抛弃孵化辅虫的能力,换取溶解囚犯和俘虏以快速换取虫蜜的溶脂强酸。\n\n阿拉克涅虫群 泰坦触须所有需要蓝图的科技,其研究只能通过基因试验卵进行。</description>
|
||||
<baseCost>500</baseCost>
|
||||
<researchViewX>10.00</researchViewX>
|
||||
<researchViewY>5.80</researchViewY>
|
||||
<hiddenPrerequisites>
|
||||
<li>ARA_Technology_7VXI</li>
|
||||
</hiddenPrerequisites>
|
||||
<prerequisites>
|
||||
<li>ARA_Titan_Base_Technology</li>
|
||||
</prerequisites>
|
||||
</ResearchProjectDef>
|
||||
</Defs>
|
||||
@@ -156,4 +156,9 @@
|
||||
<!-- 错误消息 -->
|
||||
<ARA_SwarmSpell_NoLoadToDump>{0} 没有可转储的神经束负荷</ARA_SwarmSpell_NoLoadToDump>
|
||||
<ARA_SwarmSpell_EntropyTransferFailed>无法向 {0} 转储神经束负荷</ARA_SwarmSpell_EntropyTransferFailed>
|
||||
|
||||
<ARA_BlacklistedHediff_Blocked>{0} 无法被选为目标</ARA_BlacklistedHediff_Blocked>
|
||||
<CannotTargetPawnWithBlacklistedHediff>目标不能被此技能影响</CannotTargetPawnWithBlacklistedHediff>
|
||||
|
||||
<ARA_AbilityRequiresTech>需要科技 {0} 以解锁进化</ARA_AbilityRequiresTech>
|
||||
</LanguageData>
|
||||
@@ -37,12 +37,7 @@
|
||||
<packageId>erdelf.HumanoidAlienRaces</packageId>
|
||||
<displayName>Humanoid Alien Races 2.0</displayName>
|
||||
<steamWorkshopUrl>https://steamcommunity.com/sharedfiles/filedetails/?id=839005762</steamWorkshopUrl>
|
||||
</li>
|
||||
<li>
|
||||
<packageId>Nals.FacialAnimation</packageId>
|
||||
<displayName>[NL] Facial Animation - WIP</displayName>
|
||||
<steamWorkshopUrl>https://steamcommunity.com/sharedfiles/filedetails/?id=1635901197</steamWorkshopUrl>
|
||||
</li>
|
||||
</li>
|
||||
</modDependencies>
|
||||
|
||||
<loadAfter>
|
||||
|
||||
Binary file not shown.
@@ -2,6 +2,26 @@
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\compabilityeffect_researchprereq.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\compabilityeffect_researchprereq.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_spawner\\hediffcompproperties_spawner.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_spawner\\hediffcompproperties_spawner.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_spawner\\hediffcomp_spawner.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_spawner\\hediffcomp_spawner.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\\hediffs\\ara_gestaltnode\\hediffcomp_gestaltnode.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_gestaltnode\\hediffcomp_gestaltnode.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
@@ -66,15 +86,80 @@
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 2,
|
||||
"SelectedChildIndex": 0,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "CompAbilityEffect_ResearchPrereq.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_ResearchPrereq.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\CompAbilityEffect_ResearchPrereq.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_ResearchPrereq.cs",
|
||||
"RelativeToolTip": "Abilities\\CompAbilityEffect_ResearchPrereq.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAABBAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T07:44:51.729Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"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": "AgIAAAAAAAAAAAAAAAAAAAwAAAARAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T07:21:19.792Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"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": "AgIAAAAAAAAAAAAAAAAAAAoAAAArAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T07:19:42.058Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "HediffCompProperties_Spawner.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_Spawner\\HediffCompProperties_Spawner.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_Spawner\\HediffCompProperties_Spawner.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_Spawner\\HediffCompProperties_Spawner.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_Spawner\\HediffCompProperties_Spawner.cs",
|
||||
"ViewState": "AgIAAFcAAAAAAAAAAADgv3gAAAApAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T07:09:01.203Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "HediffComp_Spawner.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_Spawner\\HediffComp_Spawner.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_Spawner\\HediffComp_Spawner.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_Spawner\\HediffComp_Spawner.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_Spawner\\HediffComp_Spawner.cs",
|
||||
"ViewState": "AgIAAFwAAAAAAAAAAAAvwHEAAAAoAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T07:08:13.475Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"Title": "CompNodeSwarmLifetime.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
|
||||
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_NodeSwarmLifetime\\CompNodeSwarmLifetime.cs",
|
||||
@@ -86,20 +171,20 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"DocumentIndex": 5,
|
||||
"Title": "HediffComp_GestaltNode.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA4AAAAnAAAAAAAAAA==",
|
||||
"ViewState": "AgIAABMAAAAAAAAAAAAAwBUAAAAVAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-02-14T02:36:39.249Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"DocumentIndex": 9,
|
||||
"Title": "ARA_DefOf.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs",
|
||||
"RelativeDocumentMoniker": "ARA_DefOf.cs",
|
||||
@@ -111,7 +196,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"DocumentIndex": 10,
|
||||
"Title": "JobDriver_CastAbilityMaintainMultiProjectile.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_LaunchMultiProjectile\\JobDriver_CastAbilityMaintainMultiProjectile.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_LaunchMultiProjectile\\JobDriver_CastAbilityMaintainMultiProjectile.cs",
|
||||
@@ -123,7 +208,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"DocumentIndex": 7,
|
||||
"Title": "CompProperties_AbilityLaunchMultiProjectile.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_LaunchMultiProjectile\\CompProperties_AbilityLaunchMultiProjectile.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_LaunchMultiProjectile\\CompProperties_AbilityLaunchMultiProjectile.cs",
|
||||
@@ -135,7 +220,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"DocumentIndex": 11,
|
||||
"Title": "CompAbilityEffect_Transform.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Morphable\\CompAbilityEffect_Transform.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_Morphable\\CompAbilityEffect_Transform.cs",
|
||||
@@ -147,7 +232,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"DocumentIndex": 8,
|
||||
"Title": "CompAbilityEffect_LaunchMultiProjectile.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_LaunchMultiProjectile\\CompAbilityEffect_LaunchMultiProjectile.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_LaunchMultiProjectile\\CompAbilityEffect_LaunchMultiProjectile.cs",
|
||||
@@ -159,7 +244,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"DocumentIndex": 13,
|
||||
"Title": "CompProperties_AbilityPsychicLoadCost.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs",
|
||||
@@ -171,7 +256,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 9,
|
||||
"DocumentIndex": 14,
|
||||
"Title": "Gizmo_PawnResearchProgress.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_PawnResearchBlueprintReader\\Gizmo_PawnResearchProgress.cs",
|
||||
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_PawnResearchBlueprintReader\\Gizmo_PawnResearchProgress.cs",
|
||||
@@ -183,7 +268,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 7,
|
||||
"DocumentIndex": 12,
|
||||
"Title": "CompAbilityEffect_PsychicLoadCost.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs",
|
||||
@@ -195,7 +280,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 12,
|
||||
"DocumentIndex": 17,
|
||||
"Title": "CompAbilityEffect_PsychicBrainburn.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs",
|
||||
@@ -207,7 +292,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 11,
|
||||
"DocumentIndex": 16,
|
||||
"Title": "Gizmo_ResearchProgress.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ResearchBlueprintReader\\Gizmo_ResearchProgress.cs",
|
||||
"RelativeDocumentMoniker": "Buildings\\Building_ResearchBlueprintReader\\Gizmo_ResearchProgress.cs",
|
||||
@@ -219,7 +304,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 13,
|
||||
"DocumentIndex": 18,
|
||||
"Title": "ResearchBlueprintData.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ResearchBlueprintReader\\ResearchBlueprintData.cs",
|
||||
"RelativeDocumentMoniker": "Buildings\\Building_ResearchBlueprintReader\\ResearchBlueprintData.cs",
|
||||
@@ -231,7 +316,7 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 10,
|
||||
"DocumentIndex": 15,
|
||||
"Title": "Comp_PawnResearchBlueprintReader.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_PawnResearchBlueprintReader\\Comp_PawnResearchBlueprintReader.cs",
|
||||
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_PawnResearchBlueprintReader\\Comp_PawnResearchBlueprintReader.cs",
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompAbilityEffect_HediffBlacklist : CompAbilityEffect
|
||||
{
|
||||
public new CompProperties_AbilityHediffBlacklist Props => (CompProperties_AbilityHediffBlacklist)props;
|
||||
|
||||
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
|
||||
// 如果不是Pawn,返回父类验证结果
|
||||
if (targetPawn == null)
|
||||
return base.Valid(target, throwMessages);
|
||||
|
||||
// 检查目标是否拥有黑名单中的任意一个Hediff
|
||||
if (HasBlacklistedHediff(targetPawn))
|
||||
{
|
||||
if (throwMessages)
|
||||
{
|
||||
Messages.Message(Props.blockedMessage.Translate(targetPawn.LabelShort),
|
||||
targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.Valid(target, throwMessages);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查目标Pawn是否拥有黑名单中的任意一个Hediff
|
||||
/// </summary>
|
||||
private bool HasBlacklistedHediff(Pawn pawn)
|
||||
{
|
||||
if (pawn?.health?.hediffSet == null || Props.blacklistedHediffs.NullOrEmpty())
|
||||
return false;
|
||||
|
||||
foreach (HediffDef hediffDef in Props.blacklistedHediffs)
|
||||
{
|
||||
if (hediffDef != null && pawn.health.hediffSet.HasHediff(hediffDef))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在能力描述中显示黑名单信息
|
||||
/// </summary>
|
||||
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
if (targetPawn != null && HasBlacklistedHediff(targetPawn))
|
||||
{
|
||||
return "CannotTargetPawnWithBlacklistedHediff".Translate();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_AbilityHediffBlacklist : CompProperties_AbilityEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// 黑名单Hediff列表,拥有这些Hediff的Pawn无法成为目标
|
||||
/// </summary>
|
||||
public List<HediffDef> blacklistedHediffs;
|
||||
|
||||
/// <summary>
|
||||
/// 目标被阻止时显示的消息
|
||||
/// </summary>
|
||||
public string blockedMessage = "ARA_BlacklistedHediff_Blocked";
|
||||
|
||||
public CompProperties_AbilityHediffBlacklist()
|
||||
{
|
||||
this.compClass = typeof(CompAbilityEffect_HediffBlacklist);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace ArachnaeSwarm
|
||||
public class CompProperties_AbilityResearchPrereq : CompProperties_AbilityEffect
|
||||
{
|
||||
public ResearchProjectDef requiredResearch;
|
||||
public string failMessage = "Research not completed.";
|
||||
public string failMessage;
|
||||
|
||||
public CompProperties_AbilityResearchPrereq()
|
||||
{
|
||||
@@ -22,7 +22,7 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
if (Props.requiredResearch != null && !Props.requiredResearch.IsFinished)
|
||||
{
|
||||
reason = Props.failMessage;
|
||||
reason = Props.failMessage ?? "ARA_AbilityRequiresTech".Translate(Props.requiredResearch);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,11 +118,11 @@
|
||||
<Compile Include="Abilities\ARA_Morphable\CompMorphable.cs" />
|
||||
<Compile Include="Abilities\ARA_Morphable\CompProperties_AbilityTransform.cs" />
|
||||
<Compile Include="Abilities\ARA_Morphable\CompProperties_Morphable.cs" />
|
||||
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_BodyPartCheck.cs" />
|
||||
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_NeedCost.cs" />
|
||||
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_ResearchPrereq.cs" />
|
||||
<Compile Include="Abilities\ARA_QueenAbility\CompAbilityEffect_SprayLiquidMulti.cs" />
|
||||
<Compile Include="Abilities\ARA_QueenAbility\CompProperties_AbilitySprayLiquidMulti.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_BodyPartCheck.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_NeedCost.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_ResearchPrereq.cs" />
|
||||
<Compile Include="Abilities\ARA_SprayLiquidMulti\CompAbilityEffect_SprayLiquidMulti.cs" />
|
||||
<Compile Include="Abilities\ARA_SprayLiquidMulti\CompProperties_AbilitySprayLiquidMulti.cs" />
|
||||
<Compile Include="Abilities\ARA_ShowInteractiveThing\CompAbilityEffect_ShowInteractiveThing.cs" />
|
||||
<Compile Include="Abilities\ARA_ShowInteractiveThing\CompProperties_AbilityShowInteractiveThing.cs" />
|
||||
<Compile Include="Abilities\ARA_ShowSpawnablePawnsList\CompAbilityEffect_AbilityShowSpawnablePawns.cs" />
|
||||
@@ -134,12 +134,12 @@
|
||||
<Compile Include="Abilities\CompAbilityEffect_DRM_Deaddustpop.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_RandomHediff.cs" />
|
||||
<Compile Include="Abilities\CompAbilityEffect_TransformCorpse.cs" />
|
||||
<Compile Include="Abilities\PsychicBrainburn\CompAbilityEffect_PsychicBrainburn.cs" />
|
||||
<Compile Include="Abilities\PsychicBrainburn\CompProperties_PsychicBrainburn.cs" />
|
||||
<Compile Include="Abilities\TrackingCharge\CompAbilityEffect_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\TrackingCharge\CompProperties_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\TrackingCharge\PawnFlyer_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\TrackingCharge\Verb_CastAbilityTrackingCharge.cs" />
|
||||
<Compile Include="Abilities\ARA_PsychicBrainburn\CompAbilityEffect_PsychicBrainburn.cs" />
|
||||
<Compile Include="Abilities\ARA_PsychicBrainburn\CompProperties_PsychicBrainburn.cs" />
|
||||
<Compile Include="Abilities\ARA_TrackingCharge\CompAbilityEffect_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\ARA_TrackingCharge\CompProperties_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\ARA_TrackingCharge\PawnFlyer_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\ARA_TrackingCharge\Verb_CastAbilityTrackingCharge.cs" />
|
||||
<Compile Include="ArachnaeLog.cs" />
|
||||
<Compile Include="ArachnaeSwarmMod.cs" />
|
||||
<Compile Include="ArachnaeSwarmSettings.cs" />
|
||||
@@ -309,9 +309,8 @@
|
||||
<Compile Include="Hediffs\HediffComp_TerrainBasedSeverity\HediffCompProperties_TerrainBasedSeverity.cs" />
|
||||
<Compile Include="Hediffs\HediffComp_TerrainBasedSeverity\HediffComp_TerrainBasedSeverity.cs" />
|
||||
<Compile Include="Hediffs\HediffGiver_RandomWithSeverity.cs" />
|
||||
<Compile Include="Hediffs\MoharHediffs\HediffCompProperties_Spawner.cs" />
|
||||
<Compile Include="Hediffs\MoharHediffs\HediffComp_Spawner.cs" />
|
||||
<Compile Include="Hediffs\MoharHediffs\Tools.cs" />
|
||||
<Compile Include="Hediffs\ARA_Spawner\HediffCompProperties_Spawner.cs" />
|
||||
<Compile Include="Hediffs\ARA_Spawner\HediffComp_Spawner.cs" />
|
||||
<Compile Include="Hediffs\ProphecyGearEffect.cs" />
|
||||
<Compile Include="Hediffs\WULA_HediffDamgeShield\DRMDamageShield.cs" />
|
||||
<Compile Include="Hediffs\WULA_HediffDamgeShield\Hediff_DamageShield.cs" />
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class HediffCompProperties_Spawner : HediffCompProperties
|
||||
{
|
||||
public HediffCompProperties_Spawner()
|
||||
{
|
||||
this.compClass = typeof(HediffComp_Spawner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 要生成的物品的ThingDef。如果animalThing为false,则使用此项。
|
||||
/// </summary>
|
||||
public ThingDef thingToSpawn;
|
||||
|
||||
/// <summary>
|
||||
/// 每次生成的基础物品数量。
|
||||
/// </summary>
|
||||
public int spawnCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,则生成一个Pawn(动物)。如果为false,则生成一个Thing。
|
||||
/// </summary>
|
||||
public bool animalThing;
|
||||
|
||||
/// <summary>
|
||||
/// 要生成的动物的PawnKindDef。如果animalThing为true,则使用此项。
|
||||
/// </summary>
|
||||
public PawnKindDef animalToSpawn;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成的动物将属于玩家派系。
|
||||
/// </summary>
|
||||
public bool factionOfPlayerAnimal;
|
||||
|
||||
/// <summary>
|
||||
/// 下一次生成事件发生前的最少天数。
|
||||
/// </summary>
|
||||
public float minDaysB4Next = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// 下一次生成事件发生前的最大天数。
|
||||
/// </summary>
|
||||
public float maxDaysB4Next = 2f;
|
||||
|
||||
/// <summary>
|
||||
/// 生成后进入宽限期(延迟下一次生成)的几率(0.0到1.0)。
|
||||
/// </summary>
|
||||
public float randomGrace;
|
||||
|
||||
/// <summary>
|
||||
/// 如果触发,宽限期的持续时间(天)。
|
||||
/// </summary>
|
||||
public float graceDays = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// 附近允许的相同Pawn的最大数量。如果超过该数量,则暂停生成。-1为禁用。
|
||||
/// </summary>
|
||||
public int spawnMaxAdjacent = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成的物品将被禁用。
|
||||
/// </summary>
|
||||
public bool spawnForbidden;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,当宿主Pawn饥饿时,生成将暂停。
|
||||
/// </summary>
|
||||
public bool hungerRelative;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,当宿主Pawn受伤时,生成将暂停。
|
||||
/// </summary>
|
||||
public bool healthRelative;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成数量将根据宿主的年龄进行调整。
|
||||
/// </summary>
|
||||
public bool ageWeightedQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成周期(两次生成之间的时间)将根据宿主的年龄进行调整。
|
||||
/// </summary>
|
||||
public bool ageWeightedPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedPeriod为true,则随着宿主年龄增长,生成周期变短。如果为false,则变长。
|
||||
/// </summary>
|
||||
public bool olderSmallerPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedQuantity为true,则随着宿主年龄增长,生成数量变多。如果为false,则变少。
|
||||
/// </summary>
|
||||
public bool olderBiggerQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedQuantity为true,则随年龄增长的数量缩放将是指数性的而非线性的。
|
||||
/// </summary>
|
||||
public bool exponentialQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 指数级数量缩放的最大乘数,以防止出现荒谬的数字。
|
||||
/// </summary>
|
||||
public int exponentialRatioLimit = 15;
|
||||
|
||||
/// <summary>
|
||||
/// 生成时显示的消息的翻译键(例如,"下了一个蛋")。
|
||||
/// </summary>
|
||||
public string spawnVerb = "delivery";
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,则为此组件启用详细的调试日志记录。
|
||||
/// </summary>
|
||||
public bool debug;
|
||||
|
||||
/// <summary>
|
||||
/// 新增:生成物品时是否销毁随机身体部位
|
||||
/// </summary>
|
||||
public bool destroyRandomBodyPart = false;
|
||||
}
|
||||
}
|
||||
883
Source/ArachnaeSwarm/Hediffs/ARA_Spawner/HediffComp_Spawner.cs
Normal file
883
Source/ArachnaeSwarm/Hediffs/ARA_Spawner/HediffComp_Spawner.cs
Normal file
@@ -0,0 +1,883 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class HediffComp_Spawner : HediffComp
|
||||
{
|
||||
public HediffCompProperties_Spawner Props
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HediffCompProperties_Spawner)this.props;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompExposeData()
|
||||
{
|
||||
Scribe_Values.Look<int>(ref this.ticksUntilSpawn, "ticksUntilSpawn", 0, false);
|
||||
Scribe_Values.Look<int>(ref this.initialTicksUntilSpawn, "initialTicksUntilSpawn", 0, false);
|
||||
Scribe_Values.Look<float>(ref this.calculatedMinDaysB4Next, "calculatedMinDaysB4Next", 0f, false);
|
||||
Scribe_Values.Look<float>(ref this.calculatedMaxDaysB4Next, "calculatedMaxDaysB4Next", 0f, false);
|
||||
Scribe_Values.Look<int>(ref this.calculatedQuantity, "calculatedQuantity", 0, false);
|
||||
Scribe_Values.Look<int>(ref this.graceTicks, "graceTicks", 0, false);
|
||||
}
|
||||
|
||||
public override void CompPostMake()
|
||||
{
|
||||
this.myDebug = this.Props.debug;
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
">>> ",
|
||||
this.parent.pawn.Label,
|
||||
" - ",
|
||||
this.parent.def.defName,
|
||||
" - CompPostMake start"
|
||||
}), this.myDebug);
|
||||
TraceProps();
|
||||
CheckProps();
|
||||
CalculateValues();
|
||||
CheckCalculatedValues();
|
||||
TraceCalculatedValues();
|
||||
if (this.initialTicksUntilSpawn == 0)
|
||||
{
|
||||
Warn("Reseting countdown bc initialTicksUntilSpawn == 0 (comppostmake)", this.myDebug);
|
||||
ResetCountdown();
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompPostTick(ref float severityAdjustment)
|
||||
{
|
||||
this.pawn = this.parent.pawn;
|
||||
if (!OkPawn(this.pawn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.blockSpawn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.graceTicks > 0)
|
||||
{
|
||||
this.graceTicks--;
|
||||
return;
|
||||
}
|
||||
if (this.Props.hungerRelative && this.pawn.Starving())
|
||||
{
|
||||
int num = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.hungerReset++;
|
||||
this.graceTicks = num;
|
||||
return;
|
||||
}
|
||||
if (this.Props.healthRelative && this.pawn.Starving())
|
||||
{
|
||||
int num2 = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.healthReset++;
|
||||
this.graceTicks = num2;
|
||||
return;
|
||||
}
|
||||
this.hungerReset = (this.healthReset = 0);
|
||||
if (this.CheckShouldSpawn())
|
||||
{
|
||||
Warn("Reseting countdown bc spawned thing", this.myDebug);
|
||||
CalculateValues();
|
||||
CheckCalculatedValues();
|
||||
ResetCountdown();
|
||||
if (Rand.Chance(this.Props.randomGrace))
|
||||
{
|
||||
int num3 = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.graceTicks = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TraceProps()
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
"Props => minDaysB4Next: ",
|
||||
this.Props.minDaysB4Next.ToString(),
|
||||
"; maxDaysB4Next: ",
|
||||
this.Props.maxDaysB4Next.ToString(),
|
||||
"; randomGrace: ",
|
||||
this.Props.randomGrace.ToString(),
|
||||
"; graceDays: ",
|
||||
this.Props.graceDays.ToString(),
|
||||
"; hungerRelative: ",
|
||||
this.Props.hungerRelative.ToString(),
|
||||
"; healthRelative: ",
|
||||
this.Props.healthRelative.ToString(),
|
||||
"; destroyRandomBodyPart: ",
|
||||
this.Props.destroyRandomBodyPart.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
if (this.Props.animalThing)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
"animalThing: ",
|
||||
this.Props.animalThing.ToString(),
|
||||
"; animalName: ",
|
||||
this.Props.animalToSpawn.defName,
|
||||
"; factionOfPlayerAnimal: ",
|
||||
this.Props.factionOfPlayerAnimal.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
if (this.Props.ageWeightedQuantity)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
"ageWeightedQuantity:",
|
||||
this.Props.ageWeightedQuantity.ToString(),
|
||||
"; olderBiggerQuantity:",
|
||||
this.Props.olderBiggerQuantity.ToString(),
|
||||
"; ",
|
||||
this.myDebug.ToString()
|
||||
}), false);
|
||||
if (this.Props.exponentialQuantity)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
"exponentialQuantity:",
|
||||
this.Props.exponentialQuantity.ToString(),
|
||||
"; exponentialRatioLimit:",
|
||||
this.Props.exponentialRatioLimit.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
}
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
"ageWeightedPeriod:",
|
||||
this.Props.ageWeightedPeriod.ToString(),
|
||||
"; olderSmallerPeriod:",
|
||||
this.Props.olderSmallerPeriod.ToString(),
|
||||
"; ",
|
||||
this.myDebug.ToString()
|
||||
}), false);
|
||||
}
|
||||
|
||||
private void CalculateValues()
|
||||
{
|
||||
float num = GetPawnAgeOverlifeExpectancyRatio(this.parent.pawn, this.myDebug);
|
||||
num = ((num > 1f) ? 1f : num);
|
||||
this.calculatedMinDaysB4Next = this.Props.minDaysB4Next;
|
||||
this.calculatedMaxDaysB4Next = this.Props.maxDaysB4Next;
|
||||
if (this.Props.ageWeightedPeriod)
|
||||
{
|
||||
float num2 = this.Props.olderSmallerPeriod ? (-num) : num;
|
||||
this.calculatedMinDaysB4Next = this.Props.minDaysB4Next * (1f + num2);
|
||||
this.calculatedMaxDaysB4Next = this.Props.maxDaysB4Next * (1f + num2);
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
" ageWeightedPeriod: ",
|
||||
this.Props.ageWeightedPeriod.ToString(),
|
||||
" ageRatio: ",
|
||||
num.ToString(),
|
||||
" minDaysB4Next: ",
|
||||
this.Props.minDaysB4Next.ToString(),
|
||||
" maxDaysB4Next: ",
|
||||
this.Props.maxDaysB4Next.ToString(),
|
||||
" daysAgeRatio: ",
|
||||
num2.ToString(),
|
||||
" calculatedMinDaysB4Next: ",
|
||||
this.calculatedMinDaysB4Next.ToString(),
|
||||
"; calculatedMaxDaysB4Next: ",
|
||||
this.calculatedMaxDaysB4Next.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
this.calculatedQuantity = this.Props.spawnCount;
|
||||
if (this.Props.ageWeightedQuantity)
|
||||
{
|
||||
float num3 = this.Props.olderBiggerQuantity ? num : (-num);
|
||||
Warn("quantityAgeRatio: " + num3.ToString(), this.myDebug);
|
||||
this.calculatedQuantity = (int)Math.Round((double)this.Props.spawnCount * (double)(1f + num3));
|
||||
if (this.Props.exponentialQuantity)
|
||||
{
|
||||
num3 = 1f - num;
|
||||
if (num3 == 0f)
|
||||
{
|
||||
Warn(">ERROR< quantityAgeRatio is f* up : " + num3.ToString(), this.myDebug);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
float num4 = this.Props.olderBiggerQuantity ? (1f / num3) : (num3 * num3);
|
||||
bool flag = false;
|
||||
bool flag2 = false;
|
||||
if (num4 > (float)this.Props.exponentialRatioLimit)
|
||||
{
|
||||
num4 = (float)this.Props.exponentialRatioLimit;
|
||||
flag = true;
|
||||
}
|
||||
this.calculatedQuantity = (int)Math.Round((double)this.Props.spawnCount * (double)num4);
|
||||
if (this.calculatedQuantity < 1)
|
||||
{
|
||||
this.calculatedQuantity = 1;
|
||||
flag2 = true;
|
||||
}
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
" exponentialQuantity: ",
|
||||
this.Props.exponentialQuantity.ToString(),
|
||||
"; expoFactor: ",
|
||||
num4.ToString(),
|
||||
"; gotLimited: ",
|
||||
flag.ToString(),
|
||||
"; gotAugmented: ",
|
||||
flag2.ToString()
|
||||
}), this.myDebug);
|
||||
}
|
||||
Warn("; Props.spawnCount: " + this.Props.spawnCount.ToString() + "; calculatedQuantity: " + this.calculatedQuantity.ToString(), this.myDebug);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckCalculatedValues()
|
||||
{
|
||||
if (this.calculatedQuantity > this.errorSpawnCount)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
">ERROR< calculatedQuantity is too high: ",
|
||||
this.calculatedQuantity.ToString(),
|
||||
"(>",
|
||||
this.errorSpawnCount.ToString(),
|
||||
"), check and adjust your hediff props"
|
||||
}), this.myDebug);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.calculatedMinDaysB4Next < this.errorMinDaysB4Next)
|
||||
{
|
||||
this.calculatedMinDaysB4Next = this.errorMinDaysB4Next;
|
||||
}
|
||||
if (this.calculatedMaxDaysB4Next < this.errorMinDaysB4Next)
|
||||
{
|
||||
this.calculatedMaxDaysB4Next = this.errorMinDaysB4Next;
|
||||
}
|
||||
}
|
||||
|
||||
private void TraceCalculatedValues()
|
||||
{
|
||||
Warn("calculatedMinDaysB4Next:" + this.calculatedMinDaysB4Next.ToString(), this.myDebug);
|
||||
Warn("calculatedMaxDaysB4Next:" + this.calculatedMaxDaysB4Next.ToString(), this.myDebug);
|
||||
Warn("calculatedQuantity:" + this.calculatedQuantity.ToString(), this.myDebug);
|
||||
}
|
||||
|
||||
private void CheckProps()
|
||||
{
|
||||
if (this.Props.animalThing && this.Props.animalToSpawn == null)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with animalflag but without animalToSpawn", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.minDaysB4Next <= 0f)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative minDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.maxDaysB4Next <= 0f)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative maxDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.maxDaysB4Next < this.Props.minDaysB4Next)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with maxDaysB4Next < minDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.spawnCount <= 0)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative spawnCount", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (!this.Props.animalThing && this.Props.thingToSpawn == null)
|
||||
{
|
||||
Warn(this.parent.pawn.Label + " has a hediffcomp_spawner without thingToSpawn", true);
|
||||
this.blockSpawn = true;
|
||||
DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.ageWeightedQuantity && this.Props.exponentialQuantity && this.Props.exponentialRatioLimit > this.errorExponentialLimit)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
this.parent.pawn.Label,
|
||||
" has a hediffcomp_spawner with exponentialRatioLimit>",
|
||||
this.errorExponentialLimit.ToString(),
|
||||
" this is not allowed. It will be set to ",
|
||||
this.errorExponentialLimit.ToString()
|
||||
}), true);
|
||||
this.Props.exponentialRatioLimit = this.errorExponentialLimit;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckShouldSpawn()
|
||||
{
|
||||
this.ticksUntilSpawn--;
|
||||
if (this.ticksUntilSpawn <= 0)
|
||||
{
|
||||
if (this.TryDoSpawn())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Warn("Did not spawn, reseting countdown", this.myDebug);
|
||||
ResetCountdown();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryDoSpawn()
|
||||
{
|
||||
Pawn pawn = this.parent.pawn;
|
||||
|
||||
if (this.Props.animalThing)
|
||||
{
|
||||
// 动物生成逻辑保持不变
|
||||
if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP)
|
||||
{
|
||||
ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn;
|
||||
if (defToCompare?.race == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return mP.def == defToCompare && mP.Position.InHorDistOf(pawn.Position, (float)this.Props.spawnMaxAdjacent);
|
||||
}).Count<Pawn>() >= this.Props.spawnMaxAdjacent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.Props.animalToSpawn == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Faction faction = this.Props.factionOfPlayerAnimal ? Faction.OfPlayer : null;
|
||||
int i = 0;
|
||||
while (i < this.calculatedQuantity)
|
||||
{
|
||||
IntVec3 intVec;
|
||||
if (!this.TryFindSpawnCell(out intVec))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Pawn pawn2 = PawnGenerator.GeneratePawn(this.Props.animalToSpawn, faction);
|
||||
if (pawn2 == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GenSpawn.Spawn(pawn2, intVec, pawn.Map, WipeMode.Vanish);
|
||||
pawn2.SetFaction(faction, null);
|
||||
FilthMaker.TryMakeFilth(intVec, pawn.Map, ThingDefOf.Filth_AmnioticFluid, pawn.LabelIndefinite(), 5, FilthSourceFlags.None);
|
||||
if (!this.Props.spawnForbidden)
|
||||
{
|
||||
pawn2.playerSettings.Master = pawn;
|
||||
pawn2.training.Train(TrainableDefOf.Obedience, pawn, true);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (PawnUtility.ShouldSendNotificationAbout(pawn) || PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||
{
|
||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.PositiveEvent, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 重新设计物品生成逻辑:按优先级顺序尝试
|
||||
bool success = TrySpawnItemWithPriority(pawn);
|
||||
|
||||
// === 新增:如果配置了销毁随机部位,在成功生成物品后执行 ===
|
||||
if (success && this.Props.destroyRandomBodyPart)
|
||||
{
|
||||
DestroyRandomBodyPart(pawn);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:销毁随机身体部位(参考 CompAbilityEffect_DestroyOwnBodyPart)
|
||||
private void DestroyRandomBodyPart(Pawn pawn)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pawn == null || pawn.Dead)
|
||||
{
|
||||
Warn($"Cannot destroy body part for null or dead pawn", this.myDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取所有可以销毁的身体部位
|
||||
List<BodyPartRecord> possibleParts = GetDestroyableBodyParts(pawn);
|
||||
|
||||
if (possibleParts.Count == 0)
|
||||
{
|
||||
Warn($"No destroyable body parts found for {pawn.LabelShort}", this.myDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
// 随机选择一个部位
|
||||
BodyPartRecord partToDestroy = possibleParts.RandomElement();
|
||||
|
||||
if (partToDestroy == null)
|
||||
{
|
||||
Warn($"Selected null body part for {pawn.LabelShort}", this.myDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录部位名称
|
||||
string partName = partToDestroy.def?.label ?? "未知部位";
|
||||
|
||||
// 添加缺失部位hediff
|
||||
pawn.health.AddHediff(HediffDefOf.MissingBodyPart, partToDestroy);
|
||||
|
||||
Warn($"Destroyed {partName} on {pawn.LabelShort}", this.myDebug);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error destroying random body part for {pawn?.LabelShort}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:获取可以销毁的身体部位列表
|
||||
private List<BodyPartRecord> GetDestroyableBodyParts(Pawn pawn)
|
||||
{
|
||||
List<BodyPartRecord> destroyableParts = new List<BodyPartRecord>();
|
||||
|
||||
if (pawn?.health?.hediffSet == null)
|
||||
return destroyableParts;
|
||||
|
||||
// 获取所有身体部位
|
||||
List<BodyPartRecord> allParts = pawn.RaceProps.body.AllParts;
|
||||
|
||||
foreach (BodyPartRecord part in allParts)
|
||||
{
|
||||
// 排除核心部位(避免死亡)
|
||||
if (IsCriticalBodyPart(part))
|
||||
continue;
|
||||
|
||||
// 排除已经缺失的部位
|
||||
if (pawn.health.hediffSet.PartIsMissing(part))
|
||||
continue;
|
||||
|
||||
// 排除已经有严重伤害的部位(可选)
|
||||
if (pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(part))
|
||||
continue;
|
||||
|
||||
destroyableParts.Add(part);
|
||||
}
|
||||
|
||||
return destroyableParts;
|
||||
}
|
||||
|
||||
// 新增:检查是否是关键身体部位
|
||||
private bool IsCriticalBodyPart(BodyPartRecord part)
|
||||
{
|
||||
if (part == null)
|
||||
return false;
|
||||
|
||||
// 根据标签判断是否为关键部位
|
||||
if (part.def.tags != null)
|
||||
{
|
||||
// 这些标签通常表示关键部位
|
||||
if (part.def.tags.Contains(BodyPartTagDefOf.ConsciousnessSource) || // 意识源(大脑)
|
||||
part.def.tags.Contains(BodyPartTagDefOf.BloodPumpingSource) || // 血液泵源(心脏)
|
||||
part.def.tags.Contains(BodyPartTagDefOf.BreathingSource) || // 呼吸源(肺)
|
||||
part.def.tags.Contains(BodyPartTagDefOf.MetabolismSource) // 代谢源(肝脏)
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据深度判断(深度较深的通常是内部器官)
|
||||
if (part.depth == BodyPartDepth.Inside && part.parent == null)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:按优先级顺序尝试生成物品
|
||||
private bool TrySpawnItemWithPriority(Pawn pawn)
|
||||
{
|
||||
Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null);
|
||||
if (thing == null)
|
||||
{
|
||||
Warn("Failed to create thing: " + this.Props.thingToSpawn?.defName, this.myDebug);
|
||||
return false;
|
||||
}
|
||||
thing.stackCount = this.calculatedQuantity;
|
||||
|
||||
// 记录原始物品用于校验
|
||||
ThingDef originalThingDef = thing.def;
|
||||
int originalStackCount = thing.stackCount;
|
||||
|
||||
// 按优先级顺序尝试生成
|
||||
bool success = false;
|
||||
string spawnMethod = "";
|
||||
|
||||
// 优先级1: 尝试在pawn附近空地生成
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnAtNearbyEmptyCell(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 优先级2: 尝试在pawn脚底生成
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnAtPawnPosition(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 优先级3: 尝试放入pawn物品栏
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnInInventory(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 生成后校验
|
||||
if (success)
|
||||
{
|
||||
bool verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, spawnMethod);
|
||||
|
||||
// 如果校验失败且不是在物品栏中生成的,尝试在物品栏中重新生成
|
||||
if (!verified && spawnMethod != "inventory")
|
||||
{
|
||||
Warn($"Spawn verification failed for {spawnMethod}, attempting inventory fallback", this.myDebug);
|
||||
|
||||
// 重新创建物品
|
||||
Thing fallbackThing = ThingMaker.MakeThing(originalThingDef, null);
|
||||
fallbackThing.stackCount = originalStackCount;
|
||||
|
||||
success = TrySpawnInInventory(pawn, fallbackThing, ref spawnMethod);
|
||||
|
||||
if (success)
|
||||
{
|
||||
verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, "inventory_fallback");
|
||||
if (!verified)
|
||||
{
|
||||
Warn("Inventory fallback also failed verification", this.myDebug);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success && verified)
|
||||
{
|
||||
if (PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||
{
|
||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")),
|
||||
spawnMethod == "inventory" || spawnMethod == "inventory_fallback" ? pawn : thing,
|
||||
MessageTypeDefOf.PositiveEvent, true);
|
||||
}
|
||||
Warn($"Successfully spawned {originalStackCount}x {originalThingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Warn($"Failed to spawn {originalStackCount}x {originalThingDef.defName} after all attempts", this.myDebug);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在附近空地生成
|
||||
private bool TrySpawnAtNearbyEmptyCell(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
IntVec3 spawnCell;
|
||||
if (TryFindSpawnCell(out spawnCell))
|
||||
{
|
||||
if (this.Props.spawnForbidden)
|
||||
{
|
||||
thing.SetForbidden(true, true);
|
||||
}
|
||||
|
||||
if (GenPlace.TryPlaceThing(thing, spawnCell, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
||||
{
|
||||
spawnMethod = "nearby_cell";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在pawn位置生成
|
||||
private bool TrySpawnAtPawnPosition(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
IntVec3 pawnPosition = pawn.Position;
|
||||
if (pawnPosition.IsValid && pawnPosition.Walkable(pawn.Map))
|
||||
{
|
||||
if (this.Props.spawnForbidden)
|
||||
{
|
||||
thing.SetForbidden(true, true);
|
||||
}
|
||||
|
||||
if (GenPlace.TryPlaceThing(thing, pawnPosition, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
||||
{
|
||||
spawnMethod = "pawn_position";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在物品栏生成
|
||||
private bool TrySpawnInInventory(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
if (pawn.inventory == null)
|
||||
{
|
||||
Warn($"Pawn {pawn.Label} does not have an inventory", this.myDebug);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pawn.inventory.innerContainer.TryAdd(thing))
|
||||
{
|
||||
spawnMethod = "inventory";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:生成后校验
|
||||
private bool VerifySpawnSuccess(Pawn pawn, ThingDef thingDef, int expectedCount, string spawnMethod)
|
||||
{
|
||||
bool verificationSuccess = false;
|
||||
|
||||
switch (spawnMethod)
|
||||
{
|
||||
case "nearby_cell":
|
||||
case "pawn_position":
|
||||
case "inventory_fallback":
|
||||
// 检查地图上是否有生成的物品
|
||||
verificationSuccess = pawn.Map.listerThings.ThingsOfDef(thingDef)
|
||||
.Any(t => t.stackCount >= expectedCount && t.Position.InHorDistOf(pawn.Position, 2f));
|
||||
break;
|
||||
|
||||
case "inventory":
|
||||
// 检查物品栏中是否有生成的物品
|
||||
verificationSuccess = pawn.inventory.innerContainer.Any(t => t.def == thingDef && t.stackCount >= expectedCount);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!verificationSuccess)
|
||||
{
|
||||
Warn($"Spawn verification failed for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
}
|
||||
else
|
||||
{
|
||||
Warn($"Spawn verification successful for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
}
|
||||
|
||||
return verificationSuccess;
|
||||
}
|
||||
|
||||
private bool TryFindSpawnCell(out IntVec3 result)
|
||||
{
|
||||
result = IntVec3.Invalid;
|
||||
bool result2;
|
||||
if (this.pawn == null)
|
||||
{
|
||||
result2 = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Map map = this.pawn.Map;
|
||||
if (map == null)
|
||||
{
|
||||
result2 = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 修改这里:将半径从5减少到2,让生成位置更靠近pawn
|
||||
int searchRadius = 2;
|
||||
|
||||
// 首先尝试在pawn的相邻单元格生成(半径为1)
|
||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null);
|
||||
|
||||
// 如果相邻单元格找不到合适位置,再尝试稍远一点(半径为2)
|
||||
if (!result.IsValid)
|
||||
{
|
||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null);
|
||||
}
|
||||
|
||||
// 如果还是找不到,尝试pawn当前位置(作为最后手段)
|
||||
if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map))
|
||||
{
|
||||
result = this.pawn.Position;
|
||||
}
|
||||
|
||||
result2 = result.IsValid;
|
||||
}
|
||||
}
|
||||
return result2;
|
||||
}
|
||||
|
||||
private void ResetCountdown()
|
||||
{
|
||||
this.ticksUntilSpawn = (int)(this.RandomDays2wait() * 60000f);
|
||||
this.initialTicksUntilSpawn = this.ticksUntilSpawn;
|
||||
}
|
||||
|
||||
private float RandomDays2wait()
|
||||
{
|
||||
return Rand.Range(this.calculatedMinDaysB4Next, this.calculatedMaxDaysB4Next);
|
||||
}
|
||||
|
||||
private float RandomGraceDays()
|
||||
{
|
||||
return Rand.Range(this.Props.graceDays / 2f, this.Props.graceDays);
|
||||
}
|
||||
|
||||
public override string CompTipStringExtra
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.myDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string text = "ticksUntilSpawn: " + this.ticksUntilSpawn.ToString() + "\n";
|
||||
string text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"initialTicksUntilSpawn: ",
|
||||
this.initialTicksUntilSpawn.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"graceTicks: ",
|
||||
this.graceTicks.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"hunger resets: ",
|
||||
this.hungerReset.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"health resets: ",
|
||||
this.healthReset.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedMinDaysB4Next: ",
|
||||
this.calculatedMinDaysB4Next.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedMaxDaysB4Next: ",
|
||||
this.calculatedMaxDaysB4Next.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedQuantity: ",
|
||||
this.calculatedQuantity.ToString(),
|
||||
"\n"
|
||||
});
|
||||
return text + "blockSpawn: " + this.blockSpawn.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// === 整合的 Tools 方法 ===
|
||||
|
||||
private void DestroyParentHediff(Hediff parentHediff, bool debug = false)
|
||||
{
|
||||
if (parentHediff.pawn != null && parentHediff.def.defName != null && debug)
|
||||
{
|
||||
Warn(parentHediff.pawn.Label + "'s Hediff: " + parentHediff.def.defName + " says goodbye.", debug);
|
||||
}
|
||||
parentHediff.Severity = 0f;
|
||||
}
|
||||
|
||||
private float GetPawnAgeOverlifeExpectancyRatio(Pawn pawn, bool debug = false)
|
||||
{
|
||||
float result = 1f;
|
||||
if (pawn == null)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Warn("GetPawnAgeOverlifeExpectancyRatio pawn NOT OK", debug);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
result = pawn.ageTracker.AgeBiologicalYearsFloat / pawn.RaceProps.lifeExpectancy;
|
||||
if (debug)
|
||||
{
|
||||
Warn(string.Concat(new string[]
|
||||
{
|
||||
pawn.Label,
|
||||
" Age: ",
|
||||
pawn.ageTracker.AgeBiologicalYearsFloat.ToString(),
|
||||
"; lifeExpectancy: ",
|
||||
pawn.RaceProps.lifeExpectancy.ToString(),
|
||||
"; ratio:",
|
||||
result.ToString()
|
||||
}), debug);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool OkPawn(Pawn pawn)
|
||||
{
|
||||
return pawn != null && pawn.Map != null;
|
||||
}
|
||||
|
||||
private void Warn(string warning, bool debug = false)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Log.Message($"[HediffComp_Spawner] {warning}");
|
||||
}
|
||||
}
|
||||
|
||||
private int ticksUntilSpawn;
|
||||
private int initialTicksUntilSpawn;
|
||||
private int hungerReset;
|
||||
private int healthReset;
|
||||
private int graceTicks;
|
||||
private Pawn pawn;
|
||||
private float calculatedMaxDaysB4Next = 2f;
|
||||
private float calculatedMinDaysB4Next = 1f;
|
||||
private int calculatedQuantity = 1;
|
||||
private bool blockSpawn;
|
||||
private bool myDebug;
|
||||
private readonly float errorMinDaysB4Next = 0.001f;
|
||||
private readonly int errorExponentialLimit = 20;
|
||||
private readonly int errorSpawnCount = 750;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
using System;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm.MoharHediffs
|
||||
{
|
||||
public class HediffCompProperties_Spawner : HediffCompProperties
|
||||
{
|
||||
public HediffCompProperties_Spawner()
|
||||
{
|
||||
this.compClass = typeof(HediffComp_Spawner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 要生成的物品的ThingDef。如果animalThing为false,则使用此项。
|
||||
/// </summary>
|
||||
public ThingDef thingToSpawn;
|
||||
|
||||
/// <summary>
|
||||
/// 每次生成的基础物品数量。
|
||||
/// </summary>
|
||||
public int spawnCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,则生成一个Pawn(动物)。如果为false,则生成一个Thing。
|
||||
/// </summary>
|
||||
public bool animalThing;
|
||||
|
||||
/// <summary>
|
||||
/// 要生成的动物的PawnKindDef。如果animalThing为true,则使用此项。
|
||||
/// </summary>
|
||||
public PawnKindDef animalToSpawn;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成的动物将属于玩家派系。
|
||||
/// </summary>
|
||||
public bool factionOfPlayerAnimal;
|
||||
|
||||
/// <summary>
|
||||
/// 下一次生成事件发生前的最少天数。
|
||||
/// </summary>
|
||||
public float minDaysB4Next = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// 下一次生成事件发生前的最大天数。
|
||||
/// </summary>
|
||||
public float maxDaysB4Next = 2f;
|
||||
|
||||
/// <summary>
|
||||
/// 生成后进入宽限期(延迟下一次生成)的几率(0.0到1.0)。
|
||||
/// </summary>
|
||||
public float randomGrace;
|
||||
|
||||
/// <summary>
|
||||
/// 如果触发,宽限期的持续时间(天)。
|
||||
/// </summary>
|
||||
public float graceDays = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// 附近允许的相同Pawn的最大数量。如果超过该数量,则暂停生成。-1为禁用。
|
||||
/// </summary>
|
||||
public int spawnMaxAdjacent = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成的物品将被禁用。
|
||||
/// </summary>
|
||||
public bool spawnForbidden;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,当宿主Pawn饥饿时,生成将暂停。
|
||||
/// </summary>
|
||||
public bool hungerRelative;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,当宿主Pawn受伤时,生成将暂停。
|
||||
/// </summary>
|
||||
public bool healthRelative;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成数量将根据宿主的年龄进行调整。
|
||||
/// </summary>
|
||||
public bool ageWeightedQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,生成周期(两次生成之间的时间)将根据宿主的年龄进行调整。
|
||||
/// </summary>
|
||||
public bool ageWeightedPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedPeriod为true,则随着宿主年龄增长,生成周期变短。如果为false,则变长。
|
||||
/// </summary>
|
||||
public bool olderSmallerPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedQuantity为true,则随着宿主年龄增长,生成数量变多。如果为false,则变少。
|
||||
/// </summary>
|
||||
public bool olderBiggerQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true且ageWeightedQuantity为true,则随年龄增长的数量缩放将是指数性的而非线性的。
|
||||
/// </summary>
|
||||
public bool exponentialQuantity;
|
||||
|
||||
/// <summary>
|
||||
/// 指数级数量缩放的最大乘数,以防止出现荒谬的数字。
|
||||
/// </summary>
|
||||
public int exponentialRatioLimit = 15;
|
||||
|
||||
/// <summary>
|
||||
/// 生成时显示的消息的翻译键(例如,“{PAWN}下了一个蛋。”)。
|
||||
/// </summary>
|
||||
public string spawnVerb = "delivery";
|
||||
|
||||
/// <summary>
|
||||
/// 如果为true,则为此组件启用详细的调试日志记录。
|
||||
/// </summary>
|
||||
public bool debug;
|
||||
}
|
||||
}
|
||||
@@ -1,739 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm.MoharHediffs
|
||||
{
|
||||
public class HediffComp_Spawner : HediffComp
|
||||
{
|
||||
public HediffCompProperties_Spawner Props
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HediffCompProperties_Spawner)this.props;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompExposeData()
|
||||
{
|
||||
Scribe_Values.Look<int>(ref this.ticksUntilSpawn, "ticksUntilSpawn", 0, false);
|
||||
Scribe_Values.Look<int>(ref this.initialTicksUntilSpawn, "initialTicksUntilSpawn", 0, false);
|
||||
Scribe_Values.Look<float>(ref this.calculatedMinDaysB4Next, "calculatedMinDaysB4Next", 0f, false);
|
||||
Scribe_Values.Look<float>(ref this.calculatedMaxDaysB4Next, "calculatedMaxDaysB4Next", 0f, false);
|
||||
Scribe_Values.Look<int>(ref this.calculatedQuantity, "calculatedQuantity", 0, false);
|
||||
Scribe_Values.Look<int>(ref this.graceTicks, "graceTicks", 0, false);
|
||||
}
|
||||
|
||||
public override void CompPostMake()
|
||||
{
|
||||
this.myDebug = this.Props.debug;
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
">>> ",
|
||||
this.parent.pawn.Label,
|
||||
" - ",
|
||||
this.parent.def.defName,
|
||||
" - CompPostMake start"
|
||||
}), this.myDebug);
|
||||
this.TraceProps();
|
||||
this.CheckProps();
|
||||
this.CalculateValues();
|
||||
this.CheckCalculatedValues();
|
||||
this.TraceCalculatedValues();
|
||||
if (this.initialTicksUntilSpawn == 0)
|
||||
{
|
||||
Tools.Warn("Reseting countdown bc initialTicksUntilSpawn == 0 (comppostmake)", this.myDebug);
|
||||
this.ResetCountdown();
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompPostTick(ref float severityAdjustment)
|
||||
{
|
||||
this.pawn = this.parent.pawn;
|
||||
if (!Tools.OkPawn(this.pawn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.blockSpawn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.graceTicks > 0)
|
||||
{
|
||||
this.graceTicks--;
|
||||
return;
|
||||
}
|
||||
if (this.Props.hungerRelative && this.pawn.IsHungry(this.myDebug))
|
||||
{
|
||||
int num = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.hungerReset++;
|
||||
this.graceTicks = num;
|
||||
return;
|
||||
}
|
||||
if (this.Props.healthRelative && this.pawn.IsInjured(this.myDebug))
|
||||
{
|
||||
int num2 = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.healthReset++;
|
||||
this.graceTicks = num2;
|
||||
return;
|
||||
}
|
||||
this.hungerReset = (this.healthReset = 0);
|
||||
if (this.CheckShouldSpawn())
|
||||
{
|
||||
Tools.Warn("Reseting countdown bc spawned thing", this.myDebug);
|
||||
this.CalculateValues();
|
||||
this.CheckCalculatedValues();
|
||||
this.ResetCountdown();
|
||||
if (Rand.Chance(this.Props.randomGrace))
|
||||
{
|
||||
int num3 = (int)(this.RandomGraceDays() * 60000f);
|
||||
this.graceTicks = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TraceProps()
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
"Props => minDaysB4Next: ",
|
||||
this.Props.minDaysB4Next.ToString(),
|
||||
"; maxDaysB4Next: ",
|
||||
this.Props.maxDaysB4Next.ToString(),
|
||||
"; randomGrace: ",
|
||||
this.Props.randomGrace.ToString(),
|
||||
"; graceDays: ",
|
||||
this.Props.graceDays.ToString(),
|
||||
"; hungerRelative: ",
|
||||
this.Props.hungerRelative.ToString(),
|
||||
"; healthRelative: ",
|
||||
this.Props.healthRelative.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
if (this.Props.animalThing)
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
"animalThing: ",
|
||||
this.Props.animalThing.ToString(),
|
||||
"; animalName: ",
|
||||
this.Props.animalToSpawn.defName,
|
||||
"; factionOfPlayerAnimal: ",
|
||||
this.Props.factionOfPlayerAnimal.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
if (this.Props.ageWeightedQuantity)
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
"ageWeightedQuantity:",
|
||||
this.Props.ageWeightedQuantity.ToString(),
|
||||
"; olderBiggerQuantity:",
|
||||
this.Props.olderBiggerQuantity.ToString(),
|
||||
"; ",
|
||||
this.myDebug.ToString()
|
||||
}), false);
|
||||
if (this.Props.exponentialQuantity)
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
"exponentialQuantity:",
|
||||
this.Props.exponentialQuantity.ToString(),
|
||||
"; exponentialRatioLimit:",
|
||||
this.Props.exponentialRatioLimit.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
}
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
"ageWeightedPeriod:",
|
||||
this.Props.ageWeightedPeriod.ToString(),
|
||||
"; olderSmallerPeriod:",
|
||||
this.Props.olderSmallerPeriod.ToString(),
|
||||
"; ",
|
||||
this.myDebug.ToString()
|
||||
}), false);
|
||||
}
|
||||
|
||||
private void CalculateValues()
|
||||
{
|
||||
float num = Tools.GetPawnAgeOverlifeExpectancyRatio(this.parent.pawn, this.myDebug);
|
||||
num = ((num > 1f) ? 1f : num);
|
||||
this.calculatedMinDaysB4Next = this.Props.minDaysB4Next;
|
||||
this.calculatedMaxDaysB4Next = this.Props.maxDaysB4Next;
|
||||
if (this.Props.ageWeightedPeriod)
|
||||
{
|
||||
float num2 = this.Props.olderSmallerPeriod ? (-num) : num;
|
||||
this.calculatedMinDaysB4Next = this.Props.minDaysB4Next * (1f + num2);
|
||||
this.calculatedMaxDaysB4Next = this.Props.maxDaysB4Next * (1f + num2);
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
" ageWeightedPeriod: ",
|
||||
this.Props.ageWeightedPeriod.ToString(),
|
||||
" ageRatio: ",
|
||||
num.ToString(),
|
||||
" minDaysB4Next: ",
|
||||
this.Props.minDaysB4Next.ToString(),
|
||||
" maxDaysB4Next: ",
|
||||
this.Props.maxDaysB4Next.ToString(),
|
||||
" daysAgeRatio: ",
|
||||
num2.ToString(),
|
||||
" calculatedMinDaysB4Next: ",
|
||||
this.calculatedMinDaysB4Next.ToString(),
|
||||
"; calculatedMaxDaysB4Next: ",
|
||||
this.calculatedMaxDaysB4Next.ToString(),
|
||||
"; "
|
||||
}), this.myDebug);
|
||||
}
|
||||
this.calculatedQuantity = this.Props.spawnCount;
|
||||
if (this.Props.ageWeightedQuantity)
|
||||
{
|
||||
float num3 = this.Props.olderBiggerQuantity ? num : (-num);
|
||||
Tools.Warn("quantityAgeRatio: " + num3.ToString(), this.myDebug);
|
||||
this.calculatedQuantity = (int)Math.Round((double)this.Props.spawnCount * (double)(1f + num3));
|
||||
if (this.Props.exponentialQuantity)
|
||||
{
|
||||
num3 = 1f - num;
|
||||
if (num3 == 0f)
|
||||
{
|
||||
Tools.Warn(">ERROR< quantityAgeRatio is f* up : " + num3.ToString(), this.myDebug);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
float num4 = this.Props.olderBiggerQuantity ? (1f / num3) : (num3 * num3);
|
||||
bool flag = false;
|
||||
bool flag2 = false;
|
||||
if (num4 > (float)this.Props.exponentialRatioLimit)
|
||||
{
|
||||
num4 = (float)this.Props.exponentialRatioLimit;
|
||||
flag = true;
|
||||
}
|
||||
this.calculatedQuantity = (int)Math.Round((double)this.Props.spawnCount * (double)num4);
|
||||
if (this.calculatedQuantity < 1)
|
||||
{
|
||||
this.calculatedQuantity = 1;
|
||||
flag2 = true;
|
||||
}
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
" exponentialQuantity: ",
|
||||
this.Props.exponentialQuantity.ToString(),
|
||||
"; expoFactor: ",
|
||||
num4.ToString(),
|
||||
"; gotLimited: ",
|
||||
flag.ToString(),
|
||||
"; gotAugmented: ",
|
||||
flag2.ToString()
|
||||
}), this.myDebug);
|
||||
}
|
||||
Tools.Warn("; Props.spawnCount: " + this.Props.spawnCount.ToString() + "; calculatedQuantity: " + this.calculatedQuantity.ToString(), this.myDebug);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckCalculatedValues()
|
||||
{
|
||||
if (this.calculatedQuantity > this.errorSpawnCount)
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
">ERROR< calculatedQuantity is too high: ",
|
||||
this.calculatedQuantity.ToString(),
|
||||
"(>",
|
||||
this.errorSpawnCount.ToString(),
|
||||
"), check and adjust your hediff props"
|
||||
}), this.myDebug);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.calculatedMinDaysB4Next < this.errorMinDaysB4Next)
|
||||
{
|
||||
this.calculatedMinDaysB4Next = this.errorMinDaysB4Next;
|
||||
}
|
||||
if (this.calculatedMaxDaysB4Next < this.errorMinDaysB4Next)
|
||||
{
|
||||
this.calculatedMaxDaysB4Next = this.errorMinDaysB4Next;
|
||||
}
|
||||
}
|
||||
|
||||
private void TraceCalculatedValues()
|
||||
{
|
||||
Tools.Warn("calculatedMinDaysB4Next:" + this.calculatedMinDaysB4Next.ToString(), this.myDebug);
|
||||
Tools.Warn("calculatedMaxDaysB4Next:" + this.calculatedMaxDaysB4Next.ToString(), this.myDebug);
|
||||
Tools.Warn("calculatedQuantity:" + this.calculatedQuantity.ToString(), this.myDebug);
|
||||
}
|
||||
|
||||
private void CheckProps()
|
||||
{
|
||||
if (this.Props.animalThing && this.Props.animalToSpawn == null)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with animalflag but without animalToSpawn", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.minDaysB4Next <= 0f)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative minDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.maxDaysB4Next <= 0f)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative maxDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.maxDaysB4Next < this.Props.minDaysB4Next)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with maxDaysB4Next < minDaysB4Next", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.spawnCount <= 0)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner with null/negative spawnCount", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (!this.Props.animalThing && this.Props.thingToSpawn == null)
|
||||
{
|
||||
Tools.Warn(this.parent.pawn.Label + " has a hediffcomp_spawner without thingToSpawn", true);
|
||||
this.blockSpawn = true;
|
||||
Tools.DestroyParentHediff(this.parent, this.myDebug);
|
||||
return;
|
||||
}
|
||||
if (this.Props.ageWeightedQuantity && this.Props.exponentialQuantity && this.Props.exponentialRatioLimit > this.errorExponentialLimit)
|
||||
{
|
||||
Tools.Warn(string.Concat(new string[]
|
||||
{
|
||||
this.parent.pawn.Label,
|
||||
" has a hediffcomp_spawner with exponentialRatioLimit>",
|
||||
this.errorExponentialLimit.ToString(),
|
||||
" this is not allowed. It will be set to ",
|
||||
this.errorExponentialLimit.ToString()
|
||||
}), true);
|
||||
this.Props.exponentialRatioLimit = this.errorExponentialLimit;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckShouldSpawn()
|
||||
{
|
||||
this.ticksUntilSpawn--;
|
||||
if (this.ticksUntilSpawn <= 0)
|
||||
{
|
||||
if (this.TryDoSpawn())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Tools.Warn("Did not spawn, reseting countdown", this.myDebug);
|
||||
this.ResetCountdown();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private PawnKindDef MyPawnKindDefNamed(string myDefName)
|
||||
{
|
||||
return DefDatabase<PawnKindDef>.GetNamed(myDefName, true);
|
||||
}
|
||||
|
||||
public bool TryDoSpawn()
|
||||
{
|
||||
Pawn pawn = this.parent.pawn;
|
||||
|
||||
if (this.Props.animalThing)
|
||||
{
|
||||
// 动物生成逻辑保持不变
|
||||
if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP)
|
||||
{
|
||||
ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn;
|
||||
if (defToCompare?.race == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return mP.def == defToCompare && mP.Position.InHorDistOf(pawn.Position, (float)this.Props.spawnMaxAdjacent);
|
||||
}).Count<Pawn>() >= this.Props.spawnMaxAdjacent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.Props.animalToSpawn == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Faction faction = this.Props.factionOfPlayerAnimal ? Faction.OfPlayer : null;
|
||||
int i = 0;
|
||||
while (i < this.calculatedQuantity)
|
||||
{
|
||||
IntVec3 intVec;
|
||||
if (!this.TryFindSpawnCell(out intVec))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Pawn pawn2 = PawnGenerator.GeneratePawn(this.Props.animalToSpawn, faction);
|
||||
if (pawn2 == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GenSpawn.Spawn(pawn2, intVec, pawn.Map, WipeMode.Vanish);
|
||||
pawn2.SetFaction(faction, null);
|
||||
FilthMaker.TryMakeFilth(intVec, pawn.Map, ThingDefOf.Filth_AmnioticFluid, pawn.LabelIndefinite(), 5, FilthSourceFlags.None);
|
||||
if (!this.Props.spawnForbidden)
|
||||
{
|
||||
pawn2.playerSettings.Master = pawn;
|
||||
pawn2.training.Train(TrainableDefOf.Obedience, pawn, true);
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (PawnUtility.ShouldSendNotificationAbout(pawn) || PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||
{
|
||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.PositiveEvent, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 重新设计物品生成逻辑:按优先级顺序尝试
|
||||
return TrySpawnItemWithPriority(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:按优先级顺序尝试生成物品
|
||||
private bool TrySpawnItemWithPriority(Pawn pawn)
|
||||
{
|
||||
Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null);
|
||||
if (thing == null)
|
||||
{
|
||||
Tools.Warn("Failed to create thing: " + this.Props.thingToSpawn?.defName, this.myDebug);
|
||||
return false;
|
||||
}
|
||||
thing.stackCount = this.calculatedQuantity;
|
||||
|
||||
// 记录原始物品用于校验
|
||||
ThingDef originalThingDef = thing.def;
|
||||
int originalStackCount = thing.stackCount;
|
||||
|
||||
// 按优先级顺序尝试生成
|
||||
bool success = false;
|
||||
string spawnMethod = "";
|
||||
|
||||
// 优先级1: 尝试在pawn附近空地生成
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnAtNearbyEmptyCell(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 优先级2: 尝试在pawn脚底生成
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnAtPawnPosition(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 优先级3: 尝试放入pawn物品栏
|
||||
if (!success)
|
||||
{
|
||||
success = TrySpawnInInventory(pawn, thing, ref spawnMethod);
|
||||
}
|
||||
|
||||
// 生成后校验
|
||||
if (success)
|
||||
{
|
||||
bool verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, spawnMethod);
|
||||
|
||||
// 如果校验失败且不是在物品栏中生成的,尝试在物品栏中重新生成
|
||||
if (!verified && spawnMethod != "inventory")
|
||||
{
|
||||
Tools.Warn($"Spawn verification failed for {spawnMethod}, attempting inventory fallback", this.myDebug);
|
||||
|
||||
// 重新创建物品
|
||||
Thing fallbackThing = ThingMaker.MakeThing(originalThingDef, null);
|
||||
fallbackThing.stackCount = originalStackCount;
|
||||
|
||||
success = TrySpawnInInventory(pawn, fallbackThing, ref spawnMethod);
|
||||
|
||||
if (success)
|
||||
{
|
||||
verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, "inventory_fallback");
|
||||
if (!verified)
|
||||
{
|
||||
Tools.Warn("Inventory fallback also failed verification", this.myDebug);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success && verified)
|
||||
{
|
||||
if (PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||
{
|
||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")),
|
||||
spawnMethod == "inventory" || spawnMethod == "inventory_fallback" ? pawn : thing,
|
||||
MessageTypeDefOf.PositiveEvent, true);
|
||||
}
|
||||
Tools.Warn($"Successfully spawned {originalStackCount}x {originalThingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Tools.Warn($"Failed to spawn {originalStackCount}x {originalThingDef.defName} after all attempts", this.myDebug);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在附近空地生成
|
||||
private bool TrySpawnAtNearbyEmptyCell(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
IntVec3 spawnCell;
|
||||
if (TryFindSpawnCell(out spawnCell))
|
||||
{
|
||||
if (this.Props.spawnForbidden)
|
||||
{
|
||||
thing.SetForbidden(true, true);
|
||||
}
|
||||
|
||||
if (GenPlace.TryPlaceThing(thing, spawnCell, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
||||
{
|
||||
spawnMethod = "nearby_cell";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在pawn位置生成
|
||||
private bool TrySpawnAtPawnPosition(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
IntVec3 pawnPosition = pawn.Position;
|
||||
if (pawnPosition.IsValid && pawnPosition.Walkable(pawn.Map))
|
||||
{
|
||||
if (this.Props.spawnForbidden)
|
||||
{
|
||||
thing.SetForbidden(true, true);
|
||||
}
|
||||
|
||||
if (GenPlace.TryPlaceThing(thing, pawnPosition, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
||||
{
|
||||
spawnMethod = "pawn_position";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:尝试在物品栏生成
|
||||
private bool TrySpawnInInventory(Pawn pawn, Thing thing, ref string spawnMethod)
|
||||
{
|
||||
if (pawn.inventory == null)
|
||||
{
|
||||
Tools.Warn($"Pawn {pawn.Label} does not have an inventory", this.myDebug);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pawn.inventory.innerContainer.TryAdd(thing))
|
||||
{
|
||||
spawnMethod = "inventory";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新增:生成后校验
|
||||
private bool VerifySpawnSuccess(Pawn pawn, ThingDef thingDef, int expectedCount, string spawnMethod)
|
||||
{
|
||||
bool verificationSuccess = false;
|
||||
|
||||
switch (spawnMethod)
|
||||
{
|
||||
case "nearby_cell":
|
||||
case "pawn_position":
|
||||
case "inventory_fallback":
|
||||
// 检查地图上是否有生成的物品
|
||||
verificationSuccess = pawn.Map.listerThings.ThingsOfDef(thingDef)
|
||||
.Any(t => t.stackCount >= expectedCount && t.Position.InHorDistOf(pawn.Position, 2f));
|
||||
break;
|
||||
|
||||
case "inventory":
|
||||
// 检查物品栏中是否有生成的物品
|
||||
verificationSuccess = pawn.inventory.innerContainer.Any(t => t.def == thingDef && t.stackCount >= expectedCount);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!verificationSuccess)
|
||||
{
|
||||
Tools.Warn($"Spawn verification failed for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tools.Warn($"Spawn verification successful for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||
}
|
||||
|
||||
return verificationSuccess;
|
||||
}
|
||||
|
||||
private bool TryFindSpawnCell(out IntVec3 result)
|
||||
{
|
||||
result = IntVec3.Invalid;
|
||||
bool result2;
|
||||
if (this.pawn == null)
|
||||
{
|
||||
result2 = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Map map = this.pawn.Map;
|
||||
if (map == null)
|
||||
{
|
||||
result2 = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 修改这里:将半径从5减少到2,让生成位置更靠近pawn
|
||||
int searchRadius = 2;
|
||||
|
||||
// 首先尝试在pawn的相邻单元格生成(半径为1)
|
||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null);
|
||||
|
||||
// 如果相邻单元格找不到合适位置,再尝试稍远一点(半径为2)
|
||||
if (!result.IsValid)
|
||||
{
|
||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null);
|
||||
}
|
||||
|
||||
// 如果还是找不到,尝试pawn当前位置(作为最后手段)
|
||||
if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map))
|
||||
{
|
||||
result = this.pawn.Position;
|
||||
}
|
||||
|
||||
result2 = result.IsValid;
|
||||
}
|
||||
}
|
||||
return result2;
|
||||
}
|
||||
|
||||
|
||||
private void ResetCountdown()
|
||||
{
|
||||
this.ticksUntilSpawn = (int)(this.RandomDays2wait() * 60000f);
|
||||
this.initialTicksUntilSpawn = this.ticksUntilSpawn;
|
||||
}
|
||||
|
||||
private float RandomDays2wait()
|
||||
{
|
||||
return Rand.Range(this.calculatedMinDaysB4Next, this.calculatedMaxDaysB4Next);
|
||||
}
|
||||
|
||||
private float RandomGraceDays()
|
||||
{
|
||||
return Rand.Range(this.Props.graceDays / 2f, this.Props.graceDays);
|
||||
}
|
||||
|
||||
public override string CompTipStringExtra
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.myDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string text = "ticksUntilSpawn: " + this.ticksUntilSpawn.ToString() + "\n";
|
||||
string text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"initialTicksUntilSpawn: ",
|
||||
this.initialTicksUntilSpawn.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"graceTicks: ",
|
||||
this.graceTicks.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"hunger resets: ",
|
||||
this.hungerReset.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"health resets: ",
|
||||
this.healthReset.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedMinDaysB4Next: ",
|
||||
this.calculatedMinDaysB4Next.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedMaxDaysB4Next: ",
|
||||
this.calculatedMaxDaysB4Next.ToString(),
|
||||
"\n"
|
||||
});
|
||||
text2 = text;
|
||||
text = string.Concat(new string[]
|
||||
{
|
||||
text2,
|
||||
"calculatedQuantity: ",
|
||||
this.calculatedQuantity.ToString(),
|
||||
"\n"
|
||||
});
|
||||
return text + "blockSpawn: " + this.blockSpawn.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private int ticksUntilSpawn;
|
||||
|
||||
private int initialTicksUntilSpawn;
|
||||
|
||||
private int hungerReset;
|
||||
|
||||
private int healthReset;
|
||||
|
||||
private int graceTicks;
|
||||
|
||||
private Pawn pawn;
|
||||
|
||||
private float calculatedMaxDaysB4Next = 2f;
|
||||
|
||||
private float calculatedMinDaysB4Next = 1f;
|
||||
|
||||
private int calculatedQuantity = 1;
|
||||
|
||||
private bool blockSpawn;
|
||||
|
||||
private bool myDebug;
|
||||
|
||||
private readonly float errorMinDaysB4Next = 0.001f;
|
||||
|
||||
private readonly int errorExponentialLimit = 20;
|
||||
|
||||
private readonly int errorSpawnCount = 750;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm.MoharHediffs
|
||||
{
|
||||
public static class Tools
|
||||
{
|
||||
public static void DestroyParentHediff(Hediff parentHediff, bool debug = false)
|
||||
{
|
||||
if (parentHediff.pawn != null && parentHediff.def.defName != null && debug)
|
||||
{
|
||||
ArachnaeLog.Debug(parentHediff.pawn.Label + "'s Hediff: " + parentHediff.def.defName + " says goodbye.");
|
||||
}
|
||||
parentHediff.Severity = 0f;
|
||||
}
|
||||
|
||||
public static float GetPawnAgeOverlifeExpectancyRatio(Pawn pawn, bool debug = false)
|
||||
{
|
||||
float result = 1f;
|
||||
if (pawn == null)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
ArachnaeLog.Debug("GetPawnAgeOverlifeExpectancyRatio pawn NOT OK");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
result = pawn.ageTracker.AgeBiologicalYearsFloat / pawn.RaceProps.lifeExpectancy;
|
||||
if (debug)
|
||||
{
|
||||
ArachnaeLog.Debug(string.Concat(new string[]
|
||||
{
|
||||
pawn.Label,
|
||||
" Age: ",
|
||||
pawn.ageTracker.AgeBiologicalYearsFloat.ToString(),
|
||||
"; lifeExpectancy: ",
|
||||
pawn.RaceProps.lifeExpectancy.ToString(),
|
||||
"; ratio:",
|
||||
result.ToString()
|
||||
}));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool IsInjured(this Pawn pawn, bool debug = false)
|
||||
{
|
||||
if (pawn == null)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
ArachnaeLog.Debug("pawn is null - wounded ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
float num = 0f;
|
||||
List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
|
||||
for (int i = 0; i < hediffs.Count; i++)
|
||||
{
|
||||
if (hediffs[i] is Hediff_Injury && !hediffs[i].IsPermanent())
|
||||
{
|
||||
num += hediffs[i].Severity;
|
||||
}
|
||||
}
|
||||
if (debug && num > 0f)
|
||||
{
|
||||
ArachnaeLog.Debug(pawn.Label + " is wounded ");
|
||||
}
|
||||
return num > 0f;
|
||||
}
|
||||
|
||||
public static bool IsHungry(this Pawn pawn, bool debug = false)
|
||||
{
|
||||
if (pawn == null)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
ArachnaeLog.Debug("pawn is null - IsHungry ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool flag = pawn.needs.food != null && pawn.needs.food.CurCategory == HungerCategory.Starving;
|
||||
if (debug && flag)
|
||||
{
|
||||
ArachnaeLog.Debug(pawn.Label + " is hungry ");
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
public static bool OkPawn(Pawn pawn)
|
||||
{
|
||||
return pawn != null && pawn.Map != null;
|
||||
}
|
||||
|
||||
public static void Warn(string warning, bool debug = false)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
ArachnaeLog.Debug(warning);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user