52 Commits

Author SHA1 Message Date
ProjectKoi-Kalo\Kalo
929d362856 织域种 2025-09-11 21:48:48 +08:00
ProjectKoi-Kalo\Kalo
a114b6f037 暂存 2025-09-11 21:35:47 +08:00
ProjectKoi-Kalo\Kalo
8cbd09e036 暂存 2025-09-11 21:12:51 +08:00
ProjectKoi-Kalo\Kalo
f3d6c4e35e 暂存 2025-09-11 21:02:32 +08:00
ProjectKoi-Kalo\Kalo
f55952befc 暂存 2025-09-11 20:57:42 +08:00
ProjectKoi-Kalo\Kalo
6c1e7743dc 暂存 2025-09-11 19:47:02 +08:00
ProjectKoi-Kalo\Kalo
dede557c05 暂存 2025-09-11 18:56:31 +08:00
ProjectKoi-Kalo\Kalo
c102458a43 暂存 2025-09-11 18:38:21 +08:00
Tourswen
f815e468eb 对营养值和花费的调整 2025-09-11 08:37:52 +08:00
Tourswen
505076b835 空天种完成 2025-09-10 23:53:25 +08:00
ProjectKoi-Kalo\Kalo
2bd1f6260f 存去掉随机似 2025-09-10 19:31:06 +08:00
ProjectKoi-Kalo\Kalo
458e9b313b 暂存去掉急救标 2025-09-10 19:24:03 +08:00
ProjectKoi-Kalo\Kalo
2a70345b8e 暂存 2025-09-10 19:21:42 +08:00
ProjectKoi-Kalo\Kalo
f531d0a136 暂存拟线虫药物 2025-09-10 19:08:42 +08:00
ProjectKoi-Kalo\Kalo
d31f5c616a 暂存工作寄生体 2025-09-10 18:21:33 +08:00
ProjectKoi-Kalo\Kalo
d18f489113 暂存 2025-09-10 17:41:53 +08:00
Tourswen
12e860d637 修复督虫出生就超过预定年龄的问题 2025-09-10 17:30:02 +08:00
ProjectKoi-Kalo\Kalo
09fd8c2c82 Merge branch '拟线种' 2025-09-10 15:00:54 +08:00
ProjectKoi-Kalo\Kalo
a072b7c532 暂存 2025-09-10 15:00:11 +08:00
ProjectKoi-Kalo\Kalo
250844ab00 暂存3 2025-09-10 14:47:33 +08:00
ProjectKoi-Kalo\Kalo
26dba2f16b 暂存2 2025-09-10 14:41:40 +08:00
ProjectKoi-Kalo\Kalo
17722d473a 暂存 2025-09-10 13:13:41 +08:00
ProjectKoi-Kalo\Kalo
ef14ad1caf 暂存 2025-09-10 12:38:56 +08:00
ProjectKoi-Kalo\Kalo
6fe5db0b4f 暂存3 2025-09-10 12:22:03 +08:00
ProjectKoi-Kalo\Kalo
5ed1b3ec62 暂存 2025-09-10 12:17:47 +08:00
ProjectKoi-Kalo\Kalo
cc5206c3c6 暂存 2025-09-10 12:14:30 +08:00
Tourswen
7da13bd49d 描述 2025-09-10 12:00:11 +08:00
ProjectKoi-Kalo\Kalo
54de15873f 暂存 2025-09-10 11:25:51 +08:00
Tourswen
ee48fb4491 描述修改,给冲撞增加前置 2025-09-10 10:43:35 +08:00
Tourswen
64fd63796d 各种描述修改,两个水货武器,科技调整,完善升级树,将武器标签系统搬过来 2025-09-10 10:01:21 +08:00
ProjectKoi-Kalo\Kalo
12ea403c97 暂存 2025-09-10 01:02:08 +08:00
ProjectKoi-Kalo\Kalo
c9fd2e8844 Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-09 23:54:51 +08:00
ProjectKoi-Kalo\Kalo
f3fb6122e3 暂存 2025-09-09 23:54:48 +08:00
Tourswen
72fbec8d21 Update ArachnaeNode_Race_Addons_Skyraider_Wing_south.sai2 2025-09-09 23:47:00 +08:00
Tourswen
c2299e22e6 杂七杂八的调整 2025-09-09 23:46:51 +08:00
ProjectKoi-Kalo\Kalo
d1f9e7f17a 虫肉虫肉 2025-09-09 23:18:27 +08:00
ProjectKoi-Kalo\Kalo
19de1bfd8f Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-09 17:51:22 +08:00
ProjectKoi-Kalo\Kalo
de5c7412b3 虫烟 2025-09-09 17:51:20 +08:00
Tourswen
770f81e4c8 科技和虫卵 2025-09-09 17:32:27 +08:00
ProjectKoi-Kalo\Kalo
6e9b0829b7 暂存 2025-09-09 15:15:34 +08:00
ProjectKoi-Kalo\Kalo
6694ff2d62 存天巢种 2025-09-09 14:56:06 +08:00
ProjectKoi-Kalo\Kalo
b1a0a35b94 Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-09 12:44:49 +08:00
ProjectKoi-Kalo\Kalo
17cdfd07eb 暂存 2025-09-09 12:44:47 +08:00
Tourswen
54ad384068 大型虫族的确立 2025-09-09 12:00:40 +08:00
Tourswen
d18e70f2e4 将所有的verb从乌拉迁移(不包括咖喱棒) 2025-09-09 11:05:06 +08:00
Tourswen
025881a310 将种族限定区域hediff挪过来 2025-09-09 10:56:15 +08:00
Tourswen
6b8fb58777 Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-09 01:14:39 +08:00
Tourswen
3add58d294 浓雾种 2025-09-09 01:12:18 +08:00
ProjectKoi-Kalo\Kalo
501bc91e35 Merge branch '空天种' 2025-09-08 23:36:01 +08:00
Tourswen
6516871763 生物孵化池的立绘 2025-09-08 22:16:09 +08:00
Tourswen
a136c0eb50 Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-08 19:21:43 +08:00
Tourswen
42a96c6cfb 修改茧名字,修改产物速率,修改菌毯减速 2025-09-08 19:21:27 +08:00
123 changed files with 9382 additions and 1456 deletions

Binary file not shown.

View File

@@ -31,6 +31,97 @@
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_TumorSpew</defName>
<label>菌瘤释放</label>
<description>排出一枚菌瘤,将附近的大片地区转变为菌毯地形,以方便虫群进行活动,并阻碍敌军的前进。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<cooldownTicksRange>5000</cooldownTicksRange>
<aiCanUse>false</aiCanUse>
<displayOrder>300</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<targetRequired>false</targetRequired>
<hostile>false</hostile>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>13</range>
<warmupTime>1</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetable>false</targetable>
<drawAimPie>false</drawAimPie>
<targetParams>
<canTargetSelf>True</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.2</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_Tumor</projectileDef>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_EggSpew_Base_Proj">
<defName>ARA_Proj_Tumor</defName>
<label>阿拉克涅菌瘤</label>
<projectile>
<spawnsThingDef>ARA_Tumor_Smokepop</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="BuildingNaturalBase">
<defName>ARA_Tumor_Smokepop</defName>
<label>阿拉克涅枯萎菌瘤</label>
<description>由少数虫族排出的特殊菌瘤,除了照明外还会在地上大范围地扩散菌毯,但是很快就会枯死。</description>
<thingClass>Building</thingClass>
<!-- <minifiedDef>MinifiedThing</minifiedDef> -->
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<selectable>true</selectable>
<fillPercent>0.20</fillPercent>
<leaveResourcesWhenKilled>false</leaveResourcesWhenKilled>
<rotatable>false</rotatable>
<tickerType>Normal</tickerType>
<repairEffect>EatVegetarian</repairEffect>
<filthLeaving>Filth_Slime</filthLeaving>
<statBases>
<MaxHitPoints>10</MaxHitPoints>
<Mass>4</Mass>
<Flammability>1.0</Flammability>
<MarketValue>50</MarketValue>
</statBases>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_Tumor</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.2</drawSize>
<shadowData>
<volume>(0.3, 0.6, 0.3)</volume>
<offset>(0,0,-0.1)</offset>
</shadowData>
</graphicData>
<placeWorkers>
<li>PlaceWorker_GlowRadius</li>
</placeWorkers>
<comps>
<li Class="CompProperties_Glower">
<glowRadius>13</glowRadius>
<glowColor>(220,210,171,0)</glowColor>
</li>
<li Class="CompProperties_Lifespan">
<lifespanTicks>9000</lifespanTicks>
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>13</spawnRadius>
</li>
</comps>
</ThingDef>
<AbilityDef>
<defName>ARA_AcidSprayBurst_Queen</defName>
@@ -106,7 +197,6 @@
<filthChance>0.25</filthChance>
</projectile>
</ThingDef>
<AbilityDef>
<defName>ARA_AcidSprayBurst</defName>
<label>酸液轰炸</label>
@@ -151,6 +241,7 @@
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_Toxic_Needle_Fire</defName>
<label>毒针连射</label>
@@ -221,7 +312,7 @@
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.5</needCost>
<needCost>0.2</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
</comps>
@@ -244,6 +335,77 @@
</projectile>
</ThingDef>
<AbilityDef>
<defName>ARA_BaseRace_Skyhive_Launcher</defName>
<label>天巢种喷射巢</label>
<description>将三只阿拉克涅天巢种辅虫发射到目标身上,天巢种将附着到敌人身上撕咬,脱落后仍然能继续对敌人展开攻击。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<cooldownTicksRange>5000</cooldownTicksRange>
<aiCanUse>true</aiCanUse>
<displayOrder>300</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<charges>3</charges>
<cooldownPerCharge>true</cooldownPerCharge>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>24</range>
<warmupTime>1</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetParams>
<canTargetPawns>True</canTargetPawns>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityLaunchMultiProjectile">
<projectileDef>Bullet_ARA_RW_Basic_SkyHive_Gun</projectileDef>
<numProjectiles>3</numProjectiles>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.2</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
</comps>
</AbilityDef>
<AbilityDef Name="LongJump">
<defName>ARA_Skyraider_jump</defName>
<label>高空机动</label>
<description>使用强壮的翅膀瞬间加力,以重定位至一处新的地点。</description>
<iconPath>UI/Abilities/Longjump</iconPath>
<cooldownTicksRange>5000</cooldownTicksRange>
<hostile>false</hostile>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<charges>2</charges>
<cooldownPerCharge>true</cooldownPerCharge>
<verbProperties>
<verbClass>Verb_CastAbilityJump</verbClass>
<label>jump</label>
<violent>false</violent>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>0</warmupTime>
<range>150</range>
<requireLineOfSight>true</requireLineOfSight>
<soundCast>Longjump_Jump</soundCast>
<soundLanding>Longjump_Land</soundLanding>
<targetParams>
<canTargetLocations>true</canTargetLocations>
<canTargetPawns>false</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
</targetParams>
</verbProperties>
<jobDef>CastJump</jobDef>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.3</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_Ability_Possess</defName>
<label>原虫种突袭寄生</label>
@@ -283,4 +445,109 @@
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_Ability_Smokepop</defName>
<label>信息素浓雾释放</label>
<description>浓雾种将其腹部的大量释放阿拉克涅信息素烟雾,形成一大片足以遮蔽虫族身形的烟雾,并防止敌方使用火焰武器点燃虫族集群。这些信息素会吸引附近的阿拉克涅辅虫破土而出支援虫群,沾染信息素的目标越多(无论敌我),前来支援的虫族就越多。</description>
<iconPath>UI/Abilities/MechSmokepop</iconPath>
<cooldownTicksRange>6000</cooldownTicksRange>
<targetRequired>false</targetRequired>
<hostile>false</hostile>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<warmupTime>1</warmupTime>
<range>10</range>
<drawAimPie>false</drawAimPie>
<targetParams>
<canTargetSelf>true</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.25</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
<!--<li Class="CompProperties_AbilityFirefoampop">
<firefoamRadius>10</firefoamRadius>
<clamorType>Ability</clamorType>
<clamorRadius>15</clamorRadius>
</li>-->
<li Class="ArachnaeSwarm.CompProperties_AbilityDRM_Deaddustpop">
<damageDef>ARA_ReinforceGas</damageDef>
<damageAmount>5</damageAmount>
<armorPenetration>2.0</armorPenetration>
<smokeRadius>10</smokeRadius>
<explosionSound>Explosion_Smoke</explosionSound>
<clamorType>Ability</clamorType>
<clamorRadius>15</clamorRadius>
<postExplosionSpawnThingDef>ARA_ReinforceGasCloud</postExplosionSpawnThingDef> <!-- ARL_ToxicGasCloud -->
<postExplosionSpawnChance>1</postExplosionSpawnChance>
<postExplosionSpawnThingCount>1</postExplosionSpawnThingCount>
</li>
<!-- <li Class="ArachnaeSwarm.CompProperties_AbilityBodyPartCheck">
<requiredPart>ARA_Toxic_Needle</requiredPart>
<failMessage>毒针腺受损或缺失,无法发射毒针</failMessage>
</li> -->
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_Ability_TrackingCharge</defName>
<label>蛮力冲撞</label>
<description>阿拉克涅盾头种对目标发起蓄势冲撞,对路径上的一切造成伤害。在冲击中途经的距离越远,伤害越高。</description>
<iconPath>UI/Commands/WarTrumpet</iconPath> <!-- Placeholder Icon -->
<cooldownTicksRange>6000</cooldownTicksRange>
<charges>3</charges>
<cooldownPerCharge>true</cooldownPerCharge>
<verbProperties>
<verbClass>ArachnaeSwarm.Verb_CastAbilityTrackingCharge</verbClass>
<label>追踪冲撞</label>
<targetParams>
<canTargetPawns>true</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
<canTargetAnimals>true</canTargetAnimals>
<canTargetMechs>true</canTargetMechs>
<canTargetSelf>false</canTargetSelf>
</targetParams>
<range>30</range>
<warmupTime>1.0</warmupTime>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_TrackingCharge">
<homingSpeed>1.5</homingSpeed>
<initialDamage>15</initialDamage>
<damagePerTile>1.5</damagePerTile>
<inertiaDistance>6</inertiaDistance>
<collisionDamageDef>Blunt</collisionDamageDef>
<flyerDef>ARA_Flyer_TrackingCharge</flyerDef>
<collisionRadius>1.5</collisionRadius> <!-- Larger collision radius -->
<impactSound>Pawn_Melee_BigBash_HitPawn</impactSound>
<damageHostileOnly>true</damageHostileOnly> <!-- Set to false to damage everyone in the path -->
</li>
<li Class="CompProperties_AbilityEffecterOnCaster">
<effecterDef>WarTrumpet</effecterDef>
<maintainTicks>20</maintainTicks> <!-- Long enough for the "2nd wave" to spawn -->
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_1VTE</requiredResearch>
<failMessage>需要科技 基因节点VTE-1"爆发激素" 以解锁技能</failMessage>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.2</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="PawnFlyerBase">
<defName>ARA_Flyer_TrackingCharge</defName>
<thingClass>ArachnaeSwarm.PawnFlyer_TrackingCharge</thingClass>
<pawnFlyer>
<flightSpeed>0.5</flightSpeed>
<heightFactor>0</heightFactor>
</pawnFlyer>
</ThingDef>
</Defs>

View File

@@ -73,7 +73,7 @@
<label>阿拉克涅孵化茧</label>
<thingClass>Projectile_SpawnsThing</thingClass>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_BioforgeIncubator</texPath>
<texPath>ArachnaeSwarm/Building/ARA_Cocoon</texPath>
<graphicClass>Graphic_Single</graphicClass>
</graphicData>
<projectile>
@@ -84,10 +84,11 @@
</projectile>
</ThingDef>
<!-- T0 -->
<AbilityDef ParentName="ARA_EggSpew_Base">
<defName>ARA_EggSpew</defName>
<label>生育虫卵</label>
<description>从卵巢中排出一颗休眠的虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点。</description>
<description>从卵巢中排出一颗休眠的虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点。\n\n该虫卵只能孵化小型虫族。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
@@ -95,4 +96,38 @@
</li>
</comps>
</AbilityDef>
<AbilityDef ParentName="ARA_EggSpew_Base">
<defName>ARA_EggSpew_Huge</defName>
<label>生育大型虫卵</label>
<description>从卵巢中排出一颗休眠的大型虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点。\n\n该虫卵只能孵化大型虫族。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_EggSac_Huge</projectileDef>
</li>
</comps>
</AbilityDef>
<!-- T1 -->
<AbilityDef ParentName="ARA_EggSpew_Base">
<defName>ARA_EggSpew_1Stage</defName>
<label>生育虫卵——等级1</label>
<description>从卵巢中排出一颗休眠的虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点。\n\n该虫卵只能孵化小型虫族。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_EggSac_1Stage</projectileDef>
</li>
</comps>
</AbilityDef>
<AbilityDef ParentName="ARA_EggSpew_Base">
<defName>ARA_EggSpew_Huge_1Stage</defName>
<label>生育大型虫卵——等级1</label>
<description>从卵巢中排出一颗休眠的大型虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点。\n\n该虫卵只能孵化大型虫族。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_EggSac_Huge_1Stage</projectileDef>
</li>
</comps>
</AbilityDef>
</Defs>

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- 1. Definition for the PawnFlyer itself -->
<ThingDef ParentName="PawnFlyerBase">
<defName>ARA_Flyer_TrackingCharge</defName>
<thingClass>ArachnaeSwarm.PawnFlyer_TrackingCharge</thingClass>
<pawnFlyer>
<flightSpeed>0.5</flightSpeed>
<heightFactor>0</heightFactor>
</pawnFlyer>
</ThingDef>
<!-- 2. The final Ability Definition -->
<AbilityDef>
<defName>ARA_Ability_TrackingCharge</defName>
<label>追踪冲撞</label>
<description>阿拉克涅盾头种对目标发起蓄势冲撞,对路径上的一切造成伤害。飞行的距离越远,伤害越高。</description>
<iconPath>UI/Commands/WarTrumpet</iconPath> <!-- Placeholder Icon -->
<cooldownTicksRange>600</cooldownTicksRange>
<verbProperties>
<verbClass>ArachnaeSwarm.Verb_CastAbilityTrackingCharge</verbClass>
<label>追踪冲撞</label>
<targetParams>
<canTargetPawns>true</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
<canTargetAnimals>true</canTargetAnimals>
<canTargetMechs>true</canTargetMechs>
<canTargetSelf>false</canTargetSelf>
</targetParams>
<range>30</range>
<warmupTime>1.0</warmupTime>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_TrackingCharge">
<homingSpeed>1.5</homingSpeed>
<initialDamage>15</initialDamage>
<damagePerTile>2</damagePerTile>
<inertiaDistance>6</inertiaDistance>
<collisionDamageDef>Blunt</collisionDamageDef>
<flyerDef>ARA_Flyer_TrackingCharge</flyerDef>
<collisionRadius>1.5</collisionRadius> <!-- Larger collision radius -->
<impactSound>Pawn_Melee_BigBash_HitPawn</impactSound>
<damageHostileOnly>true</damageHostileOnly> <!-- Set to false to damage everyone in the path -->
</li>
<li Class="CompProperties_AbilityEffecterOnCaster">
<effecterDef>WarTrumpet</effecterDef>
<maintainTicks>20</maintainTicks> <!-- Long enough for the "2nd wave" to spawn -->
</li>
</comps>
</AbilityDef>
</Defs>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- 变形技能的定义 -->
<AbilityDef>
<defName>ARA_Ability_Morph</defName>
<label>织域形态</label>
<description>将自己转换为一个坚固的静态建筑形态,或从建筑形态恢复。</description>
<iconPath>UI/Commands/EggSpew</iconPath> <!-- TODO: 替换为你的图标路径 -->
<cooldownTicksRange>6000</cooldownTicksRange>
<hotKey>Misc12</hotKey>
<targetRequired>false</targetRequired>
<casterMustBeCapableOfViolence>false</casterMustBeCapableOfViolence>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<drawAimPie>false</drawAimPie>
<requireLineOfSight>false</requireLineOfSight>
<nonInterruptingSelfCast>true</nonInterruptingSelfCast>
<warmupTime>1</warmupTime>
<range>19.9</range>
<targetable>false</targetable>
<targetParams>
<canTargetSelf>True</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityTransform">
<buildingDef>ARA_MorphableResearchBench</buildingDef>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="BuildingBase">
<defName>ARA_MorphableResearchBench</defName>
<hasInteractionCell>true</hasInteractionCell>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<label>阿拉克涅织域织座</label>
<description>一个供阿拉克涅虫族进行研究的活体结构,可以让虫群尽情地探索变异和进化方向。其研究能力完全取决于内部的阿拉克涅织域种。</description>
<thingClass>ArachnaeSwarm.Building_Morphable</thingClass>
<tickerType>Normal</tickerType>
<size>(3,3)</size>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_ResearchBench</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(3,4.5)</drawSize>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>Impassable</passability>
<castEdgeShadows>false</castEdgeShadows>
<fillPercent>0.8</fillPercent>
<staticSunShadowHeight>0</staticSunShadowHeight>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<statBases>
<MaxHitPoints>1000</MaxHitPoints>
<WorkToBuild>2800</WorkToBuild>
<Flammability>1.0</Flammability>
<ResearchSpeedFactor>1.0</ResearchSpeedFactor>
</statBases>
<uiOrder>2600</uiOrder>
<surfaceType>Item</surfaceType>
<building>
<workTableRoomRole>Laboratory</workTableRoomRole>
<workTableNotInRoomRoleFactor>0.8</workTableNotInRoomRoleFactor>
<deconstructible>false</deconstructible>
</building>
<!-- 不可建造,只能通过变形生成 -->
<comps Inherit="False">
<li Class="CompProperties_ReportWorkSpeed">
<workSpeedStat>ResearchSpeedFactor</workSpeedStat>
</li>
<li Class="ArachnaeSwarm.CompProperties_Morphable">
<restGainMultiplier>1.0</restGainMultiplier>
</li>
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelCapacity>10.0</fuelCapacity>
<targetFuelLevelConfigurable>false</targetFuelLevelConfigurable>
<fuelGizmoLabel>营养</fuelGizmoLabel>
<outOfFuelMessage>没有营养</outOfFuelMessage>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -8,14 +8,15 @@
<key>ARA_Flight_Attachment</key>
<value>
<keyframes>
<li><graphicState>ARA_FlyEast_0</graphicState><tick>0</tick></li>
<li><graphicState>ARA_FlyEast_1</graphicState><tick>4</tick></li>
<li><graphicState>ARA_FlyEast_2</graphicState><tick>8</tick></li>
<li><graphicState>ARA_FlyEast_3</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlyEast_4</graphicState><tick>16</tick></li>
<li><graphicState>ARA_FlyEast_5</graphicState><tick>20</tick></li>
<li><graphicState>ARA_FlyEast_6</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlyEast_7</graphicState><tick>28</tick></li>
<li><graphicState>ARA_FlyEast_0</graphicState><tick>6</tick></li>
<li><graphicState>ARA_FlyEast_1</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlyEast_2</graphicState><tick>18</tick></li>
<li><graphicState>ARA_FlyEast_3</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlyEast_4</graphicState><tick>32</tick></li>
<li><graphicState>ARA_FlyEast_3</graphicState><tick>48</tick></li>
<li><graphicState>ARA_FlyEast_2</graphicState><tick>52</tick></li>
<li><graphicState>ARA_FlyEast_1</graphicState><tick>58</tick></li>
<li><graphicState>ARA_FlyEast_0</graphicState><tick>60</tick></li>
</keyframes>
</value>
</li>
@@ -38,14 +39,15 @@
<key>ARA_Flight_Attachment</key>
<value>
<keyframes>
<li><graphicState>ARA_FlyNorth_0</graphicState><tick>0</tick></li>
<li><graphicState>ARA_FlyNorth_1</graphicState><tick>4</tick></li>
<li><graphicState>ARA_FlyNorth_2</graphicState><tick>8</tick></li>
<li><graphicState>ARA_FlyNorth_3</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlyNorth_4</graphicState><tick>16</tick></li>
<li><graphicState>ARA_FlyNorth_5</graphicState><tick>20</tick></li>
<li><graphicState>ARA_FlyNorth_6</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlyNorth_7</graphicState><tick>28</tick></li>
<li><graphicState>ARA_FlyNorth_0</graphicState><tick>6</tick></li>
<li><graphicState>ARA_FlyNorth_1</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlyNorth_2</graphicState><tick>18</tick></li>
<li><graphicState>ARA_FlyNorth_3</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlyNorth_4</graphicState><tick>32</tick></li>
<li><graphicState>ARA_FlyNorth_3</graphicState><tick>48</tick></li>
<li><graphicState>ARA_FlyNorth_2</graphicState><tick>52</tick></li>
<li><graphicState>ARA_FlyNorth_1</graphicState><tick>58</tick></li>
<li><graphicState>ARA_FlyNorth_0</graphicState><tick>60</tick></li>
</keyframes>
</value>
</li>
@@ -68,14 +70,15 @@
<key>ARA_Flight_Attachment</key>
<value>
<keyframes>
<li><graphicState>ARA_FlySouth_0</graphicState><tick>0</tick></li>
<li><graphicState>ARA_FlySouth_1</graphicState><tick>4</tick></li>
<li><graphicState>ARA_FlySouth_2</graphicState><tick>8</tick></li>
<li><graphicState>ARA_FlySouth_3</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlySouth_4</graphicState><tick>16</tick></li>
<li><graphicState>ARA_FlySouth_5</graphicState><tick>20</tick></li>
<li><graphicState>ARA_FlySouth_6</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlySouth_7</graphicState><tick>28</tick></li>
<li><graphicState>ARA_FlySouth_0</graphicState><tick>6</tick></li>
<li><graphicState>ARA_FlySouth_1</graphicState><tick>12</tick></li>
<li><graphicState>ARA_FlySouth_2</graphicState><tick>18</tick></li>
<li><graphicState>ARA_FlySouth_3</graphicState><tick>24</tick></li>
<li><graphicState>ARA_FlySouth_4</graphicState><tick>32</tick></li>
<li><graphicState>ARA_FlySouth_3</graphicState><tick>48</tick></li>
<li><graphicState>ARA_FlySouth_2</graphicState><tick>52</tick></li>
<li><graphicState>ARA_FlySouth_1</graphicState><tick>58</tick></li>
<li><graphicState>ARA_FlySouth_0</graphicState><tick>60</tick></li>
</keyframes>
</value>
</li>

View File

@@ -35,7 +35,21 @@
<Intellectual>3</Intellectual>
<Social>3</Social>
</skillGains>
<workDisables>ManualDumb,Mining,PlantWork,Animals,Crafting,Cooking,Constructing,Hunting</workDisables>
<workDisables>
<li>Cleaning</li>
<li>Hauling</li>
<li>Mining</li>
<li>PlantWork</li>
<li>Animals</li>
<li>Hunting</li>
<li>Crafting</li>
<li>Cooking</li>
<!-- <li>Constructing</li> -->
<!-- <li>Caring</li> -->
<!-- <li>Social</li> -->
<!-- <li>Artistic</li> -->
<!-- <li>Intellectual</li> -->
</workDisables>
<spawnCategories>
<li>ArachnaeQueen_spawnCategoriesB</li>
@@ -59,7 +73,7 @@
<defName>Arachnae_Node_BS_Adult_Myrmecocystus</defName>
<title>阿拉克涅蜜罐种</title>
<titleShort>蜜罐种</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅蜜罐种督虫。基因的选择性表达使其长出了肿胀的囊袋和复杂的口器,这使得她可以吞噬那些未经过处理的尸体和各种杂食或是将其进一步分解,并通过消化器官将其转变为阿拉克涅虫蜜以供其他虫族食用。\n\n[PAWN_nameDef]在战斗中并不是一个值得正视的对手,她没有可以接入武装器官的副肢,脆弱臃肿的特性也决定了她几乎无法躲开任何攻击。</description>
<description>[PAWN_nameDef]是一只阿拉克涅蜜罐种督虫。基因的选择性表达使其长出了肿胀的囊袋和复杂的口器,这使得她可以吞噬那些未经过处理的尸体和各种杂食或是将其进一步分解,并通过消化器官将其转变为阿拉克涅虫蜜以供其他虫族食用。\n\n[PAWN_nameDef]在战斗中并不是一个值得正视的对手,她的战斗技能非常笨拙,脆弱臃肿的特性也决定了她几乎无法躲开任何攻击。</description>
<slot>Adulthood</slot>
<workDisables>
<li>Cleaning</li>
@@ -77,7 +91,9 @@
<li>Intellectual</li>
</workDisables>
<skillGains>
<Cooking>5</Cooking>
<Shooting>-10</Shooting>
<Melee>-10</Melee>
<Plants>5</Plants>
</skillGains>
<spawnCategories>
@@ -106,7 +122,7 @@
<li>Intellectual</li>
</workDisables>
<skillGains>
<Mining>5</Mining>
<Construction>5</Construction>
</skillGains>
<spawnCategories>
@@ -172,7 +188,37 @@
<li>ArachnaeNode_spawnCategories_Fighter</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Adult_Smokepop</defName>
<title>阿拉克涅浓雾种</title>
<titleShort>浓雾种</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅浓雾种督虫,是少见的大型虫族,可以装配大型武装器官。她拥有让其他侵略者望而却步的巨型甲壳,常规的手持武器难以穿透;并且她还拥有一个巨大的浓雾腔,可以通过多条生物喷管将阻碍燃烧的白色黏着物和白色烟雾喷到大范围的广阔区域中,以掩护虫群集群冲击敌方炮塔阵地。</description>
<slot>Adulthood</slot>
<workDisables>
<!-- <li>Cleaning</li> -->
<!-- <li>Hauling</li> -->
<li>Mining</li>
<li>PlantWork</li>
<li>Animals</li>
<li>Hunting</li>
<li>Crafting</li>
<li>Cooking</li>
<li>Constructing</li>
<!-- <li>Caring</li> -->
<li>Social</li>
<li>Artistic</li>
<li>Intellectual</li>
</workDisables>
<skillGains>
<Shooting>3</Shooting>
<Melee>3</Melee>
<Medicine>6</Medicine>
</skillGains>
<spawnCategories>
<li>ArachnaeNode_spawnCategories_Smokepop</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Adult_Skyraider</defName>
<title>阿拉克涅空天种</title>
@@ -184,8 +230,8 @@
<!-- <li>Hauling</li> -->
<li>Mining</li>
<li>PlantWork</li>
<!-- <li>Animals</li> -->
<!-- <li>Hunting</li> -->
<li>Animals</li>
<li>Hunting</li>
<li>Crafting</li>
<li>Cooking</li>
<li>Constructing</li>
@@ -195,7 +241,7 @@
<li>Intellectual</li>
</workDisables>
<skillGains>
<Shooting>5</Shooting>
<Shooting>8</Shooting>
<Melee>5</Melee>
</skillGains>
@@ -203,16 +249,58 @@
<li>ArachnaeNode_spawnCategories_Skyraider</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Adult_Facehugger</defName>
<title>阿拉克涅原虫种</title>
<titleShort>原虫种</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅原虫种督虫。[PAWN_nameDef]通过独特的神经链接管伸入受害者身体来接管受害者的身体。不同于普通阿拉克涅虫族,阿拉克涅原虫种拥有自我意识,不需要女皇种的监管</description>
<description>[PAWN_nameDef]是一只阿拉克涅原虫种督虫。[PAWN_nameDef]通过独特的神经链接管伸入受害者身体来接管受害者的身体。在进行接管时,技能熟练度将采取原虫种和受害者两者间较高的一方,但是所有在寄生期间获得的技能熟练度不会被原虫种离开受害者时继承</description>
<slot>Adulthood</slot>
<workDisables>
<!-- <li>Cleaning</li>
<li>Hauling</li>
<li>Mining</li>
<li>PlantWork</li>
<li>Animals</li>
<li>Hunting</li>
<li>Crafting</li>
<li>Cooking</li>
<li>Constructing</li>
<li>Caring</li>
<li>Social</li>
<li>Artistic</li> -->
<li>Intellectual</li>
</workDisables>
<spawnCategories>
<li>ArachnaeNode_spawnCategories_Facehugger</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Adult_NeuroSwarm</defName>
<title>阿拉克涅织域种</title>
<titleShort>织域种</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅织域种督虫。织域种虽然受到女皇种监管,但仍然具有强大的高级智慧和自我意志,织域种之间能够构建一种高度互联的神经网络从而进行复杂的研究和计算工作,织域种进行计算工作时无法感知外界环境,因此她们是虫群的重要保护对象。</description>
<slot>Adulthood</slot>
<workDisables>
<li>Cleaning</li>
<!-- <li>Hauling</li> -->
<li>Mining</li>
<li>PlantWork</li>
<li>Animals</li>
<li>Hunting</li>
<!-- <li>Crafting</li> -->
<li>Cooking</li>
<li>Constructing</li>
<li>Caring</li>
<!-- <li>Artistic</li> -->
</workDisables>
<skillGains>
<Intellectual>10</Intellectual>
</skillGains>
<spawnCategories>
<li>ArachnaeNode_spawnCategories_NeuroSwarm</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
</Defs>

View File

@@ -44,4 +44,50 @@
</li>
</additionalHediffs>
</DamageDef>
<DamageDef ParentName="Bite">
<defName>ARA_SkyhiveBite</defName>
<label>天巢种撕咬</label>
<additionalHediffsThisPart>
<li>
<hediff>ARA_SkyhiveBite</hediff>
</li>
</additionalHediffsThisPart>
</DamageDef>
<DamageDef ParentName="Bite">
<defName>ARA_MimicNematodeBite</defName>
<additionalHediffs>
<li>
<hediff>ARA_MimicNematode</hediff>
<severityPerDamageDealt>0.001</severityPerDamageDealt>
</li>
</additionalHediffs>
</DamageDef>
<DamageDef>
<defName>ARA_ReinforceGas</defName>
<label>信息素烟雾</label>
<workerClass>DamageWorker_AddInjury</workerClass>
<hasForcefulImpact>false</hasForcefulImpact>
<makesBlood>false</makesBlood>
<canInterruptJobs>false</canInterruptJobs>
<externalViolence>false</externalViolence>
<deathMessage>{0} 被烟呛死了。</deathMessage>
<hediff>Burn</hediff>
<minDamageToFragment>1</minDamageToFragment>
<defaultDamage>2</defaultDamage>
<defaultArmorPenetration>0</defaultArmorPenetration>
<explosionHeatEnergyPerCell>0</explosionHeatEnergyPerCell>
<armorCategory>Heat</armorCategory>
<soundExplosion>Explosion_Smoke</soundExplosion>
<combatLogRules>Damage_Smoke</combatLogRules>
<canUseDeflectMetalEffect>false</canUseDeflectMetalEffect>
<scaleDamageToBuildingsBasedOnFlammability>true</scaleDamageToBuildingsBasedOnFlammability>
<additionalHediffs>
<li>
<hediff>ARA_ReinforceGasCoverd</hediff>
</li>
</additionalHediffs>
</DamageDef>
</Defs>

View File

@@ -249,5 +249,79 @@
<FacialAnimation.SkinTypeDef ParentName="ArachnaeNode_Skin" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Fighter_SkinNormal</defName>
<raceName>ArachnaeNode_Race_Fighter</raceName>
</FacialAnimation.SkinTypeDef>
<FacialAnimation.BrowTypeDef ParentName="ArachnaeNode_Brow" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_BrowNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.BrowTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeA" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_EyeNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeB" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_EyeNormal2</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeC" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_EyeNormal3</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeD" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_EyeNormal4</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.HeadTypeDef ParentName="ArachnaeNode_Head" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_HeadNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.HeadTypeDef>
<FacialAnimation.LidTypeDef ParentName="ArachnaeNode_Lid" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_LidNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.LidTypeDef>
<FacialAnimation.MouthTypeDef ParentName="ArachnaeNode_Mouth" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_MouthNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.MouthTypeDef>
<FacialAnimation.SkinTypeDef ParentName="ArachnaeNode_Skin" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Smokepop_SkinNormal</defName>
<raceName>ArachnaeNode_Race_Smokepop</raceName>
</FacialAnimation.SkinTypeDef>
<FacialAnimation.BrowTypeDef ParentName="ArachnaeNode_Brow" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_BrowNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.BrowTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeA" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_EyeNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeB" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_EyeNormal2</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeC" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_EyeNormal3</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.EyeballTypeDef ParentName="ArachnaeNode_EyeD" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_EyeNormal4</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.EyeballTypeDef>
<FacialAnimation.HeadTypeDef ParentName="ArachnaeNode_Head" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_HeadNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.HeadTypeDef>
<FacialAnimation.LidTypeDef ParentName="ArachnaeNode_Lid" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_LidNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.LidTypeDef>
<FacialAnimation.MouthTypeDef ParentName="ArachnaeNode_Mouth" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_MouthNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.MouthTypeDef>
<FacialAnimation.SkinTypeDef ParentName="ArachnaeNode_Skin" MayRequire="Nals.FacialAnimation">
<defName>ArachnaeNode_Race_Skyraider_SkinNormal</defName>
<raceName>ArachnaeNode_Race_Skyraider</raceName>
</FacialAnimation.SkinTypeDef>
</Defs>

View File

@@ -2,33 +2,33 @@
<Defs>
<!-- North Frames -->
<GraphicStateDef><defName>ARA_FlyNorth_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_1_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_2_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_3_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_4_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_5_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_1_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_2_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_3_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_4_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_5_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<!-- <GraphicStateDef><defName>ARA_FlyNorth_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_6</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_7_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyNorth_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_north</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef> -->
<!-- East Frames -->
<GraphicStateDef><defName>ARA_FlyEast_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_1_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_2_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_3_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_4_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_5_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_1_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_2_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_3_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_4_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_5_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<!-- <GraphicStateDef><defName>ARA_FlyEast_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_6</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_7_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlyEast_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_east</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef> -->
<!-- South Frames -->
<GraphicStateDef><defName>ARA_FlySouth_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_1_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_2_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_3_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_4_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_5_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_0</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_1_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_1</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_2_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_2</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_3_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_3</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_4_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_4</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_5_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<!-- <GraphicStateDef><defName>ARA_FlySouth_5</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_6_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_6</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_7_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef>
<GraphicStateDef><defName>ARA_FlySouth_7</defName><defaultGraphicData><graphicClass>Graphic_Single</graphicClass><texPath>Things/Pawn/Animal/Goose/Goose_Flying_8_south</texPath><drawSize>1.35</drawSize></defaultGraphicData></GraphicStateDef> -->
</Defs>

View File

@@ -84,4 +84,118 @@
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_SkyhiveBite</defName>
<label>天巢种虫族附着</label>
<description>一只可爱的天巢种阿拉克涅虫族咬到了你的身上,虫虫会不停的咬你直到从你身上脱离。这不会有太大问题...对吧?</description>
<!--<tendable>false</tendable> Must be removed via surgery -->
<!--<displayWound>true</displayWound>-->
<hediffClass>ArachnaeSwarm.HediffCurseFlame</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>600</disappearsAfterTicks>
<showRemainingTime>True</showRemainingTime>
</li>
<li Class="HediffCompProperties_DisappearsOnDeath"/>
<li Class="ArachnaeSwarm.HediffCompProperties_SpawnPawnOnRemoved">
<pawnKindDefs>
<li>ArachnaeBase_Race_Skyhive</li>
</pawnKindDefs>
<spawnCount>1</spawnCount>
<fixedBiologicalAge>0</fixedBiologicalAge>
</li>
</comps>
<modExtensions>
<li Class="ArachnaeSwarm.CurseFlameModExt">
<damageDefName>Bite</damageDefName>
<damageRange>3~5</damageRange>
<damageIntervalTicks>150</damageIntervalTicks>
</li>
</modExtensions>
<stages>
<li>
<painOffset>0.05</painOffset>
</li>
</stages>
<renderNodeProperties>
<li>
<debugLabel>Arachnae Skyhive</debugLabel>
<workerClass>PawnRenderNodeWorker_AttachmentBody</workerClass>
<texPaths>
<li>Things/Pawn/Insect/Locust/Locust_north</li>
<li>Things/Pawn/Insect/Locust/Locust_east</li>
</texPaths>
<color>(145,140,109)</color>
<baseLayer>65</baseLayer>
<texSeed>1</texSeed>
<drawData>
<dataNorth>
<rotationOffset>263</rotationOffset>
<offset>(-0.04, 0, 0.04)</offset>
</dataNorth>
<dataEast>
<rotationOffset>245</rotationOffset>
<offset>(0.05, 0, 0.02)</offset>
</dataEast>
<dataSouth>
<rotationOffset>2</rotationOffset>
<offset>(0.05, 0, 0.02)</offset>
</dataSouth>
<dataWest>
<rotationOffset>-245</rotationOffset>
<offset>(-0.04, 0, 0.04)</offset>
<flip>true</flip>
</dataWest>
</drawData>
</li>
</renderNodeProperties>
</HediffDef>
<HediffDef>
<defName>ARA_ReinforceGasCoverd</defName>
<label>阿拉克涅信息素沾染</label>
<description>你身上沾染了阿拉克涅信息素,有什么正在从在地下袭来。</description>
<!--<tendable>false</tendable> Must be removed via surgery -->
<!--<displayWound>true</displayWound>-->
<hediffClass>HediffWithComps</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>600</disappearsAfterTicks>
<showRemainingTime>True</showRemainingTime>
</li>
<li Class="HediffCompProperties_DisappearsOnDeath"/>
<li Class="ArachnaeSwarm.HediffCompProperties_SpawnPawnOnRemoved">
<pawnKindDefs>
<li>ArachnaeBase_Race_Acid</li>
</pawnKindDefs>
<spawnCount>1</spawnCount>
<fixedBiologicalAge>0</fixedBiologicalAge>
</li>
</comps>
</HediffDef>
<HediffDef>
<defName>ARA_Unburnable</defName>
<label>阻燃烟雾</label>
<description>一种特殊的烟雾覆盖了这片地区,使得置身其中的殖民者难以被点着.</description>
<hediffClass>HediffWithComps</hediffClass>
<stages>
<li>
<statFactors>
<Flammability>0</Flammability>
</statFactors>
</li>
</stages>
<comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>1200</disappearsAfterTicks>
<showRemainingTime>True</showRemainingTime>
</li>
<li Class="HediffCompProperties_DisappearsOnDeath"/>
</comps>
</HediffDef>
</Defs>

View File

@@ -83,6 +83,13 @@
<comps>
</comps>
<stages>
<li>
<minSeverity>0</minSeverity>
<disablesNeeds>
<li>Food</li>
<li>Rest</li>
</disablesNeeds>
</li>
</stages>
</HediffDef>
</Defs>

View File

@@ -0,0 +1,305 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>ARA_MimicNematode</defName>
<label>拟线种虫族寄生</label>
<description>被阿拉克涅拟线种虫族寄生了,如果不加以干预,拟线虫最终会杀死宿主并将其转化为没有意识的寄生体。拟线虫会通过寄生体的攻击行为感染其他躯体。</description>
<!-- 1. 指向我们创建的包含Comp的Hediff类 -->
<hediffClass>ArachnaeSwarm.Hediff_NecroticVirus</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<isBad>true</isBad>
<maxSeverity>1.0</maxSeverity>
<lethalSeverity>1.0</lethalSeverity>
<minSeverity>0.001</minSeverity>
<initialSeverity>0.001</initialSeverity>
<everCurableByItem>false</everCurableByItem>
<stages>
<li>
<label>休眠期</label>
<becomeVisible>false</becomeVisible>
<vomitMtbDays>5</vomitMtbDays>
</li>
<li>
<label>活跃期</label>
<minSeverity>0.5</minSeverity>
<vomitMtbDays>1</vomitMtbDays>
<painFactor>0.5</painFactor>
<totalBleedFactor>0.9</totalBleedFactor>
<becomeVisible>false</becomeVisible>
<capMods>
<li>
<capacity>Talking</capacity>
<postFactor>0</postFactor>
</li>
</capMods>
</li>
<li>
<label>终末期</label>
<minSeverity>0.7</minSeverity>
<painFactor>0</painFactor>
<totalBleedFactor>0.3</totalBleedFactor>
<becomeVisible>true</becomeVisible>
<capMods>
<li>
<capacity>Talking</capacity>
<postFactor>0</postFactor>
</li>
<li>
<capacity>BloodFiltration</capacity>
<offset>0.45</offset>
</li>
<li>
<capacity>BloodPumping</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Metabolism</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Breathing</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Consciousness</capacity>
<offset>-0.1</offset>
</li>
</capMods>
<regeneration>50</regeneration>
</li>
<li>
<label>即将转化</label>
<minSeverity>0.9</minSeverity>
<painFactor>0</painFactor>
<totalBleedFactor>0.3</totalBleedFactor>
<lifeThreatening>true</lifeThreatening>
<becomeVisible>true</becomeVisible>
<capMods>
<li>
<capacity>Talking</capacity>
<postFactor>0</postFactor>
</li>
<li>
<capacity>BloodFiltration</capacity>
<offset>0.45</offset>
</li>
<li>
<capacity>BloodPumping</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Metabolism</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Breathing</capacity>
<offset>0.1</offset>
</li>
<li>
<capacity>Consciousness</capacity>
<setMax>0.1</setMax>
</li>
</capMods>
<regeneration>50</regeneration>
</li>
</stages>
<tendable>true</tendable>
<!-- 2. 这是最关键的配置部分 -->
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>0.3</severityPerDay>
</li>
<li Class="HediffCompProperties_TendDuration">
<severityPerDayTended>-1</severityPerDayTended>
<baseTendDurationHours>24</baseTendDurationHours>
</li>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>1800000~2400000</disappearsAfterTicks> <!-- 30 ! 45 days -->
<showRemainingTime>true</showRemainingTime>
</li>
<li Class="ArachnaeSwarm.HediffCompProperties_NecroticTransformation">
<mutantDef>ARA_MimicNematodeShambler</mutantDef>
<triggerSeverity>0.7</triggerSeverity>
</li>
<!-- ==================== 新增的共生组件 ==================== -->
<li Class="ArachnaeSwarm.HediffCompProperties_Symbiosis">
<!-- "钥匙": 只有当Pawn拥有这个Hediff时共生效果才会激活 -->
<requiredHediff>ARA_SymbioticStabilizer</requiredHediff>
<!-- "新的上限": 在共生状态下此Hediff的严重性最高只能达到0.8 -->
<newMaxSeverity>0.8</newMaxSeverity>
</li>
<li Class="HediffCompProperties_DisappearsOnDeath" />
</comps>
<modExtensions>
<li Class="ArachnaeSwarm.ProphecyGearEffect">
<!-- 只有当攻击者同时拥有'ARA_MimicNematode'这个仿生体时,以下效果才会触发 -->
<requiredBionicHediff>ARA_MimicNematode</requiredBionicHediff>
<!-- 额外造成5%的'ARA_MimicNematodeBite'伤害 -->
<enableExtraDamage>true</enableExtraDamage>
<extraDamageFactor>0.05</extraDamageFactor>
<extraDamageType>ARA_MimicNematodeBite</extraDamageType>
</li>
</modExtensions>
</HediffDef>
<RecipeDef ParentName="SurgeryFlesh">
<defName>ARA_CureBloodRot</defName>
<label>清除拟线虫感染</label>
<description>通过多种药物联合靶向治疗清除患者体内的阿拉克涅拟线种虫族感染。</description>
<workerClass>Recipe_RemoveHediff</workerClass>
<jobString>清除拟线虫感染.</jobString>
<workAmount>2000</workAmount>
<hideBodyPartNames>true</hideBodyPartNames>
<isViolation>false</isViolation>
<targetsBodyPart>false</targetsBodyPart>
<removesHediff>ARA_MimicNematode</removesHediff>
<successfullyRemovedHediffMessage>{0} 成功清除了 {1} 体内的拟线虫感染.</successfullyRemovedHediffMessage>
<skillRequirements>
<Medicine>5</Medicine>
</skillRequirements>
<ingredients>
<li>
<filter>
<thingDefs>
<li>MedicineUltratech</li>
</thingDefs>
</filter>
<count>10</count>
</li>
</ingredients>
<fixedIngredientFilter>
<categories>
<li>Medicine</li>
</categories>
</fixedIngredientFilter>
</RecipeDef>
<!-- 这是我们的主要变异体Hediff现在使用我们自己的可配置类 -->
<HediffDef>
<defName>ARA_MimicNematodeShambler</defName>
<label>阿拉克涅拟线种寄生体</label>
<description>这具尸体被一种阿拉克涅拟线虫所寄生并重新激活。被寄生的生物行动迟缓、没有心智,只会无情地攻击任何活物。在活动几天后,寄生体将因宿主新陈代谢衰竭而死亡。被捕获并固定后,寄生体无法移动,因此其生命活动会暂停。</description>
<hediffClass>ArachnaeSwarm.Hediff_ConfigurableMutant</hediffClass> <!-- 指向我们自己的类 -->
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<everCurableByItem>false</everCurableByItem>
<duplicationAllowed>false</duplicationAllowed>
<keepOnBodyPartRestoration>True</keepOnBodyPartRestoration>
<stages>
<li>
<naturalHealingFactor>0</naturalHealingFactor>
<painFactor>0</painFactor>
<statFactors>
<MeleeCooldownFactor>1.5</MeleeCooldownFactor>
<PsychicSensitivity>0</PsychicSensitivity>
</statFactors>
<statOffsets>
<ComfyTemperatureMin>-60</ComfyTemperatureMin>
<ComfyTemperatureMax>30</ComfyTemperatureMax>
<MinimumContainmentStrength>25</MinimumContainmentStrength>
<ToxicResistance>1</ToxicResistance>
</statOffsets>
<capMods>
<li><capacity>Talking</capacity><postFactor>0</postFactor></li>
<li><capacity>Consciousness</capacity><postFactor>0.7</postFactor></li>
</capMods>
<regeneration>200</regeneration>
</li>
</stages>
<comps>
<!-- 原版的消失组件保持不变-->
<li Class="HediffCompProperties_DisappearsAndKills">
<compClass>HediffComp_DisappearsAndKills_Shambler</compClass>
<disappearsAfterTicks>1800000~2400000</disappearsAfterTicks> <!-- 30 ! 45 days -->
<showRemainingTime>true</showRemainingTime>
</li>
<li Class="HediffCompProperties_DisappearsOnDeath" />
<li Class="HediffCompProperties_AttachPoints" />
<!-- 添加我们的新配置组件 -->
<li Class="ArachnaeSwarm.HediffCompProperties_ConfigurableMutant">
<!-- 1. 定义起身和尸体状态 -->
<risingHediff>ARA_Rising</risingHediff>
<corpseHediff>ARA_MimicNematodeShamblerShamblerCorpse</corpseHediff>
<!-- 2. (可选) 覆盖其他默认值 -->
<bioferriteOnDeathChance>0</bioferriteOnDeathChance>
<bioferriteAmountOnDeath>0</bioferriteAmountOnDeath>
</li>
</comps>
<renderNodeProperties>
<li>
<debugLabel>ARA_Swarm_claws</debugLabel>
<workerClass>PawnRenderNodeWorker_AttachmentBody</workerClass>
<texPaths>
<li>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Claw</li>
</texPaths>
<baseLayer>60</baseLayer>
<texSeed>1</texSeed>
<drawData>
<dataNorth>
<flip>true</flip>
</dataNorth>
</drawData>
</li>
</renderNodeProperties>
</HediffDef>
<!-- ====================================================================== -->
<!-- 以下是上面引用的两个Hediff的定义保持不变 -->
<HediffDef>
<defName>ARA_Rising</defName>
<label>起身中</label>
<description>阿拉克涅拟线虫寄生赋予的强大再生能力正在复苏这具身体。</description>
<everCurableByItem>false</everCurableByItem>
<recordDownedTale>false</recordDownedTale>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<stages>
<li>
<painFactor>0</painFactor>
<capMods>
<li><capacity>Moving</capacity><postFactor>0</postFactor></li>
<li><capacity>Manipulation</capacity><postFactor>0</postFactor></li>
<li><capacity>Talking</capacity><postFactor>0</postFactor></li>
<li><capacity>Consciousness</capacity><setMax>0.1</setMax></li>
</capMods>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_MimicNematodeShamblerShamblerCorpse</defName>
<label>拟线种寄生体尸体</label>
<description>这具身体刚刚被阿拉克涅拟线种寄生"复活"过。</description>
<forceRemoveOnResurrection>true</forceRemoveOnResurrection>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<renderNodeProperties>
<li Class="PawnRenderNodeProperties_Overlay">
<debugLabel>Shambler wounds</debugLabel>
<workerClass>PawnRenderNodeWorker_OverlayShambler</workerClass>
<overlayLayer>Body</overlayLayer>
<baseLayer>20</baseLayer>
<pawnType>HumanlikeOnly</pawnType>
</li>
<li>
<debugLabel>Shambler wounds</debugLabel>
<nodeClass>PawnRenderNode_AnimalPart</nodeClass>
<workerClass>PawnRenderNodeWorker_OverlayShambler</workerClass>
<overlayLayer>Body</overlayLayer>
<baseLayer>20</baseLayer>
<pawnType>NonHumanlikeOnly</pawnType>
</li>
</renderNodeProperties>
</HediffDef>
</Defs>

View File

@@ -38,7 +38,7 @@
<moveSpeedFactorByTerrainTag>
<li>
<key>ARA_Creep</key>
<value>2.0</value>
<value>3.0</value>
</li>
</moveSpeedFactorByTerrainTag>
</PawnKindDef>
@@ -70,8 +70,8 @@
<forceNormalGearQuality>true</forceNormalGearQuality>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<maxGenerationAge>30</maxGenerationAge>
<minGenerationAge>10</minGenerationAge>
<maxGenerationAge>0</maxGenerationAge>
<minGenerationAge>0</minGenerationAge>
<canBeScattered>false</canBeScattered>
<xenotypeSet>
<xenotypeChances>
@@ -99,7 +99,7 @@
<moveSpeedFactorByTerrainTag>
<li>
<key>ARA_Creep</key>
<value>2.0</value>
<value>3.0</value>
</li>
</moveSpeedFactorByTerrainTag>
</PawnKindDef>
@@ -159,12 +159,6 @@
</categories>
</li>
</backstoryFiltersOverride>
<abilities>
<li>ARA_BioforgeIncubator_ClothBase</li>
<li>ARA_BioforgeIncubator_AcidBase</li>
<li>ARA_BioforgeIncubator_ToxicNeedleBase</li>
<li>ARA_BioforgeIncubator_BoneBase</li>
</abilities>
<apparelTags>
</apparelTags>
<apparelMoney>0</apparelMoney>
@@ -213,13 +207,34 @@
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
<PawnKindDef ParentName="ArachnaeNodeABasePawnKind">
<defName>ArachnaeNode_Race_Smokepop</defName>
<label>阿拉克涅浓雾种</label>
<race>ArachnaeNode_Race_Smokepop</race>
<defaultFactionType>PlayerColony</defaultFactionType>
<invNutrition>0</invNutrition>
<backstoryFiltersOverride>
<li>
<categories>
<li>ArachnaeNode_spawnCategoriesA</li>
<li>ArachnaeNode_spawnCategories_Smokepop</li>
</categories>
</li>
</backstoryFiltersOverride>
<abilities>
<li>ARA_Ability_Smokepop</li>
</abilities>
<apparelTags>
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
<PawnKindDef ParentName="ArachnaeNodeABasePawnKind">
<defName>ArachnaeNode_Race_Skyraider</defName>
<label>阿拉克涅空天种</label>
<race>ArachnaeNode_Race_Skyraider</race>
<defaultFactionType>PlayerColony</defaultFactionType>
<invNutrition>0</invNutrition>
<flyingAnimationFramePathPrefix>Things/Pawn/Animal/Goose/Goose_Flying_</flyingAnimationFramePathPrefix>
<flyingAnimationFramePathPrefix>ArachnaeSwarm/Things/ARA_HiveNode/Addons/Flying/ArachnaeNode_Race_Addons_Skyraider_Wing_</flyingAnimationFramePathPrefix>
<flyingAnimationDrawSize>1.35</flyingAnimationDrawSize>
<flyingAnimationFrameCount>2</flyingAnimationFrameCount>
<flyingAnimationTicksPerFrame>2</flyingAnimationTicksPerFrame>
@@ -228,19 +243,40 @@
<li>
<categories>
<li>ArachnaeNode_spawnCategoriesA</li>
<li>ArachnaeNode_spawnCategories_Fighter</li>
<li>ArachnaeNode_spawnCategories_Skyraider</li>
</categories>
</li>
</backstoryFiltersOverride>
<abilities>
<li>ARA_BaseRace_Acid_Launcher</li>
<li>ARA_AcidSprayBurst</li>
<li>ARA_Toxic_Needle_Fire</li>
<li>ARA_BaseRace_Skyhive_Launcher</li>
<li>ARA_Skyraider_jump</li>
</abilities>
<apparelTags>
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
<PawnKindDef ParentName="ArachnaeNodeABasePawnKind">
<defName>ArachnaeNode_Race_NeuroSwarm</defName>
<label>阿拉克涅织域种</label>
<race>ArachnaeNode_Race_NeuroSwarm</race>
<defaultFactionType>PlayerColony</defaultFactionType>
<invNutrition>0</invNutrition>
<backstoryFiltersOverride>
<li>
<categories>
<li>ArachnaeNode_spawnCategoriesA</li>
<li>ArachnaeNode_spawnCategories_NeuroSwarm</li>
</categories>
</li>
</backstoryFiltersOverride>
<abilities>
<li>ARA_Ability_Morph</li>
</abilities>
<apparelTags>
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
<PawnKindDef Name="ARA_InsectKindBase" ParentName="AnimalKindBase" Abstract="True">
<defaultFactionType>PlayerColony</defaultFactionType>
@@ -249,35 +285,15 @@
<forceNoDeathNotification>true</forceNoDeathNotification>
<combatPower>75</combatPower>
<ecoSystemWeight>0</ecoSystemWeight>
<maxGenerationAge>0</maxGenerationAge>
<minGenerationAge>0</minGenerationAge>
<moveSpeedFactorByTerrainTag>
<li>
<key>ARA_Creep</key>
<value>2.0</value>
<value>3.0</value>
</li>
</moveSpeedFactorByTerrainTag>
</PawnKindDef>
<!--<PawnKindDef ParentName="ARA_InsectKindBase">
<defName>ArachnaeBase_Race_Slavey</defName>
<label>阿拉克涅苦役种</label>
<race>ArachnaeBase_Race_Slavey</race>
<lifeStages>
<li>
<bodyGraphicData>
<texPath>Things/Pawn/Animal/Spelopede/Spelopede</texPath>
<drawSize>1</drawSize>
<color>(156,148,125)</color>
<shadowData>
<volume>(0.4, 0.5, 0.37)</volume>
<offset>(0,0,-0.15)</offset>
</shadowData>
</bodyGraphicData>
<dessicatedBodyGraphicData>
<texPath>Things/Pawn/Animal/Spelopede/Dessicated_Spelopede</texPath>
<drawSize>1</drawSize>
</dessicatedBodyGraphicData>
</li>
</lifeStages>
</PawnKindDef>-->
<PawnKindDef ParentName="ARA_InsectKindBase">
<defName>ArachnaeBase_Race_Scavenger</defName>
<label>阿拉克涅食腐种</label>
@@ -366,4 +382,32 @@
</li>
</lifeStages>
</PawnKindDef>
<PawnKindDef ParentName="ARA_InsectKindBase">
<defName>ArachnaeBase_Race_Skyhive</defName>
<label>阿拉克涅天巢种</label>
<race>ArachnaeBase_Race_Skyhive</race>
<flyingAnimationFramePathPrefix>Things/Pawn/Insect/Locust/LocustFlying/Locust_Flying_</flyingAnimationFramePathPrefix>
<flyingAnimationFrameCount>5</flyingAnimationFrameCount>
<flyingAnimationTicksPerFrame>2</flyingAnimationTicksPerFrame>
<flyingAnimationDrawSize>1</flyingAnimationDrawSize>
<flyingAnimationDrawSizeIsMultiplier>false</flyingAnimationDrawSizeIsMultiplier>
<flyingAnimationInheritColors>true</flyingAnimationInheritColors>
<lifeStages>
<li>
<bodyGraphicData>
<texPath>Things/Pawn/Insect/Locust/Locust</texPath>
<drawSize>1</drawSize>
<color>(145,140,109)</color>
<shadowData>
<volume>(0.2, 0.3, 0.2)</volume>
<offset>(0,0,0)</offset>
</shadowData>
</bodyGraphicData>
<dessicatedBodyGraphicData>
<texPath>Things/Pawn/Insect/Locust/Dessicated_Locust</texPath>
<drawSize>1</drawSize>
</dessicatedBodyGraphicData>
</li>
</lifeStages>
</PawnKindDef>
</Defs>

View File

@@ -42,7 +42,6 @@
</li>
<!-- ===== OUR CUSTOM NODE INSERTION START ===== -->
<!-- Using Milira's exact structure for testing -->
<li>
<debugLabel>Arachnae Flight Attachment</debugLabel>
<tagDef>ARA_Flight_Attachment</tagDef>
@@ -54,6 +53,17 @@
</dataSouth>
</drawData>
</li>
<li> <!-- 使用默认的 PawnRenderNodeProperties -->
<debugLabel>Wings (Hides when flying)</debugLabel>
<workerClass>ArachnaeSwarm.PawnRenderNodeWorker_AttachmentBody_NoFlight</workerClass>
<texPath>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Skyraider_Wing</texPath>
<baseLayer>60</baseLayer>
<drawData>
<dataSouth>
<layer>-10</layer>
</dataSouth>
</drawData>
</li>
<!-- ===== OUR CUSTOM NODE INSERTION END ===== -->
<li Class="PawnRenderNodeProperties_Parent">

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- T0 -->
<HediffDef>
<defName>ARA_Queen_0_Stage</defName>
<label>进化等级——无</label>
@@ -22,9 +23,10 @@
<li Class="HediffCompProperties_GiveAbility">
<abilityDefs>
<li>ARA_EggSpew</li>
<li>ARA_EggSpew_Huge</li>
<li>ARA_BindDrone</li>
<li>ARA_Queen_Upgrade_1_Stage</li>
<li>ARA_AcidSprayBurst_Queen</li>
<li>ARA_Queen_Upgrade_1_Stage</li>
</abilityDefs>
</li>
<li Class="HediffCompProperties_RemoveIfOtherHediff">
@@ -43,7 +45,7 @@
<hostile>false</hostile>
<groupAbility>true</groupAbility>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>true</disableGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<aiCanUse>true</aiCanUse>
<ai_IsOffensive>true</ai_IsOffensive>
<targetRequired>false</targetRequired>
@@ -68,8 +70,8 @@
<severity>1</severity>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_2WMT</requiredResearch>
<failMessage>需要科技 基因节点WMT-2"内在突破" 以解锁进化</failMessage>
<requiredResearch>ARA_Technology_1WMT</requiredResearch>
<failMessage>需要科技 基因节点WMT-1"内在突破" 以解锁进化</failMessage>
</li>
</comps>
</AbilityDef>
@@ -97,6 +99,7 @@
</li>
</comps>
</HediffDef>
<!-- T1 -->
<HediffDef>
<defName>ARA_Queen_1_Stage</defName>
<label>进化等级——等级1</label>
@@ -109,12 +112,19 @@
<comps>
<li Class="HediffCompProperties_GiveAbility">
<abilityDefs>
<li>ARA_EggSpew</li>
<li>ARA_EggSpew_1Stage</li>
<li>ARA_EggSpew_Huge_1Stage</li>
<li>ARA_BindDrone</li>
<li>ARA_AcidSprayBurst_Queen</li>
<li>ARA_TumorSpew</li>
<li>ARA_Queen_Upgrade_2_Stage</li>
</abilityDefs>
</li>
<li Class="HediffCompProperties_RemoveIfOtherHediff">
<hediffs>
<li>ARA_Queen_2_Stage_Transition_Period</li>
</hediffs>
</li>
</comps>
</HediffDef>
<AbilityDef>
@@ -126,7 +136,7 @@
<hostile>false</hostile>
<groupAbility>true</groupAbility>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>true</disableGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<aiCanUse>true</aiCanUse>
<ai_IsOffensive>true</ai_IsOffensive>
<targetRequired>false</targetRequired>
@@ -152,7 +162,7 @@
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_2WMT</requiredResearch>
<failMessage>需要科技 基因节点WMT-2"内在突破" 以解锁进化</failMessage>
<failMessage>需要科技 基因节点WMT-2"内在突破2" 以解锁进化</failMessage>
</li>
</comps>
</AbilityDef>
@@ -180,6 +190,7 @@
</li>
</comps>
</HediffDef>
<!-- T2 -->
<HediffDef>
<defName>ARA_Queen_2_Stage</defName>
<label>进化等级——等级2</label>
@@ -198,13 +209,51 @@
<!-- <li>ARA_Queen_Upgrade_2_Stage</li> -->
</abilityDefs>
</li>
<!-- <li Class="HediffCompProperties_RemoveIfOtherHediff">
<hediffs>
<li>ARA_Queen_3_Stage_Transition_Period</li>
</hediffs>
</li> -->
</comps>
</HediffDef>
<!-- T0 -->
<HediffDef>
<defName>ARA_WeaponSmith_0_Stage</defName>
<label>进化等级——无</label>
<description>这只阿拉克涅工艺种尚未得到任何强化,只能孵化最普通的茧以生产一些早期装备。</description>
<hediffClass>HediffWithComps</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<isBad>false</isBad>
<scenarioCanAdd>false</scenarioCanAdd>
<maxSeverity>2.0</maxSeverity>
<!-- <stages>
<li>
<becomeVisible>ture</becomeVisible>
</li>
<li>
<minSeverity>1.01</minSeverity>
<becomeVisible>false</becomeVisible>
</li>
</stages> -->
<comps>
<li Class="HediffCompProperties_GiveAbility">
<abilityDefs>
<li>ARA_Cocoon_Cloth</li>
<li>ARA_Cocoon_Weapon</li>
</abilityDefs>
</li>
<li Class="HediffCompProperties_RemoveIfOtherHediff">
<hediffs>
<li>ARA_Queen_1_Stage_Transition_Period</li>
</hediffs>
</li>
</comps>
</HediffDef>
<RecipeDef ParentName="SurgeryInstallBodyPartArtificialBase">
<defName>ARA_Install_</defName>
<label>安装暗物质能源炉</label>
<description>为合成人安装暗物质能源炉</description>
<defName>ARA_WeaponSmith_Upgrade_1_Stage</defName>
<label>工艺种进化——阶段1</label>
<description>由阿拉科涅女皇种为该工艺种进行基因调整,以使其获得进化并得以孵化更多的武装器官和织物</description>
<descriptionHyperlinks>
<ThingDef>WULA_Energy_Furnace_DM_Engine</ThingDef>
<HediffDef>WULA_Energy_Furnace_Hediff_DM_Engine</HediffDef>
@@ -235,4 +284,61 @@
<li>ArachnaeNode_Race_WeaponSmith</li>
</recipeUsers>
</RecipeDef>
<HediffDef>
<defName>ARA_WeaponSmith_1_Stage_Transition_Period</defName>
<label>工艺种进化——阶段1</label>
<description>由阿拉科涅女皇种为该工艺种进行基因调整,以使其获得进化并得以孵化更多的武装器官和织物。</description>
<!-- <hediffClass>HediffWithComps</hediffClass> -->
<hediffClass>Hediff_High</hediffClass>
<initialSeverity>1</initialSeverity>
<maxSeverity>1.01</maxSeverity>
<alwaysShowSeverity>true</alwaysShowSeverity>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<isBad>false</isBad>
<scenarioCanAdd>false</scenarioCanAdd>
<comps>
<li Class="HediffCompProperties_ReplaceHediff">
<hediffs>
<li>
<hediff>ARA_WeaponSmith_1_Stage</hediff>
<severityRange>0.02~0.15</severityRange>
</li>
</hediffs>
<message>{PAWN_nameDef} 通过女皇种的拔耀获得了更强大的孵化能力,现在她可以孕育更复杂的茧以获取强大的装备。</message>
</li>
</comps>
</HediffDef>
<!-- T1 -->
<HediffDef>
<defName>ARA_WeaponSmith_1_Stage</defName>
<label>进化等级——等级1</label>
<description>这只阿拉科涅工艺种通过女皇种的拔耀获得了更强大的孵化能力,现在她可以孕育更复杂的茧以获取强大的装备。</description>
<hediffClass>HediffWithComps</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<isBad>false</isBad>
<scenarioCanAdd>false</scenarioCanAdd>
<maxSeverity>2.0</maxSeverity>
<!-- <stages>
<li>
<becomeVisible>ture</becomeVisible>
</li>
<li>
<minSeverity>1.01</minSeverity>
<becomeVisible>false</becomeVisible>
</li>
</stages> -->
<comps>
<li Class="HediffCompProperties_GiveAbility">
<abilityDefs>
<li>ARA_Cocoon_Cloth_1Stage</li>
<li>ARA_Cocoon_Weapon_1Stage</li>
</abilityDefs>
</li>
<li Class="HediffCompProperties_RemoveIfOtherHediff">
<hediffs>
<li>ARA_Queen_1_Stage_Transition_Period</li>
</hediffs>
</li>
</comps>
</HediffDef>
</Defs>

View File

@@ -16,8 +16,8 @@
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_2WMT</defName>
<label>基因节点WMT-2"内在突破"</label>
<defName>ARA_Technology_1WMT</defName>
<label>基因节点WMT-1"内在突破"</label>
<description>允许女皇种进化到下一个阶段。</description>
<baseCost>150</baseCost>
<researchViewX>4.50</researchViewX>
@@ -27,6 +27,18 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_2WMT</defName>
<label>基因节点WMT-2"内在突破2"</label>
<description>允许女皇种进化到下一个阶段。</description>
<baseCost>150</baseCost>
<researchViewX>8.50</researchViewX>
<researchViewY>3.10</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<!-- 酸类发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_6VXI</defName>
@@ -43,7 +55,7 @@
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_7VXI</defName>
<label>基因节点VXI-7"外置酸袋"</label>
<description>允许工艺种孵化新的酸类武器</description>
<description>允许工艺种孵化新的武器</description>
<baseCost>150</baseCost>
<researchViewX>2.00</researchViewX>
<researchViewY>0.20</researchViewY>
@@ -65,28 +77,16 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_3KYC</defName>
<label>基因节点KYC-3"冰壳虫"</label>
<description>允许女皇种孵化新的虫族——冰壳种,拥有使得附近温度极急剧下降的特殊能力,此类虫族的卵需要在较低的温度下才能正常孵化。</description>
<baseCost>150</baseCost>
<researchViewX>2.00</researchViewX>
<researchViewY>2.20</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_2KYC</defName>
<label>基因节点KYC-2"熔火虫"</label>
<description>允许女皇种孵化新的虫族——熔火种,拥有喷射高温射流和在近距离灼烧敌人的能力,此类虫族的卵需要在较高的温度下才能正常孵化</description>
<label>基因节点KYC-2"飞行翼膜"</label>
<description>允许女皇种孵化新的虫族——空天种,敏捷而致命的精锐虫族,拥有以飞行姿态穿梭于战场的能力</description>
<baseCost>150</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>2.20</researchViewY>
<researchViewY>2.60</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_2WMT</li>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
@@ -95,13 +95,25 @@
<description>允许女皇种孵化新的虫族——原虫种,一种可以寄生在别的种族身上以控制它们的特殊督虫。</description>
<baseCost>150</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>1.50</researchViewY>
<researchViewY>1.30</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_2WMT</li>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<!-- 硬壳发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_5KYC</defName>
<label>基因节点KYC-5"巨甲"</label>
<description>允许女皇种孵化新的虫族——浓雾种,一种拥有厚重甲壳的大型督虫,可以铺设菌毯、释放烟雾和阻燃剂以协助虫群进行集群冲击。</description>
<baseCost>150</baseCost>
<researchViewX>5.50</researchViewX>
<researchViewY>2.00</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
<!-- 织物发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_4DIL</defName>
<label>基因节点DIL-4"编织"</label>
@@ -115,11 +127,11 @@
</prerequisites>
</ResearchProjectDef>
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_5DIL</defName>
<label>基因节点DIL-5"骨刀"</label>
<description>允许工艺种孵化骨刃茧,为虫族提供基础近战武器</description>
<defName>ARA_Technology_1VTE</defName>
<label>基因节点VTE-1"爆发激素"</label>
<description>允许一部分拥有厚重甲壳的阿拉克涅督虫使用追踪冲撞攻击敌军</description>
<baseCost>150</baseCost>
<researchViewX>2.00</researchViewX>
<researchViewX>1.00</researchViewX>
<researchViewY>5.10</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
@@ -139,7 +151,6 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<!-- 工艺种进化 -->
<!-- 建筑发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_5SHL</defName>
@@ -153,4 +164,17 @@
<li>ARA_Base_Technology</li>
</prerequisites>
</ResearchProjectDef>
<!-- 子巢发展 -->
<ResearchProjectDef ParentName="ARA_techBase">
<defName>ARA_Technology_6SPV</defName>
<label>基因节点SPV-6"天巢种之巢"</label>
<description>允许工艺种孵化新的武器。</description>
<baseCost>150</baseCost>
<researchViewX>1.00</researchViewX>
<researchViewY>2.20</researchViewY>
<requiredResearchBuilding>ARA_ResearchBench</requiredResearchBuilding>
<prerequisites>
<li>ARA_Technology_1WMT</li>
</prerequisites>
</ResearchProjectDef>
</Defs>

View File

@@ -67,6 +67,12 @@
</deathAction>
</race>
<comps>
<li Class="CompProperties_MechPowerCell">
<totalPowerTicks>72000</totalPowerTicks> <!-- 2 hours -->
<labelOverride>寿命</labelOverride>
<tooltipOverride>这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。</tooltipOverride>
<showGizmoOnNonPlayerControlled>true</showGizmoOnNonPlayerControlled>
</li>
<li Class="ArachnaeSwarm.CompProperties_HediffGiver">
<hediffs>
<li>ARA_TemperatureRegulation</li>
@@ -160,65 +166,4 @@
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseDrone" MayRequire="Ludeon.RimWorld.Odyssey">
<defName>ArachnaeBase_Race_Acid</defName>
<label>阿拉克涅酸噬种</label>
<description>阿拉克涅辅虫之一,智力低下,一般被作为活体炮弹打出,击中敌人后若是还没散架,就会继续依靠带酸液的颚撕咬敌军。</description>
<race>
<thinkTreeConstant>WarUrchinConstant</thinkTreeConstant>
<baseBodySize>0.5</baseBodySize>
<!-- <hasCorpse>false</hasCorpse> -->
<body>BeetleLikeWithClaw</body>
<lifeStageAges>
<li>
<def>EusocialInsectAdult</def>
<minAge>0</minAge>
<soundWounded>Pawn_Spelopede_Pain</soundWounded>
<soundDeath>Pawn_Spelopede_Death</soundDeath>
<soundCall>Pawn_Spelopede_Call</soundCall>
<soundAngry>Pawn_Spelopede_Angry</soundAngry>
</li>
</lifeStageAges>
</race>
<statBases>
<MoveSpeed>6</MoveSpeed>
</statBases>
<comps>
<li Class="CompProperties_MechPowerCell">
<totalPowerTicks>4400</totalPowerTicks> <!-- 2 hours -->
<labelOverride>寿命</labelOverride>
<tooltipOverride>这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。</tooltipOverride>
<showGizmoOnNonPlayerControlled>true</showGizmoOnNonPlayerControlled>
</li>
</comps>
<tools Inherit="False">
<li>
<label>酸性巨颚</label>
<capacities>
<li>ARA_AcidCut</li>
</capacities>
<power>6</power>
<cooldownTime>2.6</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
</li>
</tools>
</ThingDef>
<ToolCapacityDef>
<defName>ARA_AcidCut</defName>
<label>酸性撕咬</label>
</ToolCapacityDef>
<ManeuverDef>
<defName>ARA_AcidCut</defName>
<requiredCapacity>ARA_AcidCut</requiredCapacity>
<verb>
<verbClass>Verb_MeleeAttackDamage</verbClass>
<meleeDamageDef>ARA_AcidCut_Damage</meleeDamageDef>
</verb>
<logEntryDef>MeleeAttack</logEntryDef>
<combatLogRulesHit>Maneuver_Slash_MeleeHit</combatLogRulesHit>
<combatLogRulesDeflect>Maneuver_Slash_MeleeDeflect</combatLogRulesDeflect>
<combatLogRulesMiss>Maneuver_Slash_MeleeMiss</combatLogRulesMiss>
<combatLogRulesDodge>Maneuver_Slash_MeleeDodge</combatLogRulesDodge>
</ManeuverDef>
</Defs>
</Defs>

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<ThingDef ParentName="AnimalThingBase" Name="ARA_BaseDroneSwarm" Abstract="True">
<statBases>
<MarketValue>1200</MarketValue>
<PsychicSensitivity>0</PsychicSensitivity>
<ToxicResistance>1</ToxicResistance>
<Flammability>0</Flammability>
<ComfyTemperatureMin>-100</ComfyTemperatureMin>
<ComfyTemperatureMax>250</ComfyTemperatureMax>
<MeatAmount>0</MeatAmount>
<ToxicEnvironmentResistance>1</ToxicEnvironmentResistance>
<VacuumResistance>1</VacuumResistance>
</statBases>
<receivesSignals>true</receivesSignals>
<tradeability>None</tradeability>
<race>
<alwaysAwake>true</alwaysAwake>
<fleshType>Insectoid</fleshType>
<needsRest>false</needsRest>
<hasGenders>false</hasGenders>
<hasCorpse>false</hasCorpse>
<foodType>None</foodType>
<lifeExpectancy>2500</lifeExpectancy>
<bloodDef>Filth_BloodInsect</bloodDef>
<disableIgniteVerb>true</disableIgniteVerb>
<trainability>None</trainability>
<soundCallIntervalRange>1000~2000</soundCallIntervalRange>
<soundCallIntervalFriendlyFactor>2</soundCallIntervalFriendlyFactor>
<thinkTreeConstant>SentryDroneConstant</thinkTreeConstant>
<hideTrainingTab>true</hideTrainingTab>
<intelligence>ToolUser</intelligence>
<thinkTreeMain>Drone</thinkTreeMain>
<canFlyInVacuum>true</canFlyInVacuum>
</race>
<tools>
</tools>
<killedLeavings>
</killedLeavings>
</ThingDef>
<ThingDef ParentName="ARA_BaseDroneSwarm">
<defName>ArachnaeBase_Race_Acid</defName>
<label>阿拉克涅酸噬种</label>
<description>阿拉克涅辅虫之一,智力低下,一般被作为活体炮弹打出,击中敌人后若是还没散架,就会继续依靠带酸液的颚撕咬敌军。</description>
<race>
<thinkTreeConstant>WarUrchinConstant</thinkTreeConstant>
<baseBodySize>0.5</baseBodySize>
<!-- <hasCorpse>false</hasCorpse> -->
<body>BeetleLikeWithClaw</body>
<lifeStageAges>
<li>
<def>EusocialInsectAdult</def>
<minAge>0</minAge>
<soundWounded>Pawn_Spelopede_Pain</soundWounded>
<soundDeath>Pawn_Spelopede_Death</soundDeath>
<soundCall>Pawn_Spelopede_Call</soundCall>
<soundAngry>Pawn_Spelopede_Angry</soundAngry>
</li>
</lifeStageAges>
</race>
<statBases>
<MoveSpeed>6</MoveSpeed>
</statBases>
<comps>
<li Class="CompProperties_MechPowerCell">
<totalPowerTicks>4400</totalPowerTicks> <!-- 2 hours -->
<labelOverride>寿命</labelOverride>
<tooltipOverride>这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。</tooltipOverride>
<showGizmoOnNonPlayerControlled>true</showGizmoOnNonPlayerControlled>
</li>
</comps>
<tools Inherit="False">
<li>
<label>酸性巨颚</label>
<capacities>
<li>ARA_AcidCut</li>
</capacities>
<power>6</power>
<cooldownTime>2.6</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
</li>
</tools>
</ThingDef>
<ThingDef ParentName="ARA_BaseDroneSwarm">
<defName>ArachnaeBase_Race_Skyhive</defName>
<label>阿拉克涅天巢种</label>
<description>阿拉克涅辅虫之一,智力低下,通常被督虫们当成导弹打出,拥有在飞行中调整姿态以追踪敌军的能力。命中敌军后,这些虫族会趴在敌军身上进行啃咬,直到鳌刺松动而掉在地上。</description>
<race>
<flightStartChanceOnJobStart>1.0</flightStartChanceOnJobStart>
<thinkTreeConstant>WarUrchinConstant</thinkTreeConstant>
<baseBodySize>0.5</baseBodySize>
<!-- <hasCorpse>false</hasCorpse> -->
<body>BeetleLikeWithClaw</body>
<lifeStageAges>
<li>
<def>EusocialInsectAdult</def>
<minAge>0</minAge>
<soundWounded>Pawn_Spelopede_Pain</soundWounded>
<soundDeath>Pawn_Spelopede_Death</soundDeath>
<soundCall>Pawn_Spelopede_Call</soundCall>
<soundAngry>Pawn_Spelopede_Angry</soundAngry>
</li>
</lifeStageAges>
</race>
<statBases>
<MoveSpeed>6</MoveSpeed>
<MaxFlightTime>9999</MaxFlightTime>
<FlightCooldown>0</FlightCooldown>
</statBases>
<comps>
<li Class="CompProperties_MechPowerCell">
<totalPowerTicks>4400</totalPowerTicks> <!-- 2 hours -->
<labelOverride>寿命</labelOverride>
<tooltipOverride>这种特殊的阿拉克涅辅虫从出生起就走在死亡的道路上了——它们的寿命就是如此短暂。</tooltipOverride>
<showGizmoOnNonPlayerControlled>true</showGizmoOnNonPlayerControlled>
</li>
</comps>
<tools Inherit="False">
<li>
<label>巨颚</label>
<capacities>
<li>ARA_Bite</li>
</capacities>
<power>6</power>
<cooldownTime>2.6</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
</li>
</tools>
</ThingDef>
<ToolCapacityDef>
<defName>ARA_AcidCut</defName>
<label>酸性撕咬</label>
</ToolCapacityDef>
<ManeuverDef>
<defName>ARA_AcidCut</defName>
<requiredCapacity>ARA_AcidCut</requiredCapacity>
<verb>
<verbClass>Verb_MeleeAttackDamage</verbClass>
<meleeDamageDef>ARA_AcidCut_Damage</meleeDamageDef>
</verb>
<logEntryDef>MeleeAttack</logEntryDef>
<combatLogRulesHit>Maneuver_Slash_MeleeHit</combatLogRulesHit>
<combatLogRulesDeflect>Maneuver_Slash_MeleeDeflect</combatLogRulesDeflect>
<combatLogRulesMiss>Maneuver_Slash_MeleeMiss</combatLogRulesMiss>
<combatLogRulesDodge>Maneuver_Slash_MeleeDodge</combatLogRulesDodge>
</ManeuverDef>
<ToolCapacityDef>
<defName>ARA_Bite</defName>
<label>撕咬</label>
</ToolCapacityDef>
<ManeuverDef>
<defName>ARA_Bite</defName>
<requiredCapacity>ARA_Bite</requiredCapacity>
<verb>
<verbClass>Verb_MeleeAttackDamage</verbClass>
<meleeDamageDef>Bite</meleeDamageDef>
</verb>
<logEntryDef>MeleeAttack</logEntryDef>
<combatLogRulesHit>Maneuver_Slash_MeleeHit</combatLogRulesHit>
<combatLogRulesDeflect>Maneuver_Slash_MeleeDeflect</combatLogRulesDeflect>
<combatLogRulesMiss>Maneuver_Slash_MeleeMiss</combatLogRulesMiss>
<combatLogRulesDodge>Maneuver_Slash_MeleeDodge</combatLogRulesDodge>
</ManeuverDef>
</Defs>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<MutantDef ParentName="BaseMutantEntity">
<defName>ARA_MimicNematodeShambler</defName>
<label>阿拉克涅拟线种寄生体</label>
<description>阿拉克涅拟线种是虫群中最神秘的分支之一。它们与原虫种同源,但在进化之路上并未发展出高级智慧,而是走向了一条截然不同的道路:寄生。拟线种是无法脱离宿主独立存活的寄生虫。一旦寄生于生物体内,它们会长期潜伏,最终逐步接管宿主的神经与代谢系统,将其变为受其操控的行尸走肉——“寄生体”。得益于超凡的细胞复制与再生能力,拟线种能够模仿并替代宿主的细胞结构,这使得寄生体拥有了惊人的自我修复能力。然而,这种寄生关系也极具侵略性:拟线种的虫卵遍布寄生体体表,任何被寄生体攻击的生物都有可能被感染,最终沦为新的寄生体。尽管拟线虫将寄生体的新陈代谢维持在极低水平,但寄生体本身并不会主动觅食。因此,当能量耗尽后,它们终将迎来“死亡”。</description>
<hediff>ARA_MimicNematodeShambler</hediff>
<thinkTree>ARA_WorkingShambler</thinkTree>
<thinkTreeConstant>ShamblerConstant</thinkTreeConstant>
<hideLabel>true</hideLabel>
<namePrefix>拟线种寄生体 </namePrefix>
<useCorpseGraphics>false</useCorpseGraphics>
<isConsideredCorpse>true</isConsideredCorpse>
<bloodDef>Filth_DarkBlood</bloodDef>
<bloodSmearDef>Filth_DarkBloodSmear</bloodSmearDef>
<entitledToMedicalCare>false</entitledToMedicalCare>
<removeAllInjuries>true</removeAllInjuries>
<restoreLegs>true</restoreLegs>
<defaultFaction>Entities</defaultFaction>
<standingAnimation>ShamblerSway</standingAnimation>
<canOpenDoors>false</canOpenDoors>
<makesFootprints>false</makesFootprints>
<tameable>false</tameable>
<clearMutantStatusOnDeath>true</clearMutantStatusOnDeath>
<canTravelInCaravan>false</canTravelInCaravan>
<canAttackWhileCrawling>true</canAttackWhileCrawling>
<respectsAllowedArea>true</respectsAllowedArea>
<disableFlying>true</disableFlying>
<canGainXP>false</canGainXP>
<canBeDrafted>true</canBeDrafted>
<disableHostilityResponse>true</disableHostilityResponse>
<deathOnDownedChance>0.25</deathOnDownedChance>
<woundColor>(0.3, 0.3, 0.0, 1.0)</woundColor>
<anomalyKnowledgeOffset>0</anomalyKnowledgeOffset>
<knowledgeCategory>Basic</knowledgeCategory>
<!--<codexEntry>Shambler</codexEntry>-->
<!-- Sounds -->
<soundAttackChance>0.25</soundAttackChance>
<soundCall>Pawn_Shambler_Call</soundCall>
<soundAttack>Pawn_Shambler_Attack</soundAttack>
<soundWounded>Pawn_Shambler_Wounded</soundWounded>
<soundDeath>Pawn_Shambler_Killed</soundDeath>
<removesHediffs>
<li>ARA_MimicNematode</li>
</removesHediffs>
<workDisables Inherit="false">
<li>ManualSkilled</li>
<li>Intellectual</li>
<li>Artistic</li>
<li>Caring</li>
<li>Social</li>
<li>PlantWork</li>
<li>Mining</li>
<li>Hunting</li>
<li>Constructing</li>
<li>Cooking</li>
<li>Shooting</li>
</workDisables>
<!-- Rendering -->
<renderNodeProperties>
<li Class="PawnRenderNodeProperties_Overlay">
<debugLabel>Shambler wounds</debugLabel>
<workerClass>PawnRenderNodeWorker_OverlayShambler</workerClass>
<overlayLayer>Body</overlayLayer>
<baseLayer>20</baseLayer>
<pawnType>HumanlikeOnly</pawnType>
</li>
<li>
<debugLabel>Shambler wounds</debugLabel>
<nodeClass>PawnRenderNode_AnimalPart</nodeClass>
<workerClass>PawnRenderNodeWorker_OverlayShambler</workerClass>
<overlayLayer>Body</overlayLayer>
<baseLayer>20</baseLayer>
<pawnType>NonHumanlikeOnly</pawnType>
</li>
</renderNodeProperties>
<tools>
<li>
<label>撕咬</label>
<capacities>
<li>ARA_MimicNematodeShamblerBite</li>
</capacities>
<power>8.2</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>Teeth</linkedBodyPartsGroup>
<chanceFactor>1</chanceFactor>
<soundMeleeHit>Pawn_Melee_HumanBite_Hit</soundMeleeHit>
<soundMeleeMiss>Pawn_Melee_HumanBite_Miss</soundMeleeMiss>
</li>
<li>
<label>巨镰</label>
<capacities>
<li>Cut</li>
</capacities>
<power>15</power>
<cooldownTime>2.5</cooldownTime>
<linkedBodyPartsGroup>LeftHand</linkedBodyPartsGroup>
<!-- <ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable> -->
<chanceFactor>0.5</chanceFactor>
<alwaysTreatAsWeapon>true</alwaysTreatAsWeapon>
</li>
<li>
<label>巨镰</label>
<capacities>
<li>Cut</li>
</capacities>
<power>15</power>
<cooldownTime>2.5</cooldownTime>
<linkedBodyPartsGroup>RightHand</linkedBodyPartsGroup>
<!-- <ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable> -->
<chanceFactor>0.5</chanceFactor>
<alwaysTreatAsWeapon>true</alwaysTreatAsWeapon>
</li>
</tools>
</MutantDef>
<ToolCapacityDef>
<defName>ARA_MimicNematodeShamblerBite</defName>
<label>撕咬</label>
</ToolCapacityDef>
<ManeuverDef>
<defName>ARA_MimicNematodeShamblerBite</defName>
<requiredCapacity>ARA_MimicNematodeShamblerBite</requiredCapacity>
<verb>
<verbClass>Verb_MeleeAttackDamage</verbClass>
<meleeDamageDef>ARA_MimicNematodeBite</meleeDamageDef>
</verb>
<logEntryDef>MeleeAttack</logEntryDef>
<combatLogRulesHit>Maneuver_Slash_MeleeHit</combatLogRulesHit>
<combatLogRulesDeflect>Maneuver_Slash_MeleeDeflect</combatLogRulesDeflect>
<combatLogRulesMiss>Maneuver_Slash_MeleeMiss</combatLogRulesMiss>
<combatLogRulesDodge>Maneuver_Slash_MeleeDodge</combatLogRulesDodge>
</ManeuverDef>
<PawnKindDef ParentName="MutantBase" Name="ARA_ShamblerBase" Abstract="True">
<mutant>ARA_MimicNematodeShambler</mutant>
<generateInitialNonFamilyRelations>false</generateInitialNonFamilyRelations>
</PawnKindDef>
<PawnKindDef ParentName="ARA_ShamblerBase">
<defName>ARA_MimicNematodeShamblerSwarmer</defName>
<label>阿拉克涅拟线种寄生体</label>
<combatPower>40</combatPower>
<gearHealthRange>0.2~0.4</gearHealthRange>
<itemQuality>Poor</itemQuality>
<apparelMoney>0~100</apparelMoney>
<apparelAllowHeadgearChance>0</apparelAllowHeadgearChance>
<apparelTags>
<li>IndustrialBasic</li>
<li>Neolithic</li>
</apparelTags>
<meleeAttackInfectionPathways>
<li>EntityAttacked</li>
</meleeAttackInfectionPathways>
</PawnKindDef>
</Defs>

View File

@@ -111,44 +111,6 @@
</east>
</offsets>
</li>
<!--<li>
<name>ArachnaeNode Hair BG</name>
<userCustomizable>true</userCustomizable>
<path></path>
<inFrontOfBody>false</inFrontOfBody>
<layerInvert>false</layerInvert>
<colorChannel>hair</colorChannel>
<defaultOffset>Center</defaultOffset>
<drawSize>1</drawSize>
<alignWithHead>true</alignWithHead>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<linkVariantIndexWithPrevious>true</linkVariantIndexWithPrevious>
<conditions>
<BodyPart>
<bodyPart>Head</bodyPart>
</BodyPart>
<Posture>
<drawnStanding>true</drawnStanding>
<drawnInBed>false</drawnInBed>
<drawnLaying>true</drawnLaying>
</Posture>
<RotStage>Fresh,Rotting</RotStage>
</conditions>
<offsets>
<west>
<layerOffset>-0.275</layerOffset>
</west>
<south>
<layerOffset>-0.299</layerOffset>
</south>
<north>
<layerOffset>-0.275</layerOffset>
</north>
<east>
<layerOffset>-0.275</layerOffset>
</east>
</offsets>
</li>-->
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Base</path>
<inFrontOfBody>true</inFrontOfBody>
@@ -365,6 +327,8 @@
<li>ARA_RW_Basic_Acid_Bladder_Gun</li>
<li>ARA_RW_Basic_Fist_Needle_Gun</li>
<li>ARA_MW_Bone_Sword</li>
<li>ARA_RW_Basic_SkyHive_Gun</li>
<li>ARA_RW_Toxic_Needle_MG</li>
</weaponList>
<onlyUseRaceRestrictedWeapons>true</onlyUseRaceRestrictedWeapons>
<!-- 可以穿戴的衣服 -->
@@ -519,8 +483,8 @@
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<MaxNutrition>1.05</MaxNutrition>
<EatingSpeed>2</EatingSpeed>
<MaxNutrition>0.5</MaxNutrition>
<CarryingCapacity>50</CarryingCapacity>
<MeatAmount>150</MeatAmount>
@@ -567,7 +531,6 @@
<baseHealthScale>1.5</baseHealthScale>
<!-- 解剖产物 -->
<leatherDef>ARA_Carapace</leatherDef>
<specificMeatDef>Meat_Megaspider</specificMeatDef>
<!-- 身体类型 -->
<body>Human</body>
<!-- 年龄阶段,较短 -->
@@ -598,17 +561,20 @@
</lifeStageWorkSettings>
<lifeStageAges Inherit="False">
<li>
<def>ARA_Queen_Adult</def>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
<soundWounded>Pawn_BigInsect_Pain</soundWounded>
<soundDeath>Pawn_BigInsect_Death</soundDeath>
<soundCall>Pawn_BigInsect_Call</soundCall>
<soundAngry>Pawn_BigInsect_Angry</soundAngry>
</li>
</lifeStageAges>
<canFlyInVacuum>false</canFlyInVacuum>
<!-- 身形大小,略大于常规人类 -->
<baseBodySize>2</baseBodySize>
<soundMeleeHitPawn>Pawn_Melee_BigBash_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_BigBash_HitBuilding</soundMeleeHitBuilding>
<soundMeleeMiss>Pawn_Melee_BigBash_Miss</soundMeleeMiss>
<soundMeleeDodge>Pawn_MeleeDodge</soundMeleeDodge>
<canFlyInVacuum>false</canFlyInVacuum>
<!-- 身形大小,略大于常规人类 -->
<baseBodySize>1</baseBodySize>
</race>
<!-- 工具设置(攻击方式) -->
@@ -667,12 +633,44 @@
<li Class="CompProperties_DrugAddict"/> -->
</comps>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace Name="ARA_NodeBase_Huge" ParentName="ARA_NodeBase" Abstract="True">
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
<alienPartGenerator>
<!-- 图像放大 -->
<customDrawSize>(1.2,1.2)</customDrawSize>
<customHeadDrawSize>(1.05,1.05)</customHeadDrawSize>
<customPortraitDrawSize>(0.9,0.9)</customPortraitDrawSize>
<borderScale>1.2</borderScale>
<atlasScale>1.2</atlasScale>
</alienPartGenerator>
</generalSettings>
<!-- 种族的允许和禁止特化设置 -->
<raceRestriction>
<!-- 武器列表 -->
<weaponList>
<li>ARA_RW_Acid_Mortar</li>
</weaponList>
</raceRestriction>
</alienRace>
<statBases>
<MaxNutrition>0.34</MaxNutrition>
</statBases>
<race>
<baseBodySize>3</baseBodySize>
<baseHealthScale>4</baseHealthScale>
<lifeExpectancy>10</lifeExpectancy>
</race>
</AlienRace.ThingDef_AlienRace>
<!-- 定义阿拉克涅节点虫种族 -->
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase_Huge">
<defName>ArachnaeNode_Race_Myrmecocystus</defName>
<label>阿拉克涅蜜罐种</label>
<description>阿拉克涅督虫之一,拥有非常广泛食谱,可以吞下许多未经处理的生物并将其分解为阿拉克涅虫蜜,以滋养虫群。这种督虫除了生产虫蜜外也能执行烹饪和种植工作。\n\n作为督虫她可以繁育并监管若干阿拉克涅食腐种辅虫以协助巢穴进行收割和播种工作。</description>
<description>阿拉克涅督虫之一,拥有广泛食谱的大型虫族,可以吞下许多未经处理的生物并将其分解为阿拉克涅虫蜜,以滋养虫群。\n\n她可以进行搬运、烹饪和种植工作战斗技能非常差。\n\n作为督虫她可以繁育并监管若干阿拉克涅食腐种辅虫以协助巢穴进行收割和播种工作。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -680,10 +678,10 @@
<!-- 额外身体部件 -->
<bodyAddons>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Myrmecocystus_Addons_Stomach</path>
<path>
ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Myrmecocystus_Addons_Stomach</path>
<inFrontOfBody>false</inFrontOfBody>
<conditions>
</conditions>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
</li>
</bodyAddons>
</alienPartGenerator>
@@ -691,20 +689,18 @@
<!-- 种族的允许和禁止特化设置 -->
<raceRestriction>
<!-- 食物列表 -->
<whiteFoodList Inherit="False"/>
<whiteFoodList Inherit="False" />
<blackFoodList>
<li>ARA_InsectJelly</li>
</blackFoodList>
<onlyEatRaceRestrictedFood>false</onlyEatRaceRestrictedFood>
<!-- 武器列表 -->
<weaponList Inherit="False"/>
</raceRestriction>
</alienRace>
<comps>
<li Class="ArachnaeSwarm.CompProperties_MilkableArachnae">
<milkDef>ARA_InsectJelly</milkDef>
<milkIntervalDays>3</milkIntervalDays>
<milkAmount>4</milkAmount>
<milkIntervalDays>1</milkIntervalDays>
<milkAmount>10</milkAmount>
</li>
<li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier">
<freeProduction>true</freeProduction>
@@ -757,24 +753,16 @@
<foodType>OmnivoreHuman,CarnivoreAnimal,OvivoreAnimal,VegetarianRoughAnimal</foodType>
<!-- 身体类型 -->
<body>ArachnaeMyrmecocystus_Body</body>
<!-- 身形大小 -->
<baseBodySize>2.5</baseBodySize>
<!-- 血量上限 -->
<baseHealthScale>3</baseHealthScale>
<!-- 蜜罐虫的寿命很低 -->
<lifeExpectancy>1.5</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_ShieldHead</defName>
<label>阿拉克涅盾头种</label>
<description>阿拉克涅督虫之一,拥有过度生长而覆盖头部和腿部的甲壳,防御力超群的同时还可以定时剥落甲壳素供虫巢使用。坚韧的鳌刺挥舞起来非常缓慢但是可以破开岩壁和固定结构,以完成虫群的采矿和建筑工作。\n\n作为督虫她可以繁育并监管若干阿拉克涅坚颚种辅虫以协助巢穴开采矿脉。</description>
<description>阿拉克涅督虫之一,拥有过度生长而覆盖头部和腿部的甲壳,可以定时剥落甲壳素供虫巢使用。\n\n她可以进行搬运、采矿和建筑工作战斗技能平平无奇但是拥有较好的防御。\n\n作为督虫她可以繁育并监管若干阿拉克涅坚颚种辅虫以协助巢穴开采矿脉。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -798,6 +786,7 @@
</west>
</offsets>
<inFrontOfBody>true</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
</li>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_ShieldBody</path>
@@ -817,6 +806,7 @@
</offsets>
<inFrontOfBody>true</inFrontOfBody>
<layerInvert>false</layerInvert>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
</li>
</bodyAddons>
</alienPartGenerator>
@@ -828,8 +818,8 @@
<comps>
<li Class="ArachnaeSwarm.CompProperties_MilkableArachnae">
<milkDef>ARA_Carapace</milkDef>
<milkIntervalDays>3</milkIntervalDays>
<milkAmount>25</milkAmount>
<milkIntervalDays>1</milkIntervalDays>
<milkAmount>15</milkAmount>
</li>
<li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier">
<freeProduction>true</freeProduction>
@@ -873,9 +863,11 @@
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>1</ArmorRating_Blunt>
<ArmorRating_Sharp>1.25</ArmorRating_Sharp>
<ArmorRating_Heat>1</ArmorRating_Heat>
<ArmorRating_Blunt>0.75</ArmorRating_Blunt>
<ArmorRating_Sharp>1</ArmorRating_Sharp>
<ArmorRating_Heat>0.5</ArmorRating_Heat>
<MaxNutrition>0.51</MaxNutrition>
</statBases>
<race>
@@ -886,19 +878,13 @@
<!-- 血量上限 -->
<baseHealthScale>5</baseHealthScale>
<!-- 蜜罐虫的寿命很低 -->
<lifeExpectancy>2</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
<lifeExpectancy>1</lifeExpectancy>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_WeaponSmith</defName>
<label>阿拉克涅工艺种</label>
<description>阿拉克涅督虫之一,是少数拥有结茧能力的非女皇种阿拉克涅虫族——她们可以排出一枚器官茧,这枚茧将按照其信息素所标定的方向定向演化出一个武装器官,以供虫群使用。除此之外,她们的辅肢比普通的虫族更加复杂灵活,这使得她们不仅可以执行手工艺术等复杂的工作,也可以操作武装器官——虽然她们本身极度脆弱。\n\n作为督虫她可以繁育并监管若干阿拉克涅家政种辅虫以协助巢穴进行清洁和搬运工作。</description>
<description>阿拉克涅督虫之一,是少数拥有结茧能力的非女皇种阿拉克涅虫族——她们可以排出一枚器官茧,这枚茧将按照其信息素所标定的方向定向演化出一个武装器官,以供虫群使用。\n\n她可以进行搬运、手工艺术工作,战斗技能平平无奇,但本身极度脆弱。\n\n作为督虫她可以繁育并监管若干阿拉克涅家政种辅虫以协助巢穴进行清洁和搬运工作。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -908,6 +894,7 @@
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_WeaponSmith</path>
<inFrontOfBody>false</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<offsets>
<north>
<layerOffset>-0.275</layerOffset>
@@ -968,6 +955,8 @@
<ArmorRating_Blunt>0.1</ArmorRating_Blunt>
<ArmorRating_Sharp>0.1</ArmorRating_Sharp>
<ArmorRating_Heat>0.05</ArmorRating_Heat>
<MaxNutrition>1.26</MaxNutrition>
</statBases>
<race>
@@ -976,18 +965,12 @@
<baseBodySize>0.8</baseBodySize>
<baseHealthScale>0.75</baseHealthScale>
<lifeExpectancy>5</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_Fighter</defName>
<label>阿拉克涅战士种</label>
<description>阿拉克涅督虫之一,是巢穴中真正的战士,除了战斗外也可以进行狩猎和驯兽工作。其拥有强大的可塑性基因,随着科技的解锁其将获得更多的能力。\n\n作为督虫她可以向敌人投射寿命有限但是非常恼人的阿拉克涅酸噬种辅虫以阻止敌人的远程火力开火。</description>
<description>阿拉克涅督虫之一,是巢穴中真正的战士,其拥有强大的可塑性基因,随着科技的解锁其将获得更多的能力。\n\n她可以进行搬运、狩猎和驯兽工作,战斗技能非常亮眼,并且移动敏捷。\n\n作为督虫,她可以向敌人投射寿命有限但是非常恼人的阿拉克涅酸噬种辅虫,以阻止敌人的远程火力开火。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -997,10 +980,12 @@
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Claw</path>
<inFrontOfBody>true</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
</li>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Tail</path>
<inFrontOfBody>false</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<offsets>
<north>
<layerOffset>-0.275</layerOffset>
@@ -1020,7 +1005,7 @@
<!-- 基础属性设置 -->
<statBases>
<!-- 移动速度 -->
<MoveSpeed>4.5</MoveSpeed>
<MoveSpeed>5</MoveSpeed>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
@@ -1043,6 +1028,8 @@
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
<ArmorRating_Sharp>0.4</ArmorRating_Sharp>
<ArmorRating_Heat>0.3</ArmorRating_Heat>
<MaxNutrition>1.26</MaxNutrition>
</statBases>
<tools>
@@ -1062,21 +1049,15 @@
<race>
<!-- 身体类型 -->
<body>ArachnaeFighter_Body</body>
<baseBodySize>0.85</baseBodySize>
<baseBodySize>0.8</baseBodySize>
<baseHealthScale>2</baseHealthScale>
<lifeExpectancy>5</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
<lifeExpectancy>2</lifeExpectancy>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_Facehugger</defName>
<label>阿拉克涅原虫种</label>
<description>阿拉克涅督虫之一,呈现高度未分化状态的特殊督虫,可以通过独特的神经链接管控制受害者的身体,并释放灵能信号以使得周围的人忽略其存在。\n\n不同于普通阿拉克涅虫族高度未分化的身体决定了其无法孕育任何辅虫,在完成寄生前也难以胜任任何工作</description>
<description>阿拉克涅督虫之一,呈现高度未分化状态的特殊督虫,可以通过独特的神经链接管控制受害者的身体,并释放灵能信号以使得周围的人忽略其存在。然而她本身实在过于脆弱,在完成寄生前难以胜任任何工作。\n\n她可以进行所有非研究工作战斗技能约等于无。\n\n不同于普通阿拉克涅虫族高度未分化的身体决定了其无法孕育任何辅虫。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -1102,18 +1083,19 @@
<!-- 种族的允许和禁止特化设置 -->
<raceRestriction>
<!-- 武器列表 -->
<weaponList Inherit="False"/>
<weaponList Inherit="False" />
</raceRestriction>
</alienRace>
<statBases>
<MoveSpeed>5</MoveSpeed>
<EatingSpeed>5</EatingSpeed>
<MaxNutrition>1</MaxNutrition>
<CarryingCapacity>100</CarryingCapacity>
<MeatAmount>20</MeatAmount>
<LeatherAmount>5</LeatherAmount>
<MeleeDodgeChance>1.5</MeleeDodgeChance>
<MaxNutrition>2</MaxNutrition>
</statBases>
<race>
@@ -1121,12 +1103,6 @@
<baseBodySize>0.5</baseBodySize>
<baseHealthScale>0.25</baseHealthScale>
<lifeExpectancy>30</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
</race>
<comps>
<li Class="ArachnaeSwarm.CompProperties_HediffGiver">
@@ -1138,11 +1114,10 @@
</li>
</comps>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_Skyraider</defName>
<label>阿拉克涅空天种</label>
<description>阿拉克涅督虫中的精锐,进化出了强大的飞行能力,是巢穴中无可争议的空中霸主。\n\n作为为数不多拥有飞行能力的虫族她可以从空中掠袭猎物并将其带至千米高空之上俯冲投下只留其余猎物在地面无助的挣扎。</description>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase_Huge">
<defName>ArachnaeNode_Race_Smokepop</defName>
<label>阿拉克涅浓雾种</label>
<description>阿拉克涅督虫之一,身披厚重甲壳的大型虫族,拥有在大范围内喷射信息素以召唤辅虫虫群能力,虽然移动速度比较慢,但是在战斗中就如同装甲车一样难以撼动。\n\n她可以进行搬运和医护工作拥有不错的战斗技能防御力和伤害耐受能力强大。\n\n作为督虫她可以繁育并监管大量阿拉克涅家政种辅虫以协助巢穴进行清洁和搬运工作。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
@@ -1150,12 +1125,100 @@
<!-- 额外身体部件 -->
<bodyAddons>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Claw</path>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Smokepop_Armor</path>
<inFrontOfBody>true</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
</li>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Tail</path>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Smokepop_Tail</path>
<inFrontOfBody>false</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<offsets>
<north>
<layerOffset>-0.275</layerOffset>
</north>
</offsets>
</li>
</bodyAddons>
<!-- 图像放大 -->
<customDrawSize>(1.2,1.2)</customDrawSize>
<customHeadDrawSize>(1.05,1.05)</customHeadDrawSize>
<customPortraitDrawSize>(0.9,0.9)</customPortraitDrawSize>
<!-- <borderScale>4</borderScale>
<atlasScale>4</atlasScale> -->
</alienPartGenerator>
</generalSettings>
</alienRace>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AutoMechCarrier">
<freeProduction>true</freeProduction>
<disableHediff>WULA_MechCarrierSwitchHediff</disableHediff>
<fixedIngredient>ARA_InsectJelly</fixedIngredient>
<maxIngredientCount>500</maxIngredientCount>
<startingIngredientCount>500</startingIngredientCount>
<costPerPawn>999</costPerPawn>
<cooldownTicks>9999</cooldownTicks>
<productionQueue>
<li>
<!-- <pawnKind>ArachnaeBase_Race_Slavey</pawnKind> -->
<pawnKind>ArachnaeBase_Race_Maid</pawnKind>
<count>5</count>
<cooldownTicks>1000</cooldownTicks>
</li>
</productionQueue>
<spawnEffecter>CocoonDestroyed</spawnEffecter>
</li>
</comps>
<!-- 基础属性设置 -->
<statBases>
<!-- 移动速度 -->
<MoveSpeed>1.55</MoveSpeed>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<!-- <EatingSpeed>5</EatingSpeed> -->
<MaxNutrition>3</MaxNutrition>
<CarryingCapacity>100</CarryingCapacity>
<MeatAmount>150</MeatAmount>
<LeatherAmount>150</LeatherAmount>
<MeleeDodgeChance>0.5</MeleeDodgeChance>
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
<!-- <SocialImpact>1</SocialImpact> -->
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>1</ArmorRating_Blunt>
<ArmorRating_Sharp>1.2</ArmorRating_Sharp>
<ArmorRating_Heat>0.75</ArmorRating_Heat>
</statBases>
<race>
<!-- 身体类型 -->
<body>ArachnaeFighter_Body</body>
<baseHealthScale>4</baseHealthScale>
<lifeExpectancy>5</lifeExpectancy>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_Skyraider</defName>
<label>阿拉克涅空天种</label>
<description>阿拉克涅督虫之一,众督虫中的精锐,虽然身材娇小但是拥有引以为傲的强大飞行能力,是巢穴中无可争议的空中霸主。\n\n她可以进行搬运工作拥有不错的战斗技能在战场上行动时非常灵活。\n\n作为督虫她可以向敌人发射天巢种辅虫这种辅虫会自动修正姿态追踪敌军并在命中后对敌人进行持续啃咬。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
<alienPartGenerator>
<!-- 额外身体部件 -->
<bodyAddons>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Skyraider_Tail</path>
<inFrontOfBody>false</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<offsets>
<north>
<layerOffset>-0.275</layerOffset>
@@ -1188,7 +1251,7 @@
<!-- 基础属性设置 -->
<statBases>
<!-- 移动速度 -->
<MoveSpeed>4.5</MoveSpeed>
<MoveSpeed>4</MoveSpeed>
<MaxFlightTime>9999</MaxFlightTime>
<FlightCooldown>0</FlightCooldown>
@@ -1196,14 +1259,12 @@
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<!-- <EatingSpeed>5</EatingSpeed> -->
<MaxNutrition>2</MaxNutrition>
<CarryingCapacity>100</CarryingCapacity>
<MeatAmount>60</MeatAmount>
<LeatherAmount>30</LeatherAmount>
<MeleeDodgeChance>1.25</MeleeDodgeChance>
<MeleeHitChance>1.25</MeleeHitChance>
<MeleeDodgeChance>1.5</MeleeDodgeChance>
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
@@ -1211,39 +1272,90 @@
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
<ArmorRating_Sharp>0.4</ArmorRating_Sharp>
<ArmorRating_Heat>0.3</ArmorRating_Heat>
</statBases>
<ArmorRating_Blunt>0.3</ArmorRating_Blunt>
<ArmorRating_Sharp>0.2</ArmorRating_Sharp>
<ArmorRating_Heat>0.2</ArmorRating_Heat>
<tools>
<li>
<label>巨镰</label>
<capacities>
<li>Cut</li>
</capacities>
<power>20</power>
<cooldownTime>2.5</cooldownTime>
<linkedBodyPartsGroup>ARA_Sickles</linkedBodyPartsGroup>
<!-- <ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable> -->
<chanceFactor>0.5</chanceFactor>
</li>
</tools>
<MaxNutrition>1.26</MaxNutrition>
</statBases>
<race>
<!-- 身体类型 -->
<body>ArachnaeFighter_Body</body>
<renderTree>ARA_ArachnaeRenderTree</renderTree>
<flightStartChanceOnJobStart>1.0</flightStartChanceOnJobStart>
<baseBodySize>0.85</baseBodySize>
<baseHealthScale>2</baseHealthScale>
<baseBodySize>0.8</baseBodySize>
<baseHealthScale>1.5</baseHealthScale>
<lifeExpectancy>5</lifeExpectancy>
</race>
</AlienRace.ThingDef_AlienRace>
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_NeuroSwarm</defName>
<label>阿拉克涅织域种</label>
<description>阿拉克涅督虫之一,是阿拉克涅虫群中最为特殊的虫族,织域种虽然受到女皇种监管,但仍然具有强大的高级智慧和自我意志,织域种之间能够构建一种高度互联的神经网络从而进行复杂的研究和计算工作,织域种进行计算工作时无法感知外界环境,因此她们是虫群的重要保护对象。</description>
<alienRace>
<generalSettings>
<!-- 各种零件定义 -->
<alienPartGenerator>
<!-- 额外身体部件 -->
<bodyAddons>
<li>
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_WeaponSmith</path>
<inFrontOfBody>false</inFrontOfBody>
<scaleWithPawnDrawsize>true</scaleWithPawnDrawsize>
<offsets>
<north>
<layerOffset>-0.275</layerOffset>
</north>
</offsets>
</li>
</bodyAddons>
</alienPartGenerator>
</generalSettings>
<raceRestriction>
<onlyEatRaceRestrictedFood>true</onlyEatRaceRestrictedFood>
</raceRestriction>
</alienRace>
<comps>
</comps>
<!-- 基础属性设置 -->
<statBases>
<!-- 移动速度 -->
<MoveSpeed>3.5</MoveSpeed>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<!-- <EatingSpeed>5</EatingSpeed> -->
<MaxNutrition>2</MaxNutrition>
<CarryingCapacity>100</CarryingCapacity>
<MeatAmount>40</MeatAmount>
<LeatherAmount>10</LeatherAmount>
<MeleeDodgeChance>0.75</MeleeDodgeChance>
<!-- <MeleeHitChance>1</MeleeHitChance> -->
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
<!-- <SocialImpact>1</SocialImpact> -->
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>0.1</ArmorRating_Blunt>
<ArmorRating_Sharp>0.1</ArmorRating_Sharp>
<ArmorRating_Heat>0.05</ArmorRating_Heat>
<MaxNutrition>1.26</MaxNutrition>
</statBases>
<race>
<!-- 身体类型 -->
<body>ArachnaeWeaponSmith_Body</body>
<baseBodySize>0.8</baseBodySize>
<baseHealthScale>0.75</baseHealthScale>
<lifeExpectancy>5</lifeExpectancy>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
</race>
</AlienRace.ThingDef_AlienRace>
</Defs>

View File

@@ -9,67 +9,9 @@
<RoyalFavorValue>3</RoyalFavorValue>
</statBases>
<tools>
<li>
<label>left fist</label>
<labelNoLocation>fist</labelNoLocation>
<capacities>
<li>Blunt</li>
</capacities>
<power>8.2</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>LeftHand</linkedBodyPartsGroup>
<surpriseAttack>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>14</amount>
</li>
</extraMeleeDamages>
</surpriseAttack>
</li>
<li>
<label>right fist</label>
<labelNoLocation>fist</labelNoLocation>
<capacities>
<li>Blunt</li>
</capacities>
<power>8.2</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>RightHand</linkedBodyPartsGroup>
<surpriseAttack>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>14</amount>
</li>
</extraMeleeDamages>
</surpriseAttack>
</li>
<li>
<label>teeth</label>
<capacities>
<li>Bite</li>
</capacities>
<power>8.2</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>Teeth</linkedBodyPartsGroup>
<chanceFactor>0.07</chanceFactor>
<soundMeleeHit>Pawn_Melee_HumanBite_Hit</soundMeleeHit>
<soundMeleeMiss>Pawn_Melee_HumanBite_Miss</soundMeleeMiss>
</li>
<li>
<label>head</label>
<capacities>
<li>Blunt</li>
</capacities>
<power>5</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.2</chanceFactor>
</li>
</tools>
<race>
<useMeatFrom>Megaspider</useMeatFrom>
<thinkTreeMain>Humanlike</thinkTreeMain>
<thinkTreeConstant>HumanlikeConstant</thinkTreeConstant>
<intelligence>Humanlike</intelligence>
@@ -486,6 +428,12 @@
<!-- 生育能力 -->
<onlyReproduceWithRestrictedRaces>true</onlyReproduceWithRestrictedRaces>
<canReproduce>false</canReproduce>
<!-- 允许操纵的配方 -->
<recipeList>
<li>ARA_WeaponSmith_Upgrade_1_Stage</li>
<!-- <li>ARA_WeaponSmith_Upgrade_2_Stage</li> -->
<!-- <li>ARA_WeaponSmith_Upgrade_3_Stage</li> -->
</recipeList>
<!-- 允许的工作台类型,放开以供其他种族使用 -->
<!-- <workGiverList>
<li>WULA_Large_Mechine_proudctor_Bills</li>
@@ -656,7 +604,6 @@
<baseHealthScale>10</baseHealthScale>
<!-- 解剖产物 -->
<leatherDef>ARA_Carapace</leatherDef>
<specificMeatDef>Meat_Megaspider</specificMeatDef>
<soundMeleeHitPawn>Pawn_Melee_BigBash_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_BigBash_HitBuilding</soundMeleeHitBuilding>

View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- ==================== 1. 物品定义:阿拉克涅信息素溶剂 ==================== -->
<ThingDef ParentName="MakeableDrugPillBase">
<defName>ARA_PheromoneSolvent</defName>
<label>阿拉克涅信息素溶剂</label>
<description>一种合成的化学制剂,能够模拟阿拉克涅虫群内部用于区分敌我的信息素。定期注射可以欺骗宿主体内的寄生虫,使其进入休眠的共生状态,从而抑制其致命的增殖行为。</description>
<descriptionHyperlinks>
<HediffDef>ARA_SymbioticStabilizer</HediffDef>
<HediffDef>ARA_MimicNematode</HediffDef>
</descriptionHyperlinks>
<graphicData>
<texPath>Things/Item/Drug/WakeUp</texPath> <!-- 暂时使用WakeUp的贴图可后续替换 -->
<graphicClass>Graphic_StackCount</graphicClass>
<color>(1.0, 0.647, 0.0, 0.5)</color> <!-- 橙色 -->
</graphicData>
<rotatable>false</rotatable>
<statBases>
<WorkToMake>1000</WorkToMake>
<MarketValue>50</MarketValue>
<Mass>0.01</Mass>
</statBases>
<techLevel>Industrial</techLevel>
<ingestible>
<drugCategory>Medical</drugCategory> <!-- 定义为医疗品,而非娱乐品 -->
<outcomeDoers>
<li Class="IngestionOutcomeDoer_GiveHediff">
<hediffDef>ARA_SymbioticStabilizer</hediffDef>
<severity>1.0</severity> <!-- 每次服用直接将效果补满 -->
</li>
</outcomeDoers>
</ingestible>
<recipeMaker>
<researchPrerequisite>MedicineProduction</researchPrerequisite> <!-- 假设需要基础制药解锁 -->
<recipeUsers>
<li>DrugLab</li>
</recipeUsers>
</recipeMaker>
<costList>
<Neutroamine>2</Neutroamine>
<ARA_InsectJelly>5</ARA_InsectJelly> <!-- 使用虫胶作为特色材料 -->
</costList>
<comps>
<li Class="CompProperties_Drug">
<chemical>ARA_Pheromone</chemical>
<addictiveness>0.05</addictiveness>
<needLevelOffset>1</needLevelOffset>
<listOrder>1000</listOrder>
</li>
</comps>
</ThingDef>
<!-- ==================== 2. Hediff定义共生稳定器效果 ==================== -->
<HediffDef>
<defName>ARA_SymbioticStabilizer</defName>
<label>信息素抑制</label>
<labelNoun>一种信息素抑制效果</labelNoun>
<description>阿拉克涅信息素溶剂的效果正在生效,它模拟了虫群的共生信号,抑制了体内寄生体的活性。</description>
<hediffClass>HediffWithComps</hediffClass>
<defaultLabelColor>(0.7, 1.0, 0.7)</defaultLabelColor>
<isBad>false</isBad>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-0.34</severityPerDay> <!-- 严重性每天降低0.34大约3天从1.0掉到0 -->
<showHoursToRecover>true</showHoursToRecover>
</li>
</comps>
</HediffDef>
<!-- ==================== 3. 物品定义:阿拉克涅拟线种虫卵 ==================== -->
<ThingDef ParentName="MakeableDrugPillBase">
<defName>ARA_NematodeEgg</defName>
<label>阿拉克涅拟线种虫卵</label>
<description>一个经过特殊处理的阿拉克涅拟线种虫卵,可以被直接服用。服用后,虫卵会迅速在宿主体内孵化并释放大量阿拉克涅拟线虫,导致极其严重的感染。</description>
<descriptionHyperlinks>
<HediffDef>ARA_MimicNematode</HediffDef>
</descriptionHyperlinks>
<graphicData>
<texPath>Things/Item/Drug/Luciferium</texPath>
<graphicClass>Graphic_StackCount</graphicClass>
<color>(100,50,100)</color> <!-- 深紫色 -->
</graphicData>
<statBases>
<MarketValue>75</MarketValue>
<Mass>0.05</Mass>
</statBases>
<techLevel>Industrial</techLevel>
<ingestible>
<drugCategory>None</drugCategory> <!-- 修正:这不是药物,不应被药物政策管理 -->
<foodType>AnimalProduct</foodType>
<outcomeDoers>
<li Class="IngestionOutcomeDoer_GiveHediff">
<hediffDef>ARA_MimicNematode</hediffDef>
<severity>0.5</severity> <!-- 直接给予0.7的严重性 -->
</li>
</outcomeDoers>
</ingestible>
<recipeMaker IsNull="True" /> <!-- 明确声明此物品不可制造,以覆盖父类的设置 -->
</ThingDef>
<!-- ==================== 3. 阿拉克涅信息素成瘾机制 ==================== -->
<ChemicalDef>
<defName>ARA_Pheromone</defName>
<label>阿拉克涅信息素</label>
<addictionHediff>ARA_PheromoneAddiction</addictionHediff>
</ChemicalDef>
<NeedDef ParentName="DrugAddictionNeedBase">
<defName>Chemical_ARA_Pheromone</defName>
<needClass>Need_Chemical</needClass>
<label>信息素依赖</label>
<description>由于长期使用阿拉克涅信息素溶剂,此人的身体已经习惯了这种外部信息素的存在。如果中断使用,体内的拟线虫将因为失去抑制而猛烈反扑。</description>
<fallPerDay>0.333</fallPerDay>
<listPriority>50</listPriority>
</NeedDef>
<HediffDef ParentName="AddictionBase">
<defName>ARA_PheromoneAddiction</defName>
<label>信息素依赖</label>
<description>对阿拉克涅信息素溶剂产生了化学依赖。需要定期使用来维持体内的拟线虫生态平衡,否则会产生严重的戒断反应。</description>
<hediffClass>Hediff_Addiction</hediffClass>
<chemicalNeed>Chemical_ARA_Pheromone</chemicalNeed>
<stages>
<li>
<!-- 需求满足时,无效果 -->
</li>
<li>
<label>戒断反应</label>
<capMods>
<li>
<capacity>Consciousness</capacity>
<offset>-0.1</offset>
</li>
</capMods>
<hediffGivers>
<li Class="ArachnaeSwarm.HediffGiver_RandomWithSeverity">
<hediff>ARA_MimicNematode</hediff>
<mtbDays>1</mtbDays>
<severityRange>0.1~0.2</severityRange>
</li>
</hediffGivers>
</li>
</stages>
</HediffDef>
<ThoughtDef>
<defName>ARA_PheromoneWithdrawal</defName>
<workerClass>ThoughtWorker_Hediff</workerClass>
<hediff>ARA_PheromoneAddiction</hediff>
<validWhileDespawned>true</validWhileDespawned>
<stages>
<li>
<visible>false</visible>
</li>
<li>
<label>信息素戒断</label>
<description>我感觉很糟糕,体内的某些东西正在变得活跃......我需要信息素溶剂。</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<Defs>
<ThingDef Name="ARA_BaseGas" Abstract="True">
<thingClass>Gas</thingClass>
<label>gas</label>
<category>Gas</category>
<altitudeLayer>Gas</altitudeLayer>
<useHitPoints>false</useHitPoints>
<tickerType>Normal</tickerType>
<graphicData>
<graphicClass>Graphic_Gas</graphicClass>
<shaderType>Transparent</shaderType>
</graphicData>
</ThingDef>
<!-- Gas : Thing -->
<ThingDef ParentName="ARA_BaseGas">
<defName>ARA_ReinforceGasCloud</defName>
<label>阿拉克涅信息素烟雾</label>
<graphicData>
<texPath>Things/Gas/Puff</texPath>
<drawSize>2.6</drawSize>
<color>(1.0, 0.647, 0.0, 0.5)</color>
</graphicData>
<gas>
<expireSeconds>
<min>15</min>
<max>20</max>
</expireSeconds>
<rotationSpeed>20</rotationSpeed>
</gas>
<thingClass>ArachnaeSwarm.OPToxicGas</thingClass>
<modExtensions>
<li Class="ArachnaeSwarm.OPToxicDefs">
<OPToxicHediff>ARA_Unburnable</OPToxicHediff>
<OPToxicSeverity>0.1</OPToxicSeverity>
<OPSevUpTickPeriod>240</OPSevUpTickPeriod>
</li>
</modExtensions>
</ThingDef>
</Defs>

View File

@@ -63,120 +63,10 @@
<WorkToMake>3000</WorkToMake>
</statBases>
</ThingDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_BioforgeIncubator_ClothBase</defName>
<label>投放孵化茧 基础织物</label>
<description>投放一枚织物茧,内含可以孵化一套基础织物的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_BioforgeIncubator_ClothBase_Proj</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_4DIL</requiredResearch>
<failMessage>需要科技 基因节点DIL-4"编织" 以解锁此孵化路径</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_BioforgeIncubator_ClothBase_Proj</defName>
<projectile>
<spawnsThingDef>ARA_BioforgeIncubator_ClothBase</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_BioforgeIncubator_Base">
<defName>ARA_BioforgeIncubator_ClothBase</defName>
<label>阿拉克涅孵化茧 基础织物</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一套基础织物装备的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为-30~55°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_Bodystocking_White</ThingDef>
<ThingDef>ARA_Bodystocking_Black</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_4DIL</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_Bodystocking_White</thingDef>
<productionTicks>6000</productionTicks>
<totalNutritionNeeded>1</totalNutritionNeeded>
</li>
<li>
<thingDef>ARA_Bodystocking_Black</thingDef>
<productionTicks>6000</productionTicks>
<totalNutritionNeeded>1</totalNutritionNeeded>
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>-30</minSafeTemperature>
<maxSafeTemperature>55</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-30</minSafeTemperature>
<maxSafeTemperature>55</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<ApparelLayerDef>
<defName>Shield</defName>
<label>盾牌</label>
<drawOrder>275</drawOrder>
</ApparelLayerDef>
</Defs>
</Defs>

View File

@@ -0,0 +1,631 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!---->
<ThingDef ParentName="BaseMeleeWeapon_Sharp_Quality">
<defName>ARA_MW_Bone_Sword</defName>
<label>武装器官"骨刃"</label>
<description>阿拉克涅虫群督虫使用基础近战武装器官,通过多根外露神经束与督虫的辅肢相连。尽管它只是一块坚硬的剑形骨片,但是丝毫不影响那些拥有无穷蛮力的阿拉克涅虫群督虫使用它将侵犯虫巢之敌一一斩首。</description>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Melee</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_MW_Bone_Sword</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>1</drawSize>
</graphicData>
<uiIconScale>1</uiIconScale>
<!-- <equippedAngleOffset>-65</equippedAngleOffset> -->
<techLevel>Animal</techLevel>
<!-- <equippedAngleOffset>-25</equippedAngleOffset> -->
<costStuffCount>0</costStuffCount>
<stuffCategories Inherit="False"/>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<statBases>
<WorkToMake>1000</WorkToMake>
<Mass>5</Mass>
</statBases>
<tools Inherit="False">
<li>
<label>横扫</label>
<capacities>
<li>Cut</li>
</capacities>
<power>15</power>
<cooldownTime>1.3</cooldownTime>
<armorPenetration>0.50</armorPenetration>
</li>
<li>
<label>下砸</label>
<capacities>
<li>Poke</li>
</capacities>
<power>12</power>
<armorPenetration>0.20</armorPenetration>
<cooldownTime>1.5</cooldownTime>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>15</amount>
</li>
</extraMeleeDamages>
</li>
</tools>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite Inherit="False" />
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
</ThingDef>
<!---->
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Basic_Fist_Needle_Gun</defName>
<label>武装器官"拳针枪"</label>
<description>阿拉克涅虫群督虫使用基础远程武装器官,外表就像一只拳套,可以通过神经束缠绕接在阿拉克涅督虫的辅肢上。这种武器小巧轻盈,虽然射程很短,但是面对敌人时能喷出一整排的带毒尖刺,把对手扎个透心凉。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Fist_Needle_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>0.75</drawSize>
</graphicData>
<uiIconScale>1.3</uiIconScale>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite>ARA_Technology_5PAV</researchPrerequisite>
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>0.5</Mass>
<AccuracyTouch>0.85</AccuracyTouch>
<AccuracyShort>0.6</AccuracyShort>
<AccuracyMedium>0.45</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>1.25</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>0.25</warmupTime>
<defaultProjectile>Bullet_ARA_RW_Basic_Fist_Needle_Gun</defaultProjectile>
<range>14</range>
<burstShotCount>6</burstShotCount>
<ticksBetweenBurstShots>1</ticksBetweenBurstShots>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>25</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<tools Inherit="False">
<li>
<label>拳针枪拳击</label>
<capacities>
<li>Poke</li>
</capacities>
<power>10</power>
<armorPenetration>0.25</armorPenetration>
<cooldownTime>1.25</cooldownTime>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>12</amount>
</li>
</extraMeleeDamages>
</li>
</tools>
<comps>
<li Class="WulaFallenEmpire.CompProperties_CustomUniqueWeapon" MayRequire="Ludeon.RimWorld.Odyssey">
<forcedTraits>
<li>ARA_Weapon_Damage_Toxid</li>
</forcedTraits>
<numTraitsRange>
<min>1</min>
<max>1</max>
</numTraitsRange>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Basic_Fist_Needle_Gun</defName>
<label>毒针</label>
<graphicData>
<texPath>Things/Projectile/Bullet_Small</texPath>
<graphicClass>Graphic_Single</graphicClass>
<color>(117, 204, 49, 180)</color>
</graphicData>
<projectile>
<damageDef>ARA_Fist_Needle</damageDef>
<damageAmountBase>2</damageAmountBase>
<speed>40</speed>
</projectile>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Toxic_Needle_MG</defName>
<label>武装器官"风暴刺针枪"</label>
<description>阿拉克涅虫群督虫所使用的武装器官,拥有四排刺针管道,可以在联结神经束的指挥下交替发射大量的毒针,虽然准度较差但是威力不逊色于人类所使用的机枪。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Fist_Needle_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>0.75</drawSize>
</graphicData>
<uiIconScale>1.3</uiIconScale>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite>ARA_Technology_5PAV</researchPrerequisite>
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>4</Mass>
<AccuracyTouch>0.5</AccuracyTouch>
<AccuracyShort>0.4</AccuracyShort>
<AccuracyMedium>0.35</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>2.5</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>0.8</warmupTime>
<defaultProjectile>Bullet_ARA_RW_Basic_Fist_Needle_Gun</defaultProjectile>
<range>22</range>
<burstShotCount>32</burstShotCount>
<ticksBetweenBurstShots>2</ticksBetweenBurstShots>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>25</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T2</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<comps>
<li Class="WulaFallenEmpire.CompProperties_CustomUniqueWeapon" MayRequire="Ludeon.RimWorld.Odyssey">
<forcedTraits>
<li>ARA_Weapon_Damage_Toxid</li>
</forcedTraits>
<numTraitsRange>
<min>1</min>
<max>1</max>
</numTraitsRange>
</li>
</comps>
</ThingDef>
<!---->
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Basic_Acid_Bladder_Gun</defName>
<label>武装器官"酸液枪"</label>
<description>阿拉克涅虫群督虫使用基础远程武装器官,可以通过肌肉的瞬间加压喷出一团包含阿拉克涅酸液的液体团。这种酸液团的飞行速度很慢,但是能在目标地点炸开,并灼烧所有粘上酸液的敌人。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Acid_Bladder_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.2</drawSize>
</graphicData>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite>ARA_Technology_7VXI</researchPrerequisite>
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>3.5</Mass>
<AccuracyTouch>0.5</AccuracyTouch>
<AccuracyShort>0.6</AccuracyShort>
<AccuracyMedium>0.45</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>2.5</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>1.0</warmupTime>
<forcedMissRadius>1</forcedMissRadius>
<defaultProjectile>Bullet_ARA_RW_Basic_Acid_Bladder_Gun</defaultProjectile>
<isMortar>true</isMortar>
<requireLineOfSight>false</requireLineOfSight>
<minRange>3</minRange>
<range>28</range>
<burstShotCount>1</burstShotCount>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<comps>
<li Class="WulaFallenEmpire.CompProperties_CustomUniqueWeapon" MayRequire="Ludeon.RimWorld.Odyssey">
<forcedTraits>
<li>ARA_Weapon_Damage_Acid</li>
</forcedTraits>
<numTraitsRange>
<min>1</min>
<max>1</max>
</numTraitsRange>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Basic_Acid_Bladder_Gun</defName>
<label>酸液团</label>
<graphicData>
<graphicClass>Graphic_Single_AgeSecs</graphicClass>
<texPath>Things/Projectile/FleshmassSpitterProjectileSheet</texPath>
<drawSize>(.5, .5)</drawSize>
<shaderType>MoteGlow</shaderType>
</graphicData>
<uiIconScale>0.8</uiIconScale>
<thingClass>Projectile_Explosive</thingClass>
<projectile>
<useGraphicClass>True</useGraphicClass>
<shadowSize>1</shadowSize>
<damageDef>ARA_AcidBurn</damageDef>
<spinRate>20</spinRate>
<damageAmountBase>20</damageAmountBase>
<speed>15</speed>
<arcHeightFactor>1</arcHeightFactor>
<explosionRadius>1.75</explosionRadius>
<flyOverhead>true</flyOverhead>
<soundExplode>SpitterSpitLands</soundExplode>
<filth>Filth_SpentAcid</filth>
<filthCount>1</filthCount>
<explosionEffect>Shell_AcidSpitImpact</explosionEffect>
<explosionEffectLifetimeTicks>60</explosionEffectLifetimeTicks>
<doExplosionVFX>false</doExplosionVFX>
</projectile>
<comps>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitStream</effecterDef>
</li>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitLaunched</effecterDef>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Acid_Mortar</defName>
<label>武装器官"腐蚀臼炮"</label>
<description>阿拉克涅虫群督虫使用大型远程武装器官,膛内布满了强健的肌肉组织,可以在一瞬间的收缩后将一团酸液发射到空中,以在安全距离下对敌人的集群进行轰炸。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Acid_Bladder_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.2</drawSize>
</graphicData>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite>ARA_Technology_7VXI</researchPrerequisite>
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>3.5</Mass>
<AccuracyTouch>0.3</AccuracyTouch>
<AccuracyShort>0.3</AccuracyShort>
<AccuracyMedium>0.25</AccuracyMedium>
<AccuracyLong>0.1</AccuracyLong>
<RangedWeapon_Cooldown>3.5</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>1.5</warmupTime>
<forcedMissRadius>3</forcedMissRadius>
<defaultProjectile>Bullet_ARA_RW_Acid_Mortar</defaultProjectile>
<isMortar>true</isMortar>
<requireLineOfSight>false</requireLineOfSight>
<minRange>5</minRange>
<range>120</range>
<burstShotCount>1</burstShotCount>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T2</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<comps>
<li Class="WulaFallenEmpire.CompProperties_CustomUniqueWeapon" MayRequire="Ludeon.RimWorld.Odyssey">
<forcedTraits>
<li>ARA_Huge_Weapon</li>
<li>ARA_Weapon_Damage_Acid</li>
</forcedTraits>
<numTraitsRange>
<min>2</min>
<max>2</max>
</numTraitsRange>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Acid_Mortar</defName>
<label>大型酸液团</label>
<graphicData>
<graphicClass>Graphic_Single_AgeSecs</graphicClass>
<texPath>Things/Projectile/FleshmassSpitterProjectileSheet</texPath>
<drawSize>(.75, .75)</drawSize>
<shaderType>MoteGlow</shaderType>
</graphicData>
<uiIconScale>0.8</uiIconScale>
<thingClass>Projectile_Explosive</thingClass>
<projectile>
<useGraphicClass>True</useGraphicClass>
<shadowSize>1</shadowSize>
<damageDef>ARA_AcidBurn</damageDef>
<spinRate>15</spinRate>
<damageAmountBase>50</damageAmountBase>
<speed>45</speed>
<arcHeightFactor>1</arcHeightFactor>
<explosionRadius>3.5</explosionRadius>
<flyOverhead>true</flyOverhead>
<soundExplode>SpitterSpitLands</soundExplode>
<filth>Filth_SpentAcid</filth>
<filthCount>4</filthCount>
<explosionEffect>Shell_AcidSpitImpact</explosionEffect>
<explosionEffectLifetimeTicks>60</explosionEffectLifetimeTicks>
<doExplosionVFX>false</doExplosionVFX>
</projectile>
<comps>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitStream</effecterDef>
</li>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitLaunched</effecterDef>
</li>
</comps>
</ThingDef>
<!-- spawn -->
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Basic_SkyHive_Gun</defName>
<label>武装器官"天巢种之巢"</label>
<description>阿拉科涅虫群的生物武器</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Acid_Bladder_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.2</drawSize>
</graphicData>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite>ARA_Technology_6SPV</researchPrerequisite>
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>3.5</Mass>
<AccuracyTouch>0.5</AccuracyTouch>
<AccuracyShort>0.6</AccuracyShort>
<AccuracyMedium>0.45</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>2.5</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>ArachnaeSwarm.Verb_ShootShotgun</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>1.0</warmupTime>
<defaultProjectile>Bullet_ARA_RW_Basic_SkyHive_Gun</defaultProjectile>
<isMortar>true</isMortar>
<requireLineOfSight>false</requireLineOfSight>
<minRange>3</minRange>
<range>28</range>
<burstShotCount>1</burstShotCount>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<comps>
<li Class="WulaFallenEmpire.CompProperties_CustomUniqueWeapon" MayRequire="Ludeon.RimWorld.Odyssey">
<forcedTraits>
<li>ARA_Weapon_Damage_Spawn</li>
</forcedTraits>
<numTraitsRange>
<min>1</min>
<max>1</max>
</numTraitsRange>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Basic_SkyHive_Gun</defName>
<label>阿拉克涅天巢种</label>
<graphicData>
<graphicClass>Graphic_Single_AgeSecs</graphicClass>
<texPath>Things/Pawn/Insect/Locust/Locust_north</texPath>
<color>(156,148,125)</color>
<drawSize>(1,1)</drawSize>
<shaderType>TransparentPostLight</shaderType>
</graphicData>
<uiIconScale>0.8</uiIconScale>
<thingClass>ArachnaeSwarm.Projectile_TrackingBullet</thingClass>
<projectile>
<useGraphicClass>True</useGraphicClass>
<shadowSize>1</shadowSize>
<damageDef>ARA_SkyhiveBite</damageDef>
<damageAmountBase>10</damageAmountBase>
<speed>25</speed>
<arcHeightFactor>1</arcHeightFactor>
<flyOverhead>true</flyOverhead>
</projectile>
<modExtensions>
<li Class="ArachnaeSwarm.TrackingBulletDef">
<!-- 追踪速度,数值越高,转向越快,追踪能力越强 -->
<homingSpeed>0.75</homingSpeed>
<!-- 初始发射时的随机散射角度(左右各多少度) -->
<initRotateAngle>35</initRotateAngle>
<!-- 失去目标后多少 Tick 后自毁,可以是一个范围,如 "120~180" -->
<destroyTicksAfterLosingTrack>150</destroyTicksAfterLosingTrack>
<!-- 子弹离目标多近时就直接判定为命中 -->
<impactThreshold>2.1</impactThreshold>
</li>
<li Class="ArachnaeSwarm.ShotgunExtension">
<pelletCount>3</pelletCount>
</li>
</modExtensions>
<comps>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitStream</effecterDef>
</li>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitLaunched</effecterDef>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseMeleeWeapon_Sharp_Quality">
<defName>ARA_MW_Mimic_Niddle</defName>
<label>武装器官"拟线种毒针"</label>
<description>阿拉克涅虫群督虫使用基础近战武装器官,通过多根外露神经束与督虫的辅肢相连。这根毒针中藏有休眠中的阿拉克涅拟线种虫卵,攻击将感染受害者使其最终成为被拟线虫操控的寄生体。</description>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Melee</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_MW_Bone_Sword</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>1</drawSize>
</graphicData>
<uiIconScale>1</uiIconScale>
<!-- <equippedAngleOffset>-65</equippedAngleOffset> -->
<techLevel>Animal</techLevel>
<!-- <equippedAngleOffset>-25</equippedAngleOffset> -->
<costStuffCount>0</costStuffCount>
<stuffCategories Inherit="False"/>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<statBases>
<WorkToMake>1000</WorkToMake>
<Mass>5</Mass>
</statBases>
<tools Inherit="False">
<li>
<label></label>
<capacities>
<li>Cut</li>
</capacities>
<power>15</power>
<cooldownTime>1.3</cooldownTime>
<armorPenetration>0.50</armorPenetration>
</li>
<li>
<label></label>
<capacities>
<li>Poke</li>
</capacities>
<power>12</power>
<armorPenetration>0.20</armorPenetration>
<cooldownTime>1.5</cooldownTime>
<extraMeleeDamages>
<li>
<def>ARA_MimicNematodeBite</def>
<amount>4</amount>
</li>
</extraMeleeDamages>
</li>
</tools>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite Inherit="False" />
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
</ThingDef>
</Defs>

View File

@@ -1,624 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="BaseMeleeWeapon_Sharp_Quality">
<defName>ARA_MW_Bone_Sword</defName>
<label>武装器官"骨刃"</label>
<description>阿拉克涅虫群督虫使用基础近战武装器官,通过多根外露神经束与督虫的辅肢相连。尽管它只是一块坚硬的剑形骨片,但是丝毫不影响那些拥有无穷蛮力的阿拉克涅虫群督虫使用它将侵犯虫巢之敌一一斩首。</description>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Melee</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_MW_Bone_Sword</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>1</drawSize>
</graphicData>
<uiIconScale>1</uiIconScale>
<!-- <equippedAngleOffset>-65</equippedAngleOffset> -->
<techLevel>Animal</techLevel>
<!-- <equippedAngleOffset>-25</equippedAngleOffset> -->
<costStuffCount>0</costStuffCount>
<stuffCategories Inherit="False"/>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<statBases>
<WorkToMake>1000</WorkToMake>
<Mass>5</Mass>
</statBases>
<tools Inherit="False">
<li>
<label>横扫</label>
<capacities>
<li>Cut</li>
</capacities>
<power>15</power>
<cooldownTime>1.3</cooldownTime>
<armorPenetration>0.50</armorPenetration>
</li>
<li>
<label>下砸</label>
<capacities>
<li>Poke</li>
</capacities>
<power>12</power>
<armorPenetration>0.20</armorPenetration>
<cooldownTime>1.5</cooldownTime>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>15</amount>
</li>
</extraMeleeDamages>
</li>
</tools>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite Inherit="False" />
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
</ThingDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_BioforgeIncubator_BoneBase</defName>
<label>投放孵化茧 骨刃器官</label>
<description>投放一枚武装器官茧,内含可以孵化一套基础骨刃武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_BioforgeIncubator_BoneBase_Proj</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_5DIL</requiredResearch>
<failMessage>需要科技 基因节点DIL-5"骨刀" 以解锁此孵化路径</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_BioforgeIncubator_BoneBase_Proj</defName>
<projectile>
<spawnsThingDef>ARA_BioforgeIncubator_BoneBase</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_BioforgeIncubator_Base">
<defName>ARA_BioforgeIncubator_BoneBase</defName>
<label>阿拉克涅孵化茧 基础骨片装备</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一个骨片武装器官的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为-20~35°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_MW_Bone_Sword</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_5DIL</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_MW_Bone_Sword</thingDef>
<productionTicks>60000</productionTicks>
<totalNutritionNeeded>15</totalNutritionNeeded>
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>-20</minSafeTemperature>
<maxSafeTemperature>35</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-20</minSafeTemperature>
<maxSafeTemperature>35</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Basic_Fist_Needle_Gun</defName>
<label>武装器官"拳针枪"</label>
<description>阿拉克涅虫群督虫使用基础远程武装器官,外表就像一只拳套,可以通过神经束缠绕接在阿拉克涅督虫的辅肢上。这种武器小巧轻盈,虽然射程很短,但是面对敌人时能喷出一整排的带毒尖刺,把对手扎个透心凉。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Fist_Needle_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>0.75</drawSize>
</graphicData>
<uiIconScale>1.3</uiIconScale>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite Inherit="False" />
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>0.5</Mass>
<AccuracyTouch>0.85</AccuracyTouch>
<AccuracyShort>0.6</AccuracyShort>
<AccuracyMedium>0.45</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>1.25</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>0.25</warmupTime>
<defaultProjectile>Bullet_ARA_RW_Basic_Fist_Needle_Gun</defaultProjectile>
<range>14</range>
<burstShotCount>6</burstShotCount>
<ticksBetweenBurstShots>1</ticksBetweenBurstShots>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>25</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
<tools Inherit="False">
<li>
<label>拳针枪拳击</label>
<capacities>
<li>Poke</li>
</capacities>
<power>10</power>
<armorPenetration>0.25</armorPenetration>
<cooldownTime>1.25</cooldownTime>
<extraMeleeDamages>
<li>
<def>Stun</def>
<amount>12</amount>
</li>
</extraMeleeDamages>
</li>
</tools>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Basic_Fist_Needle_Gun</defName>
<label>毒针</label>
<graphicData>
<texPath>Things/Projectile/Bullet_Small</texPath>
<graphicClass>Graphic_Single</graphicClass>
<color>(117, 204, 49, 180)</color>
</graphicData>
<projectile>
<damageDef>ARA_Fist_Needle</damageDef>
<damageAmountBase>2</damageAmountBase>
<speed>40</speed>
</projectile>
</ThingDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_BioforgeIncubator_ToxicNeedleBase</defName>
<label>投放孵化茧 毒针器官</label>
<description>投放一枚武装器官茧,内含可以孵化一套基础毒针武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_BioforgeIncubator_ToxicNeedleBase_Proj</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_5PAV</requiredResearch>
<failMessage>需要科技 基因节点PAV-5"毒刺" 以解锁此孵化路径</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_BioforgeIncubator_ToxicNeedleBase_Proj</defName>
<projectile>
<spawnsThingDef>ARA_BioforgeIncubator_ToxicNeedleBase</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_BioforgeIncubator_Base">
<defName>ARA_BioforgeIncubator_ToxicNeedleBase</defName>
<label>阿拉克涅孵化茧 基础毒针武器</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一个毒针武装器官的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为0~22°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_RW_Basic_Fist_Needle_Gun</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_5PAV</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_RW_Basic_Fist_Needle_Gun</thingDef>
<productionTicks>40000</productionTicks>
<totalNutritionNeeded>10</totalNutritionNeeded>
<!--<requiredResearch>ARA_Technology_5PAV</requiredResearch>-->
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>0</minSafeTemperature>
<maxSafeTemperature>22</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>0</minSafeTemperature>
<maxSafeTemperature>22</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>ARA_RW_Basic_Acid_Bladder_Gun</defName>
<label>武装器官"酸液枪"</label>
<description>阿拉克涅虫群督虫使用基础远程武装器官,可以通过肌肉的瞬间加压喷出一团包含阿拉克涅酸液的液体团。这种酸液团的飞行速度很慢,但是能在目标地点炸开,并灼烧所有粘上酸液的敌人。</description>
<tickerType>Normal</tickerType>
<techLevel>Animal</techLevel>
<graphicData>
<texPath>ArachnaeSwarm/Weapon/ARA_RW_Basic_Acid_Bladder_Gun</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.2</drawSize>
</graphicData>
<soundInteract>SpitterSpawn</soundInteract>
<recipeMaker>
<recipeUsers Inherit="False" />
<researchPrerequisite Inherit="False" />
<unfinishedThingDef>UnfinishedWeapon</unfinishedThingDef>
</recipeMaker>
<statBases>
<WorkToMake>1300</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>3.5</Mass>
<AccuracyTouch>0.5</AccuracyTouch>
<AccuracyShort>0.6</AccuracyShort>
<AccuracyMedium>0.45</AccuracyMedium>
<AccuracyLong>0.3</AccuracyLong>
<RangedWeapon_Cooldown>2.5</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>1.0</warmupTime>
<forcedMissRadius>1</forcedMissRadius>
<defaultProjectile>Bullet_ARA_RW_Basic_Acid_Bladder_Gun</defaultProjectile>
<isMortar>true</isMortar>
<requireLineOfSight>false</requireLineOfSight>
<minRange>3</minRange>
<range>28</range>
<burstShotCount>1</burstShotCount>
<soundCast>SpitterSpit</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<ARA_Carapace>50</ARA_Carapace>
</costList>
<weaponTags>
<li>ARA_Armed_Organ</li>
<li>ARA_Armed_Organ_Ranged</li>
<li>ARA_Armed_Organ_T1</li>
</weaponTags>
<thingSetMakerTags>
<li>RewardStandardQualitySuper</li>
</thingSetMakerTags>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_ARA_RW_Basic_Acid_Bladder_Gun</defName>
<label>酸液团</label>
<graphicData>
<graphicClass>Graphic_Single_AgeSecs</graphicClass>
<texPath>Things/Projectile/FleshmassSpitterProjectileSheet</texPath>
<drawSize>(.5, .5)</drawSize>
<shaderType>MoteGlow</shaderType>
</graphicData>
<uiIconScale>0.8</uiIconScale>
<thingClass>Projectile_Explosive</thingClass>
<projectile>
<useGraphicClass>True</useGraphicClass>
<shadowSize>1</shadowSize>
<damageDef>ARA_AcidBurn</damageDef>
<spinRate>20</spinRate>
<damageAmountBase>20</damageAmountBase>
<speed>15</speed>
<arcHeightFactor>1</arcHeightFactor>
<explosionRadius>1.75</explosionRadius>
<flyOverhead>true</flyOverhead>
<soundExplode>SpitterSpitLands</soundExplode>
<filth>Filth_SpentAcid</filth>
<filthCount>1</filthCount>
<explosionEffect>Shell_AcidSpitImpact</explosionEffect>
<explosionEffectLifetimeTicks>60</explosionEffectLifetimeTicks>
<doExplosionVFX>false</doExplosionVFX>
</projectile>
<comps>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitStream</effecterDef>
</li>
<li Class="CompProperties_ProjectileEffecter">
<effecterDef>Shell_AcidSpitLaunched</effecterDef>
</li>
</comps>
</ThingDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_BioforgeIncubator_AcidBase</defName>
<label>投放孵化茧 酸液器官</label>
<description>投放一枚武装器官茧,内含可以孵化一套基础酸液武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_7VXI</requiredResearch>
<failMessage>需要科技 基因节点VXI-7"外置酸袋" 以解锁此孵化路径</failMessage>
</li>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_BioforgeIncubator_AcidBase_Proj</projectileDef>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_BioforgeIncubator_AcidBase_Proj</defName>
<projectile>
<spawnsThingDef>ARA_BioforgeIncubator_AcidBase</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_BioforgeIncubator_Base">
<defName>ARA_BioforgeIncubator_AcidBase</defName>
<label>阿拉克涅孵化茧 基础酸性武器</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一个酸性武装器官的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为10~28°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_RW_Basic_Acid_Bladder_Gun</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_7VXI</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_RW_Basic_Acid_Bladder_Gun</thingDef>
<productionTicks>80000</productionTicks>
<totalNutritionNeeded>30</totalNutritionNeeded>
<!--<requiredResearch>ARA_Technology_7VXI</requiredResearch>-->
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>10</minSafeTemperature>
<maxSafeTemperature>28</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
<!--
当一个生产流程完成时,系统会通过以下三个步骤来确定最终的物品品质:
第 1 步: 计算“基础品质分” (Base Quality Score)
基础品质分代表了在整个生产过程中,理想条件所占的比例。理想条件被严格定义为:燃料充足 且 温度适宜。
公式:
基础品质分 = 在理想条件下度过的时间(ticks) / 生产总需时间(ticks)
C# 代码对应:
baseQuality = (_selectedProcess.productionTicks > 0) ? (float)ticksUnderOptimalConditions / _selectedProcess.productionTicks : 0f;
说明:
ticksUnderOptimalConditions 是一个计数器只有在同时满足燃料充足和温度安全这两个条件的游戏刻Tick它才会加 1。
_selectedProcess.productionTicks 是在 XML 中为该产品定义的总生产时间。
这个得分的范围是 0.0 (0%) 到 1.0 (100%)。如果整个过程都完美无缺,这个分数就是 1.0。
第 2 步: 计算“温度惩罚分” (Temperature Penalty Score)
温度惩罚分是一个独立累加的负面分数。它只在环境温度超出安全范围时才会累积。
公式:
每刻惩罚增加量 = 超出安全范围的度数 × penaltyPerDegreePerTick
温度惩罚分 = 所有惩罚增加量的总和
C# 代码对应:
temperaturePenaltyPercent = Mathf.Min(1f, temperaturePenaltyPercent + tempDelta * Props.penaltyPerDegreePerTick);
说明:
penaltyPerDegreePerTick 是一个可在 XML 中配置的系数代表每超出1度、每刻所产生的惩罚量。
这个惩罚是不可逆的。即使温度恢复正常,已经累积的惩罚也不会减少。
它的最大值被限制在 1.0 (100%),以防止无限累加。
第 3 步: 计算“最终品质分”并映射到品质等级
最终品质分由基础分减去惩罚分得出,这个分数将直接决定物品的品质等级。
公式:
最终品质分 = 基础品质分 - 温度惩罚分
C# 代码对应:
finalQualityScore = Mathf.Clamp01(baseQuality - temperaturePenaltyPercent);
映射到品质等级:
得到 finalQualityScore (一个 0.0 到 1.0 之间的值) 后,系统会通过一系列 if-else if 判断,将其映射到游戏中的 QualityCategory (品质等级)。例如,在我们的代码中:
>= 0.99 -> 传说 (Legendary)
>= 0.90 -> 杰作 (Masterwork)
>= 0.70 -> 优秀 (Excellent)
>= 0.50 -> 良好 (Good)
>= 0.20 -> 普通 (Normal)
>= 0.10 -> 差 (Poor)
< 0.10 -> 劣质 (Awful)
总结
这个系统的核心在于,它鼓励玩家全程维持最佳生产环境。
仅仅保持燃料充足或温度适宜是不够的,必须两者兼顾才能提高“基础品质分”。
同时,必须极力避免温度超出安全范围,因为“温度惩罚分”是纯粹的惩罚,它只会单方面地拉低最终品质,且无法挽回。
这种设计为玩家提供了一个清晰的目标和富有挑战性的过程管理,而不是一个简单的“放置-等待”式生产。
-->
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>10</minSafeTemperature>
<maxSafeTemperature>28</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -1,243 +1,239 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!-- 1. 加成建筑 "孵化加速器" -->
<ThingDef ParentName="BuildingBase">
<defName>ARA_IncubationAccelerator</defName>
<label>孵化加速器</label>
<description>一个辅助性的生物机械装置,当放置在大型孵化池旁边时,可以加速其内部的孵化过程。</description>
<graphicData>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
</graphicData>
<size>(1,1)</size>
<comps>
<!-- 使用原版的 CompFacility -->
<li Class="CompProperties_Facility">
<statOffsets>
<!-- 提供我们自定义的孵化速度加成 -->
<ARA_IncubationSpeedFactor>0.60</ARA_IncubationSpeedFactor>
</statOffsets>
</li>
</comps>
</ThingDef>
<!-- 1. 加成建筑 "孵化加速器" -->
<ThingDef ParentName="BuildingBase">
<defName>ARA_IncubationAccelerator</defName>
<label>孵化加速器</label>
<description>一个辅助性的生物机械装置,当放置在大型孵化池旁边时,可以加速其内部的孵化过程。</description>
<graphicData>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
</graphicData>
<size>(1,1)</size>
<comps>
<!-- 使用原版的 CompFacility -->
<li Class="CompProperties_Facility">
<statOffsets>
<!-- 提供我们自定义的孵化速度加成 -->
<ARA_IncubationSpeedFactor>0.60</ARA_IncubationSpeedFactor>
</statOffsets>
</li>
</comps>
</ThingDef>
<!-- 3. 主建筑 "生物孵化池" -->
<ThingDef ParentName="BuildingBase">
<defName>ARA_BioforgeIncubator_Thing</defName>
<label>生物质物品孵化池</label>
<description>一个大型的、需要消耗大量营养物质的孵化设施,可以同时孵化多个单位,并能通过链接外部设备来提高效率。</description>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_BioforgeIncubator</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(5,6)</drawSize>
</graphicData>
<size>(5,5)</size>
<tickerType>Normal</tickerType>
<stuffCategories Inherit="False" />
<costStuffCount>0</costStuffCount>
<costList>
<ARA_Carapace>50</ARA_Carapace>
</costList>
<castEdgeShadows>false</castEdgeShadows>
<staticSunShadowHeight>0</staticSunShadowHeight>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<pathCost>50</pathCost>
<statBases>
<MaxHitPoints>250</MaxHitPoints>
<WorkToBuild>2800</WorkToBuild>
<Flammability>1.0</Flammability>
</statBases>
<placeWorkers>
<li>PlaceWorker_PreventInteractionSpotOverlap</li>
</placeWorkers>
<fillPercent>0.8</fillPercent>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<hasInteractionCell>true</hasInteractionCell>
<designationCategory>ARA_Buildings</designationCategory>
<uiOrder>2600</uiOrder>
<surfaceType>Item</surfaceType>
<building>
<workTableRoomRole>Laboratory</workTableRoomRole>
<workTableNotInRoomRoleFactor>0.8</workTableNotInRoomRoleFactor>
</building>
<comps>
<!-- a. 我们新的队列物品生产组件 -->
<li Class="ArachnaeSwarm.CompProperties_QueuedInteractiveProducer">
<!-- 队列和交互设置 -->
<productionQueueLimit>3</productionQueueLimit>
<minNutritionToStart>1.0</minNutritionToStart>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li> <!-- 示例:允许普通殖民者操作 -->
</whitelist>
<!-- 3. 主建筑 "生物孵化池" -->
<ThingDef ParentName="BuildingBase">
<defName>ARA_BioforgeIncubator_Thing</defName>
<label>生物质物品孵化池</label>
<description>一个大型的、需要消耗大量营养物质的孵化设施,可以同时孵化多个单位,并能通过链接外部设备来提高效率。</description>
<graphicData>
<texPath>Things/Building/AncientHeatVent</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(7,7)</drawSize>
</graphicData>
<size>(7,7)</size>
<tickerType>Normal</tickerType>
<stuffCategories Inherit="False"/>
<costStuffCount>0</costStuffCount>
<costList>
<ARA_Carapace>50</ARA_Carapace>
</costList>
<castEdgeShadows>false</castEdgeShadows>
<staticSunShadowHeight>0</staticSunShadowHeight>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<pathCost>50</pathCost>
<statBases>
<MaxHitPoints>250</MaxHitPoints>
<WorkToBuild>2800</WorkToBuild>
<Flammability>1.0</Flammability>
</statBases>
<placeWorkers>
<li>PlaceWorker_PreventInteractionSpotOverlap</li>
</placeWorkers>
<fillPercent>0.8</fillPercent>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<hasInteractionCell>true</hasInteractionCell>
<designationCategory>ARA_Buildings</designationCategory>
<uiOrder>2600</uiOrder>
<surfaceType>Item</surfaceType>
<building>
<workTableRoomRole>Laboratory</workTableRoomRole>
<workTableNotInRoomRoleFactor>0.8</workTableNotInRoomRoleFactor>
</building>
<comps>
<!-- 质量系统设置 -->
<minSafeTemperature>10</minSafeTemperature>
<maxSafeTemperature>30</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
<!-- a. 我们新的队列物品生产组件 -->
<li Class="ArachnaeSwarm.CompProperties_QueuedInteractiveProducer">
<!-- 队列和交互设置 -->
<productionQueueLimit>3</productionQueueLimit>
<minNutritionToStart>1.0</minNutritionToStart>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li> <!-- 示例:允许普通殖民者操作 -->
</whitelist>
<!-- 生产列表 -->
<processes>
<li>
<thingDef>ARA_RW_Basic_Acid_Bladder_Gun</thingDef>
<productionTicks>80000</productionTicks>
<totalNutritionNeeded>30</totalNutritionNeeded>
<requiredResearch>ARA_Technology_7VXI</requiredResearch>
</li>
<li>
<thingDef>ARA_RW_Basic_Fist_Needle_Gun</thingDef>
<productionTicks>40000</productionTicks>
<totalNutritionNeeded>10</totalNutritionNeeded>
<requiredResearch>ARA_Technology_5PAV</requiredResearch>
</li>
</processes>
</li>
<!-- 质量系统设置 -->
<minSafeTemperature>10</minSafeTemperature>
<maxSafeTemperature>30</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
<!-- b. 我们的营养燃料组件 -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>100.0</fuelCapacity>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelGizmoLabel>生物质</fuelGizmoLabel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
</li>
<!-- 生产列表 -->
<processes>
<li>
<thingDef>ARA_RW_Basic_Acid_Bladder_Gun</thingDef>
<productionTicks>80000</productionTicks>
<totalNutritionNeeded>30</totalNutritionNeeded>
<requiredResearch>ARA_Technology_7VXI</requiredResearch>
</li>
<li>
<thingDef>ARA_RW_Basic_Fist_Needle_Gun</thingDef>
<productionTicks>40000</productionTicks>
<totalNutritionNeeded>10</totalNutritionNeeded>
<requiredResearch>ARA_Technology_5PAV</requiredResearch>
</li>
</processes>
</li>
<!-- c. 原版的设施链接接收组件 -->
<li Class="CompProperties_AffectedByFacilities">
<linkableFacilities>
<li>ARA_IncubationAccelerator</li>
</linkableFacilities>
</li>
</comps>
</ThingDef>
<!-- b. 我们的营养燃料组件 -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>100.0</fuelCapacity>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelGizmoLabel>生物质</fuelGizmoLabel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
</li>
<ThingDef ParentName="BuildingBase">
<defName>ARA_BioforgeIncubator</defName>
<label>生物质孵化池</label>
<description>一个大型的、需要消耗大量营养物质的孵化设施,可以同时孵化多个单位,并能通过链接外部设备来提高效率。</description>
<graphicData>
<texPath>Things/Building/AncientHeatVent</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(7,7)</drawSize>
</graphicData>
<size>(7,7)</size>
<tickerType>Normal</tickerType>
<stuffCategories Inherit="False" />
<costStuffCount>0</costStuffCount>
<costList>
<ARA_Carapace>50</ARA_Carapace>
</costList>
<castEdgeShadows>false</castEdgeShadows>
<staticSunShadowHeight>0</staticSunShadowHeight>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<pathCost>50</pathCost>
<statBases>
<MaxHitPoints>250</MaxHitPoints>
<WorkToBuild>2800</WorkToBuild>
<Flammability>1.0</Flammability>
</statBases>
<placeWorkers>
<li>PlaceWorker_PreventInteractionSpotOverlap</li>
</placeWorkers>
<fillPercent>0.8</fillPercent>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<hasInteractionCell>true</hasInteractionCell>
<designationCategory>ARA_Buildings</designationCategory>
<uiOrder>2600</uiOrder>
<surfaceType>Item</surfaceType>
<building>
<workTableRoomRole>Laboratory</workTableRoomRole>
<workTableNotInRoomRoleFactor>0.8</workTableNotInRoomRoleFactor>
</building>
<comps>
<!-- c. 原版的设施链接接收组件 -->
<li Class="CompProperties_AffectedByFacilities">
<linkableFacilities>
<li>ARA_IncubationAccelerator</li>
</linkableFacilities>
</li>
<!-- a. 我们自己的队列生产组件 -->
<li Class="ArachnaeSwarm.CompProperties_QueuedPawnSpawner">
<productionQueueLimit>5</productionQueueLimit>
<minNutritionToStart>0.5</minNutritionToStart>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
</li>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
</li>
<li>
<pawnKind>ArachnaeNode_Race_WeaponSmith</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
<!--<requiredResearch>ARA_AdvancedBiology</requiredResearch>-->
</li>
</spawnablePawns>
</li>
</comps>
</ThingDef>
<!-- b. 我们的营养燃料组件 -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>100.0</fuelCapacity>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelGizmoLabel>生物质</fuelGizmoLabel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
</li>
<ThingDef ParentName="BuildingBase">
<defName>ARA_BioforgeIncubator</defName>
<label>生物质孵化池</label>
<description>一个大型的、需要消耗大量营养物质的孵化设施,可以同时孵化多个单位,并能通过链接外部设备来提高效率。</description>
<graphicData>
<texPath>Things/Building/AncientHeatVent</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(7,7)</drawSize>
</graphicData>
<size>(7,7)</size>
<tickerType>Normal</tickerType>
<stuffCategories Inherit="False"/>
<costStuffCount>0</costStuffCount>
<costList>
<ARA_Carapace>50</ARA_Carapace>
</costList>
<castEdgeShadows>false</castEdgeShadows>
<staticSunShadowHeight>0</staticSunShadowHeight>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<terrainAffordanceNeeded>ARA_Creep</terrainAffordanceNeeded>
<pathCost>50</pathCost>
<statBases>
<MaxHitPoints>250</MaxHitPoints>
<WorkToBuild>2800</WorkToBuild>
<Flammability>1.0</Flammability>
</statBases>
<placeWorkers>
<li>PlaceWorker_PreventInteractionSpotOverlap</li>
</placeWorkers>
<fillPercent>0.8</fillPercent>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<hasInteractionCell>true</hasInteractionCell>
<designationCategory>ARA_Buildings</designationCategory>
<uiOrder>2600</uiOrder>
<surfaceType>Item</surfaceType>
<building>
<workTableRoomRole>Laboratory</workTableRoomRole>
<workTableNotInRoomRoleFactor>0.8</workTableNotInRoomRoleFactor>
</building>
<comps>
<!-- a. 我们自己的队列生产组件 -->
<li Class="ArachnaeSwarm.CompProperties_QueuedPawnSpawner">
<productionQueueLimit>5</productionQueueLimit>
<minNutritionToStart>0.5</minNutritionToStart>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
</li>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
</li>
<li>
<pawnKind>ArachnaeNode_Race_WeaponSmith</pawnKind>
<delayTicks>180000</delayTicks>
<totalNutritionNeeded>5.0</totalNutritionNeeded>
<!--<requiredResearch>ARA_AdvancedBiology</requiredResearch>-->
</li>
</spawnablePawns>
</li>
<!-- b. 我们的营养燃料组件 -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>100.0</fuelCapacity>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelGizmoLabel>生物质</fuelGizmoLabel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
</li>
<!-- c. 原版的设施链接接收组件 -->
<li Class="CompProperties_AffectedByFacilities">
<linkableFacilities>
<li>ARA_IncubationAccelerator</li>
</linkableFacilities>
</li>
</comps>
</ThingDef>
<!-- c. 原版的设施链接接收组件 -->
<li Class="CompProperties_AffectedByFacilities">
<linkableFacilities>
<li>ARA_IncubationAccelerator</li>
</linkableFacilities>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<TerrainDef ParentName="FloorBase">
<TerrainDef ParentName="NaturalTerrainBase">
<defName>ARA_InsectCreep</defName>
<label>阿拉克涅菌毯</label>
<description>由阿拉克涅虫族所铺设的由真菌、甲壳素分泌物混合得到的地面,会自动在各种拉克涅虫族建筑附近蔓延。这种奇特的结构质地紧密且暗藏大量营养输送组织,可以支撑重型建筑、种植作物、加速其上的阿拉克涅虫族移动速度,但是除了虫族以外没人想踩在这坨软乎乎的活体结构上。</description>
<designationCategory>ARA_Buildings</designationCategory>
<texturePath>Terrain/Surfaces/InsectSludge</texturePath>
<color>(203, 163, 68)</color>
<color>(239, 139, 48)</color>
<pollutionShaderType MayRequire="Ludeon.RimWorld.Biotech">TerrainFadeRoughLinearBurn</pollutionShaderType>
<pollutionOverlayTexturePath>Terrain/Surfaces/PollutionMud</pollutionOverlayTexturePath>
<pollutionColor>(1, 1, 1, 1)</pollutionColor>
<edgeType>FadeRough</edgeType>
<resourcesFractionWhenDeconstructed>0</resourcesFractionWhenDeconstructed>
<renderPrecedence>330</renderPrecedence>
<pathCost>2</pathCost>
<pathCost>10</pathCost>
<generatedFilth>Filth_Slime</generatedFilth>
<researchPrerequisites>
<li>ARA_Base_Technology</li>
@@ -28,7 +28,7 @@
<Beauty>-6</Beauty>
<CleaningTimeFactor>0.25</CleaningTimeFactor>
<Cleanliness>0</Cleanliness>
<Flammability>0.2</Flammability>
<Flammability>0</Flammability>
</statBases>
<fertility>1.25</fertility>
<affordances Inherit="False">
@@ -73,7 +73,7 @@
<building>
<isAirtight>true</isAirtight>
<!-- <isNaturalRock>true</isNaturalRock> -->
<smoothedThing>SmoothedGranite</smoothedThing>
<!-- <smoothedThing>SmoothedGranite</smoothedThing> -->
<blueprintGraphicData>
<texPath>ArachnaeSwarm/Building/Linked/ARA_InsectWall_Blueprint</texPath>
</blueprintGraphicData>
@@ -327,17 +327,19 @@
<ThingDef ParentName="BenchBase">
<defName>ARA_ResearchBench</defName>
<label>阿拉克涅研究台</label>
<description>一个供阿拉克涅女皇种和智囊种进行研究的活体结构,可以让虫群尽情地探索变异和进化方向。</description>
<description>一个供阿拉克涅虫族进行研究的活体结构,可以让虫群尽情地探索变异和进化方向。</description>
<thingClass>Building_ResearchBench</thingClass>
<size>(3,3)</size>
<stuffCategories Inherit="False"/>
<costStuffCount>0</costStuffCount>
<minifiedDef Inherit="False"/>
<thingCategories Inherit="False"/>
<costList>
<ARA_Carapace>50</ARA_Carapace>
</costList>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_ResearchBench</texPath>
<graphicClass>Graphic_Single</graphicClass>
<graphicClass>Graphic_Multi</graphicClass>
<shaderType>CutoutComplex</shaderType>
<drawSize>(3,4.5)</drawSize>
</graphicData>

View File

@@ -52,7 +52,7 @@
</comps>
</ThingDef>
<!-- T1 -->
<!-- T0 -->
<ThingDef ParentName="ARA_EggSpew_Base_Proj">
<defName>ARA_Proj_EggSac</defName>
<label>阿拉克涅虫卵</label>
@@ -65,7 +65,6 @@
<label>阿拉克涅虫卵囊</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅女皇种所诞之卵,内含哺育一只新督虫所需的营养和遗传物质,可以通过阿拉克涅女皇种的交互完成激活进程——参阅虫卵的超链接,了解各个督虫的特点。\n\n卵囊对温度极度敏感该类型的卵适温为-25~30°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ArachnaeNode_Race_Myrmecocystus</ThingDef>
<ThingDef>ArachnaeNode_Race_ShieldHead</ThingDef>
<ThingDef>ArachnaeNode_Race_WeaponSmith</ThingDef>
<ThingDef>ArachnaeNode_Race_Fighter</ThingDef>
@@ -77,10 +76,6 @@
<comps>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delayTicks>10000</delayTicks>
</li>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>
<delayTicks>120000</delayTicks>
@@ -151,4 +146,148 @@
</li>
</comps>
</ThingDef>
<ThingDef ParentName="ARA_EggSpew_Base_Proj">
<defName>ARA_Proj_EggSac_Huge</defName>
<label>大型阿拉克涅虫卵</label>
<projectile>
<spawnsThingDef>ARA_InteractiveEggSac_Huge</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_InteractiveEggSac_Base">
<defName>ARA_InteractiveEggSac_Huge</defName>
<label>大型阿拉克涅虫卵囊</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅女皇种所诞之卵,内含哺育一只大型督虫所需的营养和遗传物质,可以通过阿拉克涅女皇种的交互完成激活进程——参阅虫卵的超链接,了解各个督虫的特点。\n\n卵囊对温度极度敏感该类型的卵适温为-25~30°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ArachnaeNode_Race_Myrmecocystus</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Base_Technology</li>
</researchPrerequisites>
<comps>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delayTicks>180000</delayTicks>
</li>
</spawnablePawns>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-25</minSafeTemperature>
<maxSafeTemperature>30</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<!-- T1 -->
<ThingDef ParentName="ARA_EggSpew_Base_Proj">
<defName>ARA_Proj_EggSac_1Stage</defName>
<label>阿拉克涅虫卵</label>
<projectile>
<spawnsThingDef>ARA_InteractiveEggSac_1Stage</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_InteractiveEggSac_Base">
<defName>ARA_InteractiveEggSac_1Stage</defName>
<label>阿拉克涅虫卵囊</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅女皇种所诞之卵,内含哺育一只新督虫所需的营养和遗传物质,可以通过阿拉克涅女皇种的交互完成激活进程——参阅虫卵的超链接,了解各个督虫的特点。\n\n卵囊对温度极度敏感该类型的卵适温为-10~22°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ArachnaeNode_Race_ShieldHead</ThingDef>
<ThingDef>ArachnaeNode_Race_WeaponSmith</ThingDef>
<ThingDef>ArachnaeNode_Race_Fighter</ThingDef>
<ThingDef>ArachnaeNode_Race_Skyraider</ThingDef>
<ThingDef>ArachnaeNode_Race_Facehugger</ThingDef>
</descriptionHyperlinks>
<comps>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>
<delayTicks>120000</delayTicks>
</li>
<li>
<pawnKind>ArachnaeNode_Race_WeaponSmith</pawnKind>
<delayTicks>180000</delayTicks>
</li>
<li>
<pawnKind>ArachnaeNode_Race_Fighter</pawnKind>
<delayTicks>120000</delayTicks>
<requiredResearch>ARA_Technology_1KYC</requiredResearch>
</li>
<li>
<pawnKind>ArachnaeNode_Race_Facehugger</pawnKind>
<delayTicks>420000</delayTicks>
<requiredResearch>ARA_Technology_4KYC</requiredResearch>
</li>
<li>
<pawnKind>ArachnaeNode_Race_Skyraider</pawnKind>
<delayTicks>360000</delayTicks>
<requiredResearch>ARA_Technology_2KYC</requiredResearch>
</li>
</spawnablePawns>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-10</minSafeTemperature>
<maxSafeTemperature>22</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="ARA_EggSpew_Base_Proj">
<defName>ARA_Proj_EggSac_Huge_1Stage</defName>
<label>大型阿拉克涅虫卵</label>
<projectile>
<spawnsThingDef>ARA_InteractiveEggSac_Huge_1Stage</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_InteractiveEggSac_Base">
<defName>ARA_InteractiveEggSac_Huge_1Stage</defName>
<label>大型阿拉克涅虫卵囊</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅女皇种所诞之卵,内含哺育一只大型督虫所需的营养和遗传物质,可以通过阿拉克涅女皇种的交互完成激活进程——参阅虫卵的超链接,了解各个督虫的特点。\n\n卵囊对温度极度敏感该类型的卵适温为-10~22°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ArachnaeNode_Race_Myrmecocystus</ThingDef>
<ThingDef>ArachnaeNode_Race_Smokepop</ThingDef>
</descriptionHyperlinks>
<comps>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<spawnablePawns>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delayTicks>180000</delayTicks>
</li>
<li>
<pawnKind>ArachnaeNode_Race_Smokepop</pawnKind>
<delayTicks>360000</delayTicks>
<requiredResearch>ARA_Technology_5KYC</requiredResearch>
</li>
</spawnablePawns>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-10</minSafeTemperature>
<maxSafeTemperature>22</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef Name="ARA_BioforgeIncubator_Base" ParentName="BuildingBase" Abstract="True">
<ThingDef Name="ARA_Cocoon_Base" ParentName="BuildingBase" Abstract="True">
<thingClass>Building</thingClass>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_BioforgeIncubator</texPath>
<texPath>ArachnaeSwarm/Building/ARA_Cocoon</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>(1.1,1.1)</drawSize>
</graphicData>
@@ -38,4 +38,230 @@
</li>
</comps>
</ThingDef>
<!-- T0 -->
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_Cocoon_Cloth</defName>
<label>投放织物孵化茧</label>
<description>投放一枚织物茧,内含可以孵化一套基础织物的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Cocoon_Cloth_Proj</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityResearchPrereq">
<requiredResearch>ARA_Technology_4DIL</requiredResearch>
<failMessage>需要科技 基因节点DIL-4"编织" 以解锁此孵化路径</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_Cocoon_Cloth_Proj</defName>
<projectile>
<spawnsThingDef>ARA_Cocoon_Cloth</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_Cocoon_Base">
<defName>ARA_Cocoon_Cloth</defName>
<label>阿拉克涅孵化茧 基础织物</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一套基础织物装备的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为-30~55°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_Bodystocking_White</ThingDef>
<ThingDef>ARA_Bodystocking_Black</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_4DIL</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_Bodystocking_White</thingDef>
<productionTicks>6000</productionTicks>
<totalNutritionNeeded>1</totalNutritionNeeded>
</li>
<li>
<thingDef>ARA_Bodystocking_Black</thingDef>
<productionTicks>6000</productionTicks>
<totalNutritionNeeded>1</totalNutritionNeeded>
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>-30</minSafeTemperature>
<maxSafeTemperature>55</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-30</minSafeTemperature>
<maxSafeTemperature>55</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
<AbilityDef ParentName="ARA_CocoonSpew_Base">
<defName>ARA_Cocoon_Wepaon</defName>
<label>投放武装器官孵化茧</label>
<description>投放一枚武装器官茧,内含可以孵化一套基础武装器官的营养和遗传物质——参阅茧的超链接,了解其能生产的所有装备的特点。</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Cocoon_Wepaon_Proj</projectileDef>
</li>
</comps>
</AbilityDef>
<ThingDef ParentName="ARA_CocoonSpew_Base_Proj">
<defName>ARA_Cocoon_Wepaon_Proj</defName>
<projectile>
<spawnsThingDef>ARA_Cocoon_Wepaon</spawnsThingDef>
</projectile>
</ThingDef>
<ThingDef ParentName="ARA_Cocoon_Base">
<defName>ARA_Cocoon_Wepaon</defName>
<label>阿拉克涅孵化茧 武装器官</label>
<description>一个布满尖刺的囊状物,是阿拉克涅工艺种所诞之卵,内含孵化一个武装器官的营养物质,可以通过阿拉克涅工艺种的交互完成激活进程——参阅茧的超链接,了解其能生产的所有装备的特点。\n\n孵化茧对温度极度敏感该类型的茧适温为-20~35°C需要小心保护</description>
<descriptionHyperlinks>
<ThingDef>ARA_MW_Bone_Sword</ThingDef>
<ThingDef>ARA_RW_Basic_Acid_Bladder_Gun</ThingDef>
<ThingDef>ARA_RW_Basic_Fist_Needle_Gun</ThingDef>
</descriptionHyperlinks>
<researchPrerequisites>
<li>ARA_Technology_5DIL</li>
</researchPrerequisites>
<comps>
<!-- The new, GrowthVat-style fuel component -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelCapacity>10</fuelCapacity>
<fuelLabel>营养</fuelLabel>
<fuelFilter>
<categories>
<li>Foods</li>
</categories>
</fuelFilter>
<fuelConsumptionRate>0</fuelConsumptionRate> <!-- IMPORTANT: Disable base class consumption -->
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<initialFuelPercent>1</initialFuelPercent>
<autoRefuelPercent>1</autoRefuelPercent>
</li>
<!-- The refactored producer component -->
<li Class="ArachnaeSwarm.CompProperties_InteractiveProducer">
<processes>
<li>
<thingDef>ARA_MW_Bone_Sword</thingDef>
<productionTicks>60000</productionTicks>
<totalNutritionNeeded>15</totalNutritionNeeded>
</li>
<li>
<thingDef>ARA_RW_Basic_Fist_Needle_Gun</thingDef>
<productionTicks>40000</productionTicks>
<totalNutritionNeeded>10</totalNutritionNeeded>
<requiredResearch>ARA_Technology_5PAV</requiredResearch>
</li>
<li>
<thingDef>ARA_RW_Basic_Acid_Bladder_Gun</thingDef>
<productionTicks>80000</productionTicks>
<totalNutritionNeeded>30</totalNutritionNeeded>
<requiredResearch>ARA_Technology_7VXI</requiredResearch>
</li>
</processes>
<whitelist>
<li>ArachnaeNode_Race_WeaponSmith</li>
</whitelist>
<spawnCount>1</spawnCount>
<destroyOnSpawn>True</destroyOnSpawn>
<minSafeTemperature>-20</minSafeTemperature>
<maxSafeTemperature>35</maxSafeTemperature>
<penaltyPerDegreePerTick>0.00001</penaltyPerDegreePerTick>
<damagePerTickWhenUnfueled>0.2</damagePerTickWhenUnfueled>
<minNutritionToStart>1.0</minNutritionToStart>
<qualityThresholds>
<li>
<quality>Legendary</quality>
<threshold>0.99</threshold>
</li>
<li>
<quality>Masterwork</quality>
<threshold>0.90</threshold>
</li>
<li>
<quality>Excellent</quality>
<threshold>0.70</threshold>
</li>
<li>
<quality>Good</quality>
<threshold>0.50</threshold>
</li>
<li>
<quality>Normal</quality>
<threshold>0.20</threshold>
</li>
<li>
<quality>Poor</quality>
<threshold>0.10</threshold>
</li>
</qualityThresholds>
</li>
<li Class="ArachnaeSwarm.CompProperties_TemperatureRuinableDamage">
<minSafeTemperature>-20</minSafeTemperature>
<maxSafeTemperature>35</maxSafeTemperature>
<progressPerDegreePerTick>0.00005</progressPerDegreePerTick>
<damagePerTick>0.005</damagePerTick>
<recoveryRate>0.001</recoveryRate>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- ================================================================== -->
<!-- ===== 2. 定义我们的“工作僵尸”思考树,并引用上面的子树 ===== -->
<!-- ================================================================== -->
<ThinkTreeDef>
<defName>ARA_WorkingShambler</defName>
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<!-- 基础状态检查 (来自 Shambler) -->
<li Class="ThinkNode_Subtree">
<treeDef>Despawned</treeDef>
</li>
<li Class="ThinkNode_ConditionalDowned">
<subNodes>
<li Class="ThinkNode_ConditionalCanCrawl">
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>Downed</treeDef>
</li>
</subNodes>
</li>
</subNodes>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>BurningResponse</treeDef>
</li>
<!-- 响应直接命令和威胁 (来自 Shambler) -->
<li Class="ThinkNode_QueuedJob" />
<li Class="ThinkNodeConditional_EscapingHoldingPlatform">
<subNodes>
<li Class="JobGiver_EscapingHoldingPlatform" />
</subNodes>
</li>
<li Class="JobGiver_ReactToCloseMeleeThreat" />
<li Class="ThinkNode_Subtree">
<treeDef>LordDuty</treeDef>
</li>
<!-- 主动战斗 (来自 Shambler) -->
<li Class="JobGiver_ShamblerFight">
<targetAcquireRadius>20</targetAcquireRadius>
<targetKeepRadius>30</targetKeepRadius>
</li>
<!-- 工作逻辑 (引用我们自己的精简版工作核心) -->
<li Class="JobGiver_SeekAllowedArea" />
<li Class="JobGiver_Work">
<emergency>true</emergency>
</li>
<!-- 核心工作循环,但使用我们的精简版 -->
<li Class="JobGiver_Work"/>
<!-- 空闲时徘徊 (来自 Shambler) -->
<li Class="JobGiver_ShamblerWander">
<wanderRadius>5</wanderRadius>
</li>
</subNodes>
</thinkRoot>
</ThinkTreeDef>
</Defs>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<WeaponCategoryDef>
<defName>ARA_Huge_Weapon_Category</defName>
<label>大型武装器官</label>
<description>这种武装器官相当巨大只有那些大型阿拉克涅督虫体型大于2.0)才能使用此武器。</description>
</WeaponCategoryDef>
<WeaponCategoryDef>
<defName>ARA_Weapon_Damage_Category</defName>
<label>特殊武装器官</label>
<description>这种武装器官除了造成常规伤害外,还能引起其他的效果。</description>
</WeaponCategoryDef>
</Defs>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<WeaponTraitDef>
<defName>ARA_Huge_Weapon</defName>
<label>大型武装器官</label>
<description>这种武装器官相当巨大只有那些大型阿拉克涅督虫体型大于2.0)才能使用此武器。</description>
<commonality>1</commonality>
<weaponCategory>ARA_Huge_Weapon_Category</weaponCategory>
<statOffsets>
</statOffsets>
<statFactors>
</statFactors>
</WeaponTraitDef>
<WeaponTraitDef>
<defName>ARA_Weapon_Damage_Acid</defName>
<label>阿拉克涅酸液</label>
<description>这种武装器官的射弹命中敌人时,会在对方身上留下造成持续性伤害的酸液。</description>
<commonality>1</commonality>
<weaponCategory>ARA_Weapon_Damage_Category</weaponCategory>
<statOffsets>
</statOffsets>
<statFactors>
</statFactors>
</WeaponTraitDef>
<WeaponTraitDef>
<defName>ARA_Weapon_Damage_Toxid</defName>
<label>阿拉克涅毒素</label>
<description>这种武装器官的射弹命中敌人时,会向对方体内注入毒素使其中毒。</description>
<commonality>1</commonality>
<weaponCategory>ARA_Weapon_Damage_Category</weaponCategory>
<statOffsets>
</statOffsets>
<statFactors>
</statFactors>
</WeaponTraitDef>
<WeaponTraitDef>
<defName>ARA_Weapon_Damage_Spawn</defName>
<label>阿拉克涅子巢</label>
<description>这种武装器官的主要攻击方式是释放辅虫,其中一些会直接把辅虫往敌人中投掷,另一些则会使辅虫跟踪和吸附敌军以造成伤害。</description>
<commonality>1</commonality>
<weaponCategory>ARA_Weapon_Damage_Category</weaponCategory>
<statOffsets>
</statOffsets>
<statFactors>
</statFactors>
</WeaponTraitDef>
</Defs>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
<!-- CompAbilityEffect_Transform -->
<PawnTransformer_SpaceBlocked>{PAWN_labelShort} 无法变形:空间不足或有障碍物。</PawnTransformer_SpaceBlocked>
<AbilityCannotBeUsedOnOthers>此能力只能对自己施放。</AbilityCannotBeUsedOnOthers>
<!-- Building_Morphable -->
<StoredPawn>织域者</StoredPawn>
<Activity>活动</Activity>
<Researching>研究中</Researching>
<Idle>空闲中</Idle>
<Sleeping>睡眠中</Sleeping>
<PawnTransformer_OutOfFuel>{PAWN_labelShort} 因营养耗尽而被强制弹出!</PawnTransformer_OutOfFuel>
<PawnTransformer_ForcedRevert>{PAWN_labelShort} 因受到攻击而被强制弹出!</PawnTransformer_ForcedRevert>
<PawnTransformer_BuildingDestroyed>{PAWN_labelShort} 从被摧毁的 {BUILDING_label} 中弹出!</PawnTransformer_BuildingDestroyed>
</LanguageData>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1,14 +1,14 @@
{
"Version": 1,
"WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\ara_buildingterrainspawn\\compdelayedterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:ara_buildingterrainspawn\\compdelayedterrainspawn.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\\verb\\verb_shootmeltbeam.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:verb\\verb_shootmeltbeam.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\ara_buildingterrainspawn\\compproperties_delayedterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:ara_buildingterrainspawn\\compproperties_delayedterrainspawn.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\\verb\\compcleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:verb\\compcleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@@ -18,37 +18,36 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 0,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "CompDelayedTerrainSpawn.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeDocumentMoniker": "ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeToolTip": "ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxcAAAAfAAAAAAAAAA==",
"Title": "Verb_ShootMeltBeam.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verb\\Verb_ShootMeltBeam.cs",
"RelativeDocumentMoniker": "Verb\\Verb_ShootMeltBeam.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verb\\Verb_ShootMeltBeam.cs",
"RelativeToolTip": "Verb\\Verb_ShootMeltBeam.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAyAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-09-05T11:17:51.595Z",
"WhenOpened": "2025-09-09T03:04:00.299Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "CompProperties_DelayedTerrainSpawn.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_BuildingTerrainSpawn\\CompProperties_DelayedTerrainSpawn.cs",
"RelativeDocumentMoniker": "ARA_BuildingTerrainSpawn\\CompProperties_DelayedTerrainSpawn.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_BuildingTerrainSpawn\\CompProperties_DelayedTerrainSpawn.cs",
"RelativeToolTip": "ARA_BuildingTerrainSpawn\\CompProperties_DelayedTerrainSpawn.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Title": "CompCleave.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verb\\CompCleave.cs",
"RelativeDocumentMoniker": "Verb\\CompCleave.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verb\\CompCleave.cs",
"RelativeToolTip": "Verb\\CompCleave.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAmAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-09-05T11:17:48.391Z",
"EditorCaption": ""
},
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
"WhenOpened": "2025-09-09T03:03:30.118Z"
}
]
}

View File

@@ -0,0 +1,154 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using RimWorld;
namespace WulaFallenEmpire
{
public class CompCustomUniqueWeapon : CompUniqueWeapon
{
// 使用 'new' 关键字来明确隐藏基类成员,解决 CS0108 警告
public new CompProperties_CustomUniqueWeapon Props => (CompProperties_CustomUniqueWeapon)props;
private List<WeaponTraitDef> customTraits = new List<WeaponTraitDef>();
// 使用 'new' 关键字隐藏基类属性,解决 CS0506 错误
public new List<WeaponTraitDef> TraitsListForReading => customTraits;
// PostExposeData 是 virtual 的,保留 override
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Collections.Look(ref customTraits, "customTraits", LookMode.Def);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
if (customTraits == null) customTraits = new List<WeaponTraitDef>();
SetupCustomTraits(fromSave: true);
}
}
// PostPostMake 是 virtual 的,保留 override
public override void PostPostMake()
{
InitializeCustomTraits();
if (parent.TryGetComp<CompQuality>(out var comp))
{
comp.SetQuality(QualityUtility.GenerateQuality(QualityGenerator.Super), ArtGenerationContext.Outsider);
}
}
private void InitializeCustomTraits()
{
if (customTraits == null) customTraits = new List<WeaponTraitDef>();
customTraits.Clear();
if (Props.forcedTraits != null)
{
foreach (var traitToForce in Props.forcedTraits)
{
if (customTraits.All(t => !t.Overlaps(traitToForce)))
{
customTraits.Add(traitToForce);
}
}
}
IntRange traitRange = Props.numTraitsRange ?? new IntRange(1, 3);
int totalTraitsTarget = Mathf.Max(customTraits.Count, traitRange.RandomInRange);
int missingTraits = totalTraitsTarget - customTraits.Count;
if (missingTraits > 0)
{
// CanAddTrait 现在是我们自己的 'new' 方法
IEnumerable<WeaponTraitDef> possibleTraits = DefDatabase<WeaponTraitDef>.AllDefs.Where(CanAddTrait);
for (int i = 0; i < missingTraits; i++)
{
if (!possibleTraits.Any()) break;
var chosenTrait = possibleTraits.RandomElementByWeight(t => t.commonality);
customTraits.Add(chosenTrait);
possibleTraits = possibleTraits.Where(t => t != chosenTrait && !t.Overlaps(chosenTrait));
}
}
SetupCustomTraits(fromSave: false);
}
private void SetupCustomTraits(bool fromSave)
{
foreach (WeaponTraitDef trait in customTraits)
{
if (trait.abilityProps != null && parent.GetComp<CompEquippableAbilityReloadable>() is CompEquippableAbilityReloadable comp)
{
comp.props = trait.abilityProps;
if (!fromSave)
{
comp.Notify_PropsChanged();
}
}
}
}
// 使用 'new' 关键字隐藏基类方法,解决 CS0506 错误
public new bool CanAddTrait(WeaponTraitDef trait)
{
if (customTraits.Any(t => t == trait || t.Overlaps(t)))
return false;
if (Props.weaponCategories != null && Props.weaponCategories.Any() && !Props.weaponCategories.Contains(trait.weaponCategory))
return false;
if (customTraits.Count == 0 && !trait.canGenerateAlone)
return false;
return true;
}
// --- 下面的方法都是 virtual 的,保留 override ---
public override string TransformLabel(string label) => label;
public override Color? ForceColor() => null;
public override float GetStatOffset(StatDef stat) => customTraits.Sum(t => t.statOffsets.GetStatOffsetFromList(stat));
public override float GetStatFactor(StatDef stat) => customTraits.Aggregate(1f, (current, t) => current * t.statFactors.GetStatFactorFromList(stat));
public override string CompInspectStringExtra()
{
if (customTraits.NullOrEmpty()) return null;
return "WeaponTraits".Translate() + ": " + customTraits.Select(t => t.label).ToCommaList().CapitalizeFirst();
}
public override string CompTipStringExtra()
{
if (customTraits.NullOrEmpty()) return base.CompTipStringExtra();
return "WeaponTraits".Translate() + ": " + customTraits.Select(t => t.label).ToCommaList().CapitalizeFirst();
}
public override IEnumerable<StatDrawEntry> SpecialDisplayStats()
{
if (customTraits.NullOrEmpty()) yield break;
var builder = new StringBuilder();
builder.AppendLine("Stat_ThingUniqueWeaponTrait_Desc".Translate());
builder.AppendLine();
for (int i = 0; i < customTraits.Count; i++)
{
WeaponTraitDef trait = customTraits[i];
builder.AppendLine(trait.LabelCap.Colorize(ColorLibrary.Yellow));
builder.AppendLine(trait.description);
if (i < customTraits.Count - 1) builder.AppendLine();
}
yield return new StatDrawEntry(
parent.def.IsMeleeWeapon ? StatCategoryDefOf.Weapon_Melee : StatCategoryDefOf.Weapon_Ranged,
"Stat_ThingUniqueWeaponTrait_Label".Translate(),
customTraits.Select(t => t.label).ToCommaList().CapitalizeFirst(),
builder.ToString(),
1104);
}
}
}

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
using Verse;
using RimWorld;
namespace WulaFallenEmpire
{
public class CompProperties_CustomUniqueWeapon : CompProperties_UniqueWeapon
{
// A list of traits that will always be added to the weapon.
public List<WeaponTraitDef> forcedTraits;
// The range of traits to randomly add. If not defined in XML, a default of 1-3 will be used.
public IntRange? numTraitsRange;
public CompProperties_CustomUniqueWeapon()
{
// Point to the implementation of our custom logic.
this.compClass = typeof(CompCustomUniqueWeapon);
}
}
}

View File

@@ -0,0 +1,23 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
namespace ArachnaeSwarm
{
public class HediffCompProperties_GiveHediffsInRangeToRace : HediffCompProperties
{
public float range;
public TargetingParameters targetingParameters;
public HediffDef hediff;
public ThingDef mote;
public bool hideMoteWhenNotDrafted;
public float initialSeverity = 1f;
public bool onlyPawnsInSameFaction = true;
public List<ThingDef> targetRaces; // 新增:可配置的目标种族列表
public HediffCompProperties_GiveHediffsInRangeToRace()
{
compClass = typeof(HediffComp_GiveHediffsInRangeToRace);
}
}
}

View File

@@ -0,0 +1,63 @@
using RimWorld;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class HediffComp_GiveHediffsInRangeToRace : HediffComp
{
private Mote mote;
public HediffCompProperties_GiveHediffsInRangeToRace Props => (HediffCompProperties_GiveHediffsInRangeToRace)props;
public override void CompPostTick(ref float severityAdjustment)
{
if (!parent.pawn.Awake() || parent.pawn.health == null || parent.pawn.health.InPainShock || !parent.pawn.Spawned)
{
return;
}
if (!Props.hideMoteWhenNotDrafted || parent.pawn.Drafted)
{
if (Props.mote != null && (mote == null || mote.Destroyed))
{
mote = MoteMaker.MakeAttachedOverlay(parent.pawn, Props.mote, Vector3.zero);
}
if (mote != null)
{
mote.Maintain();
}
}
IReadOnlyList<Pawn> pawns = ((!Props.onlyPawnsInSameFaction || parent.pawn.Faction == null) ? parent.pawn.Map.mapPawns.AllPawnsSpawned : parent.pawn.Map.mapPawns.SpawnedPawnsInFaction(parent.pawn.Faction));
foreach (Pawn pawn in pawns)
{
// 修改点检查种族是否在我们的目标列表中如果列表为空或null则不进行任何操作
if ((Props.targetRaces.NullOrEmpty() || !Props.targetRaces.Contains(pawn.def)) || pawn.Dead || pawn.health == null || pawn == parent.pawn || !(pawn.Position.DistanceTo(parent.pawn.Position) <= Props.range) || !Props.targetingParameters.CanTarget(pawn))
{
continue;
}
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediff);
if (hediff == null)
{
hediff = pawn.health.AddHediff(Props.hediff, pawn.health.hediffSet.GetBrain());
hediff.Severity = Props.initialSeverity;
HediffComp_Link hediffComp_Link = hediff.TryGetComp<HediffComp_Link>();
if (hediffComp_Link != null)
{
hediffComp_Link.drawConnection = true;
hediffComp_Link.other = parent.pawn;
}
}
HediffComp_Disappears hediffComp_Disappears = hediff.TryGetComp<HediffComp_Disappears>();
if (hediffComp_Disappears == null)
{
Log.Error("HediffComp_GiveHediffsInRangeToRace has a hediff in props which does not have a HediffComp_Disappears");
}
else
{
hediffComp_Disappears.ticksToDisappear = 5;
}
}
}
}
}

View File

@@ -0,0 +1,85 @@
using RimWorld;
using Verse;
using Verse.Sound;
using System.Collections.Generic;
using System.Linq;
namespace ArachnaeSwarm
{
public class CompAbilityEffect_DRM_Deaddustpop : CompAbilityEffect
{
public new CompProperties_AbilityDRM_Deaddustpop Props
{
get
{
return (CompProperties_AbilityDRM_Deaddustpop)this.props;
}
}
private Pawn Pawn
{
get
{
return this.parent.pawn;
}
}
private List<IntVec3> AffectedCells(LocalTargetInfo target)
{
return GenRadial.RadialCellsAround(target.Cell, Props.smokeRadius, true).ToList();
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
GenExplosion.DoExplosion(
center: target.Cell,
map: this.parent.pawn.MapHeld,
radius: this.Props.smokeRadius,
damType: this.Props.damageDef,
instigator: null,
damAmount: this.Props.damageAmount,
armorPenetration: this.Props.armorPenetration,
// 明确命名关键参数,避免顺序错误
postExplosionSpawnThingDef: this.Props.postExplosionSpawnThingDef,
postExplosionSpawnChance: this.Props.postExplosionSpawnChance,
postExplosionSpawnThingCount: this.Props.postExplosionSpawnThingCount,
postExplosionGasType: this.Props.gasType,
// 需要补充的参数(根据实际需求填写)
flammabilityChanceCurve: null,
overrideCells: this.AffectedCells(target), // 明确传递实际需要的值
postExplosionSpawnSingleThingDef: null,
preExplosionSpawnSingleThingDef: null
);
}
public override void DrawEffectPreview(LocalTargetInfo target)
{
GenDraw.DrawRadiusRing(target.Cell, this.Props.smokeRadius);
}
}
public class CompProperties_AbilityDRM_Deaddustpop : CompProperties_AbilityEffect
{
public CompProperties_AbilityDRM_Deaddustpop()
{
this.compClass = typeof(CompAbilityEffect_DRM_Deaddustpop);
}
public float smokeRadius;
public SoundDef explosionSound;
public GasType gasType;
public DamageDef damageDef;
public float postExplosionSpawnChance = 0f;
public int postExplosionSpawnThingCount = 1;
public ThingDef postExplosionSpawnThingDef = null;
public int damageAmount = -1;
public float armorPenetration = -1f;
}
}

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -69,6 +68,10 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ARA_CustomUniqueWeapon\CompCustomUniqueWeapon.cs" />
<Compile Include="ARA_CustomUniqueWeapon\CompProperties_CustomUniqueWeapon.cs" />
<Compile Include="ARA_GiveHediffsInRangeToRace\HediffCompProperties_GiveHediffsInRangeToRace.cs" />
<Compile Include="ARA_GiveHediffsInRangeToRace\HediffComp_GiveHediffsInRangeToRace.cs" />
<Compile Include="ARA_SpawnPawnFromList\CompProperties_SpawnPawnFromList.cs" />
<Compile Include="ARA_SpawnPawnFromList\CompSpawnPawnFromList.cs" />
<Compile Include="ARA_SpawnPawnFromList\JobDriver_Incubate.cs" />
@@ -89,6 +92,18 @@
<Compile Include="ARA_HiveMind\CompAbilityEffect_BindDrone.cs" />
<Compile Include="ARA_HiveMind\CompProperties_AbilityBindDrone.cs" />
<Compile Include="ARA_SpawnPawnFromList\JobGiver_MaintainBuildings.cs" />
<Compile Include="Verb\CompCleave.cs" />
<Compile Include="Verb\CompMultiStrike.cs" />
<Compile Include="Verb\VerbPropertiesExplosiveBeam.cs" />
<Compile Include="Verb\VerbProperties_Excalibur.cs" />
<Compile Include="Verb\VerbProperties_WeaponStealBeam.cs" />
<Compile Include="Verb\Verb_MeleeAttack_Cleave.cs" />
<Compile Include="Verb\Verb_MeleeAttack_MultiStrike.cs" />
<Compile Include="Verb\Verb_ShootArc.cs" />
<Compile Include="Verb\Verb_ShootBeamExplosive.cs" />
<Compile Include="Verb\Verb_ShootMeltBeam.cs" />
<Compile Include="Verb\Verb_ShootShotgun.cs" />
<Compile Include="Verb\Verb_ShootWeaponStealBeam.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="ARA_CompHediffGiver\CompHediffGiver.cs" />
@@ -109,9 +124,9 @@
<Compile Include="ARA_BuildingTerrainSpawn\CompDelayedTerrainSpawn.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="WULA_AutoMechCarrier\CompAutoMechCarrier.cs" />
<Compile Include="WULA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />
<Compile Include="WULA_AutoMechCarrier\PawnProductionEntry.cs" />
<Compile Include="ARA_AutoMechCarrier\CompAutoMechCarrier.cs" />
<Compile Include="ARA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />
<Compile Include="ARA_AutoMechCarrier\PawnProductionEntry.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="ARA_CompInteractiveProducer\CompInteractiveProducer.cs" />
@@ -141,12 +156,49 @@
<Compile Include="CompPawnFlight.cs" />
<Compile Include="CompProperties_PawnFlight.cs" />
<Compile Include="HarmonyPatches.cs" />
<Compile Include="OPToxicGas.cs" />
<Compile Include="PawnRenderNodeWorker_AttachmentBody_NoFlight.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="CompAbilityEffect_LaunchMultiProjectile.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Abilities\CompAbilityEffect_TrackingCharge.cs" />
<Compile Include="Abilities\CompProperties_TrackingCharge.cs" />
<Compile Include="Abilities\PawnFlyer_TrackingCharge.cs" />
<Compile Include="Abilities\Verb_CastAbilityTrackingCharge.cs" />
<Compile Include="Abilities\CompAbilityEffect_DRM_Deaddustpop.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="HediffComp_SpawnPawnOnRemoved.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Projectiles\BulletWithTrail.cs" />
<Compile Include="Projectiles\ExplosiveTrackingBulletDef.cs" />
<Compile Include="Projectiles\Projectile_ConfigurableHellsphereCannon.cs" />
<Compile Include="Projectiles\Projectile_CruiseMissile.cs" />
<Compile Include="Projectiles\Projectile_ExplosiveTrackingBullet.cs" />
<Compile Include="Projectiles\Projectile_ExplosiveWithTrail.cs" />
<Compile Include="Projectiles\Projectile_TrackingBullet.cs" />
<Compile Include="Projectiles\Projectile_WulaPenetratingBeam.cs" />
<Compile Include="Projectiles\Projectile_WulaPenetratingBullet.cs" />
<Compile Include="Projectiles\TrackingBulletDef.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="HediffComp_NecroticTransformation.cs" />
<Compile Include="Hediff_NecroticVirus_Configurable.cs" />
<Compile Include="NecroticTransformationUtility.cs" />
<Compile Include="ProphecyGearEffect.cs" />
<Compile Include="Hediff_ConfigurableMutant.cs" />
<Compile Include="HediffComp_Symbiosis.cs" />
<Compile Include="HediffGiver_RandomWithSeverity.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Morphable\CompProperties_Morphable.cs" />
<Compile Include="Morphable\CompMorphable.cs" />
<Compile Include="Morphable\CompProperties_AbilityTransform.cs" />
<Compile Include="Morphable\CompAbilityEffect_Transform.cs" />
<Compile Include="Morphable\Building_Morphable.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 自定义清理任务删除obj文件夹中的临时文件 -->

View File

@@ -0,0 +1,44 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityLaunchMultiProjectile : CompProperties_AbilityLaunchProjectile
{
public int numProjectiles = 1;
public CompProperties_AbilityLaunchMultiProjectile()
{
compClass = typeof(CompAbilityEffect_LaunchMultiProjectile);
}
}
public class CompAbilityEffect_LaunchMultiProjectile : CompAbilityEffect
{
public new CompProperties_AbilityLaunchMultiProjectile Props => (CompProperties_AbilityLaunchMultiProjectile)props;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
for (int i = 0; i < Props.numProjectiles; i++)
{
LaunchProjectile(target);
}
}
private void LaunchProjectile(LocalTargetInfo target)
{
if (Props.projectileDef != null)
{
Pawn pawn = parent.pawn;
Projectile projectile = (Projectile)GenSpawn.Spawn(Props.projectileDef, pawn.Position, pawn.Map);
projectile.Launch(pawn, pawn.DrawPos, target, target, ProjectileHitFlags.IntendedTarget, parent.verb.preventFriendlyFire);
}
}
public override bool AICanTargetNow(LocalTargetInfo target)
{
return target.Pawn != null;
}
}
}

View File

@@ -0,0 +1,31 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
/// <summary>
/// XML配置类用于在HediffDef的comp中指定转化后的MutantDef
/// </summary>
public class HediffCompProperties_NecroticTransformation : HediffCompProperties
{
// 在XML中需要指定的MutantDef的defName
public MutantDef mutantDef;
// 在XML中配置触发转变所需的严重性阈值
public float triggerSeverity = 0.7f;
public HediffCompProperties_NecroticTransformation()
{
compClass = typeof(HediffComp_NecroticTransformation);
}
}
/// <summary>
/// HediffComp用于在运行时存储和提供由XML定义的MutantDef
/// </summary>
public class HediffComp_NecroticTransformation : HediffComp
{
// 属性用于方便地从Comp中获取配置
public HediffCompProperties_NecroticTransformation Props => (HediffCompProperties_NecroticTransformation)props;
}
}

View File

@@ -0,0 +1,104 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
using System.Linq;
namespace ArachnaeSwarm
{
/// <summary>
/// Defines the properties for HediffComp_SpawnPawnOnRemoved.
/// You must specify the pawnKindDef to spawn.
/// </summary>
public class HediffCompProperties_SpawnPawnOnRemoved : HediffCompProperties
{
public List<PawnKindDef> pawnKindDefs; // 更改为列表
public int spawnCount = 1; // 新增生成数量
public float? fixedBiologicalAge; // 新增用于XML配置的固定生物年龄
public FloatRange? biologicalAgeRange; // 新增用于XML配置的生物年龄范围
public HediffCompProperties_SpawnPawnOnRemoved()
{
this.compClass = typeof(HediffComp_SpawnPawnOnRemoved);
}
}
/// <summary>
/// Spawns a specified pawn when the parent hediff is removed.
/// The pawn's faction is determined by the hediff's instigator.
/// </summary>
public class HediffComp_SpawnPawnOnRemoved : HediffComp
{
// This field will store the faction of the original attacker.
private Faction casterFaction;
public HediffCompProperties_SpawnPawnOnRemoved Props => (HediffCompProperties_SpawnPawnOnRemoved)this.props;
/// <summary>
/// Called after the hediff is added. We use this to capture the instigator's faction.
/// </summary>
public override void CompPostPostAdd(DamageInfo? dinfo)
{
base.CompPostPostAdd(dinfo);
if (dinfo.HasValue && dinfo.Value.Instigator != null)
{
this.casterFaction = dinfo.Value.Instigator.Faction;
}
}
/// <summary>
/// Called when the hediff is removed. This is where we spawn the pawn.
/// </summary>
public override void CompPostPostRemoved()
{
base.CompPostPostRemoved();
if (this.Pawn == null || this.Pawn.Map == null || Props.pawnKindDefs.NullOrEmpty())
{
Log.Warning("ArachnaeSwarm: HediffComp_SpawnPawnOnRemoved tried to spawn a pawn but required data was missing (Pawn, Map, or pawnKindDefs).");
return;
}
Map map = this.Pawn.Map;
IntVec3 loc = this.Pawn.Position;
// If casterFaction is null, default to the player's faction
if (this.casterFaction == null)
{
this.casterFaction = Faction.OfPlayer;
}
for (int i = 0; i < Props.spawnCount; i++)
{
PawnKindDef selectedPawnKindDef = Props.pawnKindDefs.RandomElement();
Pawn newPawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
kind: selectedPawnKindDef,
faction: this.casterFaction, // Use the stored faction
context: PawnGenerationContext.NonPlayer,
tile: -1,
forceGenerateNewPawn: true,
fixedBiologicalAge: Props.fixedBiologicalAge, // 使用XML配置的固定生物年龄
biologicalAgeRange: Props.biologicalAgeRange // 使用XML配置的生物年龄范围
));
if (newPawn != null)
{
GenSpawn.Spawn(newPawn, loc, map, WipeMode.Vanish);
}
else
{
Log.Error($"ArachnaeSwarm: Failed to generate pawn of kind {selectedPawnKindDef.defName}.");
}
}
}
/// <summary>
/// Ensures the casterFaction is saved and loaded with the game.
/// </summary>
public override void CompExposeData()
{
base.CompExposeData();
Scribe_References.Look(ref this.casterFaction, "casterFaction");
}
}
}

View File

@@ -0,0 +1,61 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
/// <summary>
/// XML配置类定义共生关系
/// </summary>
public class HediffCompProperties_Symbiosis : HediffCompProperties
{
// 实现共存所需的Hediff
public HediffDef requiredHediff;
// 共存状态下的最大严重性
public float newMaxSeverity = 0.9f;
public HediffCompProperties_Symbiosis()
{
compClass = typeof(HediffComp_Symbiosis);
}
}
/// <summary>
/// HediffComp实现共生逻辑
/// </summary>
public class HediffComp_Symbiosis : HediffComp
{
private HediffCompProperties_Symbiosis Props => (HediffCompProperties_Symbiosis)props;
// 重写CompPostTick它会在游戏每一帧在计算完严重性增量之后应用增量之前被调用
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
// 检查宿主Pawn是否存在以及配置是否完整
if (this.Pawn == null || Props.requiredHediff == null)
{
return;
}
// 检查Pawn是否拥有“共存”所需的Hediff
if (this.Pawn.health.hediffSet.HasHediff(Props.requiredHediff))
{
// 如果当前严重性已经达到或超过上限
if (this.parent.Severity >= Props.newMaxSeverity)
{
// 将当前严重性强制拉回到上限
this.parent.Severity = Props.newMaxSeverity;
// 并且阻止任何将要发生的严重性增加将增量设为0
severityAdjustment = 0;
}
// 如果当前严重性加上即将发生的增量会超过上限
else if (this.parent.Severity + severityAdjustment > Props.newMaxSeverity)
{
// 重新计算增量,使其恰好达到上限
severityAdjustment = Props.newMaxSeverity - this.parent.Severity;
}
}
}
}
}

View File

@@ -0,0 +1,54 @@
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// A custom HediffGiver that is similar to HediffGiver_Random,
/// but allows specifying a random severity range for the given hediff.
/// </summary>
public class HediffGiver_RandomWithSeverity : HediffGiver
{
// XML configurable fields
public float mtbDays;
public FloatRange severityRange = new FloatRange(0.01f, 1f);
public override void OnIntervalPassed(Pawn pawn, Hediff cause)
{
// Calculate the chance based on Mean Time Between (MTB) days and pawn-specific factors
float mtb = this.mtbDays;
float chanceFactor = ChanceFactor(pawn);
if (chanceFactor != 0f && Rand.MTBEventOccurs(mtb / chanceFactor, 60000f, 60f))
{
// Try to apply the hediff with our custom logic
if (TryApplyWithCustomSeverity(pawn))
{
// If successful, send a letter to the player
SendLetter(pawn, cause);
}
}
}
/// <summary>
/// Applies the hediff and then sets its severity to a random value within the specified range.
/// </summary>
/// <param name="pawn">The pawn to apply the hediff to.</param>
/// <returns>True if the hediff was successfully applied, false otherwise.</returns>
private bool TryApplyWithCustomSeverity(Pawn pawn)
{
// First, apply the hediff using the base class logic.
// This will add the hediff with its default initial severity.
if (base.TryApply(pawn))
{
// If the hediff was successfully added, find it.
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(this.hediff);
if (hediff != null)
{
// Set its severity to a random value from our configured range.
hediff.Severity = this.severityRange.RandomInRange;
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,373 @@
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.AI.Group;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class HediffCompProperties_ConfigurableMutant : HediffCompProperties
{
// --- 可配置的Hediff ---
public HediffDef risingHediff;
public HediffDef corpseHediff;
// --- 可配置的时间和范围 ---
public FloatRange resurrectionSecondsRange = new FloatRange(5f, 10f);
public FloatRange stunSecondsRange = new FloatRange(1f, 3f);
public FloatRange alertSecondsRange = new FloatRange(0.5f, 3f);
public IntRange selfRaiseHoursRange = new IntRange(3, 4);
public IntRange checkForTargetTicksInterval = new IntRange(900, 1800);
// --- 可配置的杂项值 ---
public float particleSpawnMTBSeconds = 1f;
public float extinguishFireMTB = 45f;
public float bioferriteOnDeathChance = 0.04f;
public int bioferriteAmountOnDeath = 10;
public HediffCompProperties_ConfigurableMutant()
{
this.compClass = typeof(HediffComp_ConfigurableMutant);
}
}
public class HediffComp_ConfigurableMutant : HediffComp
{
public HediffCompProperties_ConfigurableMutant Props => (HediffCompProperties_ConfigurableMutant)this.props;
}
public class Hediff_ConfigurableMutant : HediffWithComps
{
// 运行时状态字段,保持不变
public float headRotation;
private float resurrectTimer;
private float selfRaiseTimer;
private float alertTimer;
private int nextTargetCheckTick = -99999;
private Thing alertedTarget;
private Effecter riseEffecter;
private Sustainer riseSustainer;
private float corpseDamagePct = 1f;
private HediffComp_ConfigurableMutant PropsComp => this.TryGetComp<HediffComp_ConfigurableMutant>();
public bool IsRising => PropsComp?.Props.risingHediff != null && pawn.health.hediffSet.HasHediff(PropsComp.Props.risingHediff);
public override void PostMake()
{
base.PostMake();
headRotation = Rand.RangeSeeded(-20f, 20f, pawn.thingIDNumber);
if (!pawn.Dead)
{
pawn.timesRaisedAsShambler++;
}
}
public override void PostAdd(DamageInfo? dinfo)
{
if (!ModLister.CheckAnomaly("Shambler"))
{
pawn.health.RemoveHediff(this);
}
else
{
base.PostAdd(dinfo);
}
}
public override void Notify_Spawned()
{
base.Notify_Spawned();
pawn.Map.mapPawns.RegisterShambler(pawn);
}
public override void TickInterval(int delta)
{
base.TickInterval(delta);
var compProps = PropsComp?.Props;
if (compProps == null) return; // 如果没有Comp则不执行任何操作
if (IsRising)
{
if ((float)Find.TickManager.TicksGame > resurrectTimer)
{
FinishRising();
}
if (!pawn.Spawned) return;
if ((float)Find.TickManager.TicksGame > resurrectTimer - 15f)
{
riseSustainer?.End();
}
else if (IsRising)
{
if (riseSustainer == null || riseSustainer.Ended)
{
riseSustainer = SoundDefOf.Pawn_Shambler_Rise.TrySpawnSustainer(SoundInfo.InMap(pawn, MaintenanceType.PerTick));
}
if (riseEffecter == null)
{
riseEffecter = EffecterDefOf.ShamblerRaise.Spawn(pawn, pawn.Map);
}
if (pawn.Drawer.renderer.CurAnimation != AnimationDefOf.ShamblerRise)
{
pawn.Drawer.renderer.SetAnimation(AnimationDefOf.ShamblerRise);
}
riseSustainer.Maintain();
riseEffecter.EffectTick(pawn, TargetInfo.Invalid);
}
return;
}
if (Rand.MTBEventOccurs(compProps.particleSpawnMTBSeconds, 60f, 1f))
{
FleckMaker.ThrowShamblerParticles(pawn);
}
if (pawn.IsBurning() && !pawn.Downed && Rand.MTBEventOccurs(compProps.extinguishFireMTB, 60f, 1f))
{
((Fire)pawn.GetAttachment(ThingDefOf.Fire))?.Destroy();
pawn.records.Increment(RecordDefOf.FiresExtinguished);
}
if (pawn.Spawned && pawn.mutant != null && !pawn.mutant.IsPassive && !pawn.Drafted)
{
if (Find.TickManager.TicksGame > nextTargetCheckTick)
{
nextTargetCheckTick = Find.TickManager.TicksGame + compProps.checkForTargetTicksInterval.RandomInRange;
Thing thing = MutantUtility.FindShamblerTarget(pawn);
if (thing != null)
{
Notify_DelayedAlert(thing);
MutantUtility.ActivateNearbyShamblers(pawn, thing);
}
}
if (alertedTarget != null && (float)Find.TickManager.TicksGame > alertTimer)
{
pawn.mindState.enemyTarget = alertedTarget;
pawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; // 直接给public字段赋值绕过internal方法
alertedTarget = null;
if (DebugViewSettings.drawShamblerAlertMote)
{
MoteMaker.MakeColonistActionOverlay(pawn, ThingDefOf.Mote_ShamblerAlert);
}
SoundDefOf.Pawn_Shambler_Alert.PlayOneShot(pawn);
}
}
if (ShouldSelfRaise())
{
StartRising();
}
}
private bool ShouldSelfRaise()
{
if (pawn.DevelopmentalStage == DevelopmentalStage.Baby) return false;
return pawn.Downed && pawn.CarriedBy == null && (float)Find.TickManager.TicksGame > selfRaiseTimer;
}
public void StartRising(int lifespanTicks = -1)
{
var compProps = PropsComp?.Props;
if (compProps?.risingHediff == null)
{
Log.Error($"[ConfigurableMutant] risingHediff is not defined in XML for {this.def.defName}");
return;
}
if (!pawn.Dead && !pawn.Downed)
{
Log.Error("Tried to raise non dead/downed pawn as shambler");
if(pawn.mutant != null) pawn.mutant.Turn(clearLord: true);
return;
}
MutantUtility.RestoreBodyParts(pawn);
pawn.Notify_DisabledWorkTypesChanged();
if (!pawn.Dead || ResurrectionUtility.TryResurrect(pawn, new ResurrectionParams { noLord = true, restoreMissingParts = false, removeDiedThoughts = false }))
{
pawn.jobs?.EndCurrentJob(JobCondition.InterruptForced);
resurrectTimer = Find.TickManager.TicksGame + compProps.resurrectionSecondsRange.RandomInRange.SecondsToTicks();
pawn.health.AddHediff(compProps.risingHediff);
}
}
private void CancelRising()
{
var risingHediff = PropsComp?.Props.risingHediff;
if (risingHediff == null) return;
riseSustainer?.End();
resurrectTimer = -99999f;
if (pawn.health.hediffSet.TryGetHediff(risingHediff, out var hediff))
{
pawn.health.RemoveHediff(hediff);
}
if (!pawn.Dead)
{
pawn.Kill(null, null);
}
}
private void FinishRising(bool stun = true)
{
var compProps = PropsComp?.Props;
if (compProps?.risingHediff != null && pawn.health.hediffSet.TryGetHediff(compProps.risingHediff, out var hediff))
{
pawn.health.RemoveHediff(hediff);
}
if (pawn.ParentHolder is Pawn_CarryTracker pawn_CarryTracker)
{
pawn_CarryTracker.TryDropCarriedThing(pawn_CarryTracker.pawn.Position, ThingPlaceMode.Near, out var _);
pawn_CarryTracker.pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
}
if (pawn.mutant != null && !pawn.mutant.HasTurned)
{
pawn.mutant.Turn();
}
pawn.timesRaisedAsShambler++;
MutantUtility.RestoreUntilNotDowned(pawn);
if (pawn.Spawned && stun)
{
pawn.Rotation = Rot4.South;
if(compProps != null)
pawn.stances.stunner.StunFor(compProps.stunSecondsRange.RandomInRange.SecondsToTicks(), pawn, addBattleLog: false, showMote: false);
}
pawn.Drawer.renderer.SetAnimation(null);
StartSelfRaiseTimer();
}
private void StartSelfRaiseTimer()
{
var selfRaiseHoursRange = PropsComp?.Props.selfRaiseHoursRange ?? new IntRange(3, 4);
selfRaiseTimer = Find.TickManager.TicksGame + 2500 * selfRaiseHoursRange.RandomInRange;
}
public override void Notify_PawnPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
{
base.Notify_PawnPostApplyDamage(dinfo, totalDamageDealt);
if (dinfo.Instigator != null && pawn.HostileTo(dinfo.Instigator))
{
if (pawn.Spawned && dinfo.Instigator is IAttackTarget && dinfo.Instigator.Spawned && pawn.CanSee(dinfo.Instigator))
{
pawn.mindState.enemyTarget = dinfo.Instigator;
pawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; // 直接给public字段赋值绕过internal方法
pawn.jobs.EndCurrentJob(JobCondition.InterruptOptional);
pawn.GetLord()?.Notify_PawnAcquiredTarget(pawn, dinfo.Instigator);
}
MutantUtility.ActivateNearbyShamblers(pawn, dinfo.Instigator);
}
}
public void Notify_DelayedAlert(Thing target)
{
var alertSecondsRange = PropsComp?.Props.alertSecondsRange ?? new FloatRange(0.5f, 3f);
if (pawn.mutant != null && !pawn.mutant.IsPassive && !pawn.Drafted && pawn.mindState.enemyTarget == null)
{
alertTimer = Find.TickManager.TicksGame + alertSecondsRange.RandomInRange.SecondsToTicks();
alertedTarget = target;
pawn.GetLord()?.Notify_PawnAcquiredTarget(pawn, target);
}
}
public override void Notify_Downed()
{
StartSelfRaiseTimer();
}
public override void Notify_PawnKilled()
{
corpseDamagePct = pawn.health.summaryHealth.SummaryHealthPercent;
base.Notify_PawnKilled();
}
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
{
if (IsRising)
{
CancelRising();
}
var compProps = PropsComp?.Props;
if (compProps != null && pawn.timesRaisedAsShambler == 1 && Rand.Chance(compProps.bioferriteOnDeathChance) && pawn.SpawnedOrAnyParentSpawned)
{
Thing thing = ThingMaker.MakeThing(ThingDefOf.Bioferrite);
thing.stackCount = compProps.bioferriteAmountOnDeath;
GenPlace.TryPlaceThing(thing, pawn.PositionHeld, pawn.MapHeld, ThingPlaceMode.Near, out var lastResultingThing);
lastResultingThing.SetForbidden(value: true);
}
if (pawn.Corpse != null)
{
pawn.Corpse.HitPoints = Mathf.Max(Mathf.RoundToInt((float)pawn.Corpse.MaxHitPoints * corpseDamagePct), 10);
}
if (compProps?.corpseHediff != null)
{
pawn.health.AddHediff(compProps.corpseHediff);
}
base.Notify_PawnDied(dinfo, culprit);
}
public override void PreRemoved()
{
pawn.MapHeld?.mapPawns.DeregisterShambler(pawn);
base.PreRemoved();
}
public override void PostRemoved()
{
base.PostRemoved();
if (pawn.Dead) return;
if (IsRising) CancelRising();
if (pawn.IsMutant)
{
if (pawn.mutant.HasTurned) pawn.mutant.Revert();
else pawn.mutant = null;
}
}
public override IEnumerable<Gizmo> GetGizmos()
{
foreach (Gizmo gizmo in base.GetGizmos())
{
yield return gizmo;
}
if (DebugSettings.ShowDevGizmos && pawn.Downed && !IsRising)
{
var command_Action = new Command_Action
{
defaultLabel = "Self Raise",
action = () => StartRising()
};
yield return command_Action;
}
}
public override string GetInspectString()
{
if (ShouldSelfRaise()) return "ShamblerRegenerating".Translate();
if (IsRising) return "ShamblerRising".Translate();
if (pawn.CurJobDef == JobDefOf.Wait_Wander || pawn.CurJobDef == JobDefOf.Wait_MaintainPosture) return "ShamblerStanding".Translate();
if (pawn.CurJobDef == JobDefOf.GotoWander || pawn.CurJobDef == JobDefOf.Goto) return "ShamblerShuffling".Translate();
return "";
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref alertTimer, "alertTimer", 0f);
Scribe_Values.Look(ref nextTargetCheckTick, "nextTargetCheckTick", 0);
Scribe_References.Look(ref alertedTarget, "alertedTarget");
Scribe_Values.Look(ref resurrectTimer, "resurrectTimer", 0f);
Scribe_Values.Look(ref selfRaiseTimer, "selfRaiseTimer", 0f);
Scribe_Values.Look(ref headRotation, "headRotation", 0f);
}
}
}

View File

@@ -0,0 +1,147 @@
using RimWorld;
using Verse;
using UnityEngine;
using System.Linq;
namespace ArachnaeSwarm
{
public class Hediff_NecroticVirus : HediffWithComps
{
private const int EffectInterval = 600;
// 用于存储攻击者派系的字段
private Faction casterFaction;
// 属性来获取我们的自定义Comp
private HediffComp_NecroticTransformation PropsComp => this.TryGetComp<HediffComp_NecroticTransformation>();
public override void PostAdd(DamageInfo? dinfo)
{
base.PostAdd(dinfo);
if (dinfo.HasValue && dinfo.Value.Instigator != null)
{
this.casterFaction = dinfo.Value.Instigator.Faction;
}
}
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
{
base.Notify_PawnDied(dinfo, culprit);
TransformToMutant();
}
public override void PostTick()
{
base.PostTick();
if (pawn.IsHashIntervalTick(EffectInterval) && pawn.Spawned)
{
ShowVirusEffects();
}
}
private void TransformToMutant()
{
var comp = PropsComp;
if (comp == null || comp.Props.mutantDef == null)
{
Log.Error($"[NecroticVirus] HediffComp_NecroticTransformation or its mutantDef is not configured in XML for {this.def.defName}.");
return;
}
// 检查严重性是否达到XML中配置的阈值
if (this.Severity < comp.Props.triggerSeverity)
{
return;
}
try
{
if (pawn.Corpse == null || pawn.Corpse.Destroyed)
{
return;
}
Map map = pawn.Corpse.Map;
IntVec3 position = pawn.Corpse.Position;
// 使用我们自己的、更安全的检查方法
if (!NecroticTransformationUtility.CanResurrect(pawn.Corpse))
{
Log.Warning($"[NecroticVirus] Pawn {pawn.LabelShort} does not meet conditions for resurrection.");
return;
}
// **优先使用攻击者的派系,如果没有,则执行备用逻辑**
Faction faction = this.casterFaction ?? GetHostileFaction();
// **调用我们自己的工具方法传入从XML获取的mutantDef**
NecroticTransformationUtility.ResurrectAsCustomMutant(pawn, comp.Props.mutantDef, faction);
// **关键修复在成功转化后立即移除导致转化的Hediff本身防止其残留**
pawn.health.RemoveHediff(this);
// 添加转化特效
FleckMaker.ThrowSmoke(position.ToVector3Shifted(), map, 1.5f);
FleckMaker.ThrowDustPuff(position.ToVector3Shifted(), map, 1.2f);
// 发送转化消息
if (PawnUtility.ShouldSendNotificationAbout(pawn))
{
Messages.Message(
"NecroticVirus_TransformationMessage".Translate(pawn.LabelShortCap, pawn.LabelShortCap),
new LookTargets(position, map),
MessageTypeDefOf.NegativeEvent
);
}
}
catch (System.Exception ex)
{
Log.Error($"[NecroticVirus] Error during transformation: {ex}");
}
}
private Faction GetHostileFaction()
{
if (pawn.Faction != null && pawn.Faction.HostileTo(Faction.OfPlayer))
{
return pawn.Faction;
}
Faction entitiesFaction = Find.FactionManager.AllFactions.FirstOrDefault(f => f.def.defName == "Entities");
if (entitiesFaction != null && !entitiesFaction.defeated)
{
return entitiesFaction;
}
return Find.FactionManager.RandomEnemyFaction(allowNonHumanlike: true, allowHidden: false, allowDefeated: false);
}
private void ShowVirusEffects()
{
if (pawn == null || !pawn.Spawned) return;
Vector3 pos = pawn.DrawPos;
Map map = pawn.Map;
float sizeMultiplier = 1f;
if (CurStageIndex == 1) sizeMultiplier = 1.2f;
if (CurStageIndex == 2) sizeMultiplier = 1.5f;
FleckMaker.ThrowMicroSparks(pos, map);
FleckMaker.ThrowDustPuff(pos, map, 0.8f * sizeMultiplier);
}
public override string TipStringExtra
{
get
{
return base.TipStringExtra + "\n" + "NecroticVirus_EffectTip".Translate();
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_References.Look(ref this.casterFaction, "casterFaction");
}
}
}

View File

@@ -0,0 +1,259 @@
using RimWorld;
using System.Text;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class Building_Morphable : Building
{
private CompMorphable compMorphable;
private CompRefuelableNutrition compRefuelable;
private Effecter researchEffecter;
public float virtualRest; // Public for external access
private bool forceSleep;
public float VirtualRestMax => 1.0f;
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref virtualRest, "virtualRest", 1f);
Scribe_Values.Look(ref forceSleep, "forceSleep", false);
}
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
this.compMorphable = GetComp<CompMorphable>();
this.compRefuelable = GetComp<CompRefuelableNutrition>();
}
protected override void Tick()
{
base.Tick();
if (compMorphable?.StoredPawn == null)
{
StopResearchEffect();
return;
}
Pawn pawn = compMorphable.StoredPawn;
var needs = pawn.needs;
if (needs == null)
{
return;
}
// --- 饮食逻辑 ---
if (needs.food != null && compRefuelable != null)
{
if (compRefuelable.HasFuel)
{
// 模拟消耗
compRefuelable.ConsumeFuel(pawn.needs.food.FoodFallPerTick);
}
else
{
Messages.Message("PawnTransformer_OutOfFuel".Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.NegativeEvent);
this.Destroy(DestroyMode.Vanish);
return;
}
}
// --- 休息与研究逻辑 ---
if (needs.rest != null)
{
if (needs.rest.CurLevel <= 0)
{
forceSleep = true;
}
if (forceSleep && needs.rest.CurLevel >= needs.rest.MaxLevel)
{
forceSleep = false;
}
}
TimeAssignmentDef assignment = pawn.timetable?.CurrentAssignment ?? TimeAssignmentDefOf.Anything;
if (forceSleep || assignment == TimeAssignmentDefOf.Sleep || assignment == TimeAssignmentDefOf.Joy)
{
// 休眠期 (只有在强制休眠或日程为睡眠/娱乐时才恢复)
if (needs.rest != null)
{
virtualRest = Mathf.Min(VirtualRestMax, virtualRest + (Need_Rest.BaseRestGainPerTick * ((CompProperties_Morphable)compMorphable.props).restGainMultiplier)); // 使用XML中定义的乘数
}
StopResearchEffect();
}
else // 工作或任意时间 (只要不在休息/娱乐,就下降)
{
// 使用固定的、预估的下降率
if (virtualRest > 0)
{
virtualRest -= (0.66f / 60000f);
}
ResearchProjectDef currentProj = Find.ResearchManager.GetProject();
if (currentProj != null)
{
float researchSpeed = pawn.GetStatValue(StatDefOf.ResearchSpeed);
researchSpeed *= this.GetStatValue(StatDefOf.ResearchSpeedFactor);
Find.ResearchManager.ResearchPerformed(researchSpeed, pawn);
pawn.skills.Learn(SkillDefOf.Intellectual, 0.1f, false);
StartResearchEffect();
}
else
{
StopResearchEffect();
}
}
}
private void StartResearchEffect()
{
if (researchEffecter == null)
{
researchEffecter = EffecterDefOf.Research.Spawn();
}
researchEffecter.EffectTick(this, TargetInfo.Invalid);
}
private void StopResearchEffect()
{
if (researchEffecter != null)
{
researchEffecter.Cleanup();
researchEffecter = null;
}
}
public override string Label
{
get
{
if (compMorphable?.StoredPawn != null)
{
return $"{base.Label} ({compMorphable.StoredPawn.LabelShort})";
}
return base.Label;
}
}
public override string GetInspectString()
{
List<string> inspectStrings = new List<string>();
if (compMorphable?.StoredPawn != null)
{
Pawn pawn = compMorphable.StoredPawn;
// 1. 活动状态 (置于首位)
TimeAssignmentDef assignment = pawn.timetable?.CurrentAssignment ?? TimeAssignmentDefOf.Anything;
bool isWorkingTime = !forceSleep && (assignment == TimeAssignmentDefOf.Work || assignment == TimeAssignmentDefOf.Anything);
string activity;
if (isWorkingTime)
{
ResearchProjectDef currentProj = Find.ResearchManager.GetProject();
if (currentProj != null)
{
activity = "Activity".Translate() + ": " + "Researching".Translate() + $" ({currentProj.LabelCap})";
}
else
{
activity = "Activity".Translate() + ": " + "Idle".Translate();
}
}
else
{
activity = "Activity".Translate() + ": " + "Sleeping".Translate();
}
inspectStrings.Add(activity);
// 2. 智识技能
SkillRecord intellectualSkill = pawn.skills?.GetSkill(SkillDefOf.Intellectual);
if (intellectualSkill != null)
{
inspectStrings.Add($"{SkillDefOf.Intellectual.LabelCap}: {intellectualSkill.Level} ({intellectualSkill.XpProgressPercent:P0})");
}
// 3. 休息需求
Need_Rest restNeed = pawn.needs?.rest;
if (restNeed != null)
{
inspectStrings.Add($"{restNeed.LabelCap}: {virtualRest.ToStringPercent()}");
}
}
// 基础信息如HP最后添加
string baseString = base.GetInspectString();
if (!baseString.NullOrEmpty())
{
inspectStrings.Add(baseString);
}
return string.Join("\n", inspectStrings);
}
public override void PostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
{
base.PostApplyDamage(dinfo, totalDamageDealt);
if (dinfo.Amount <= 0 || this.Destroyed)
{
return;
}
if (compMorphable?.StoredPawn != null)
{
ForceRevert(dinfo);
}
}
private void ForceRevert(DamageInfo dinfo)
{
Pawn pawn = compMorphable.StoredPawn;
Map map = this.Map;
IntVec3 position = this.Position;
compMorphable.SetStoredPawn(null);
float damageProportion = dinfo.Amount / this.def.statBases.GetStatValueFromList(StatDefOf.MaxHitPoints, 1f);
float pawnDamage = pawn.MaxHitPoints * damageProportion;
DamageInfo pawnDinfo = new DamageInfo(dinfo.Def, pawnDamage, dinfo.ArmorPenetrationInt, dinfo.Angle, dinfo.Instigator, null, dinfo.Weapon, dinfo.Category, dinfo.IntendedTarget);
this.Destroy(DestroyMode.Vanish);
GenSpawn.Spawn(pawn, position, map, WipeMode.Vanish);
PawnComponentsUtility.AddComponentsForSpawn(pawn);
pawn.TakeDamage(pawnDinfo);
Messages.Message("PawnTransformer_ForcedRevert".Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.NegativeEvent);
}
public override void Destroy(DestroyMode mode)
{
if (researchEffecter != null)
{
researchEffecter.Cleanup();
researchEffecter = null;
}
if (this.Spawned && compMorphable != null && compMorphable.StoredPawn != null)
{
Pawn pawn = compMorphable.StoredPawn;
GenSpawn.Spawn(pawn, this.Position, this.Map, WipeMode.Vanish);
PawnComponentsUtility.AddComponentsForSpawn(pawn);
if (mode == DestroyMode.KillFinalize)
{
Messages.Message("PawnTransformer_BuildingDestroyed".Translate(pawn.Named("PAWN"), this.Named("BUILDING")), pawn, MessageTypeDefOf.NegativeEvent);
}
}
base.Destroy(mode);
}
}
}

View File

@@ -0,0 +1,73 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompAbilityEffect_Transform : CompAbilityEffect
{
public new CompProperties_AbilityTransform Props => (CompProperties_AbilityTransform)props;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn pawn = parent.pawn;
// 检查空间
foreach (var cell in GenRadial.RadialCellsAround(pawn.Position, Props.buildingDef.Size.x / 2f, true))
{
if (!cell.InBounds(pawn.Map) || !cell.Walkable(pawn.Map) || cell.GetEdifice(pawn.Map) != null)
{
Messages.Message("PawnTransformer_SpaceBlocked".Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.RejectInput, false);
// 重置技能冷却
parent.StartCooldown(0);
return;
}
}
// 执行转换
IntVec3 position = pawn.Position;
Map map = pawn.Map;
pawn.DeSpawn(DestroyMode.Vanish);
Building building = (Building)GenSpawn.Spawn(Props.buildingDef, position, map, WipeMode.Vanish);
building.SetFaction(pawn.Faction);
var newMorphComp = building.GetComp<CompMorphable>();
if (newMorphComp != null)
{
newMorphComp.SetStoredPawn(pawn);
}
// 同步需求值
var buildingMorphable = building as Building_Morphable;
var refuelableComp = building.GetComp<CompRefuelableNutrition>();
if (buildingMorphable != null && refuelableComp != null && pawn.needs != null)
{
if(pawn.needs.food != null)
{
refuelableComp.Refuel(refuelableComp.Props.fuelCapacity * pawn.needs.food.CurLevelPercentage);
}
if(pawn.needs.rest != null)
{
buildingMorphable.virtualRest = buildingMorphable.VirtualRestMax * pawn.needs.rest.CurLevelPercentage;
}
}
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
// 这个技能只应该对自己释放
if (target.Pawn != parent.pawn)
{
if (throwMessages)
{
Messages.Message("AbilityCannotBeUsedOnOthers".Translate(), MessageTypeDefOf.RejectInput, false);
}
return false;
}
return base.Valid(target, throwMessages);
}
}
}

View File

@@ -0,0 +1,80 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class CompMorphable : ThingComp
{
private Pawn storedPawn;
public bool wasEjectedForFuel = false;
public Pawn StoredPawn => storedPawn;
public void SetStoredPawn(Pawn pawn)
{
this.storedPawn = pawn;
}
public override void PostExposeData()
{
base.PostExposeData();
Scribe_References.Look(ref storedPawn, "storedPawn", false);
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
if (parent.Faction == Faction.OfPlayer && storedPawn != null)
{
yield return new Command_Action
{
defaultLabel = "恢复人形",
defaultDesc = "将此建筑恢复为人形。",
icon = TexCommand.ReleaseAnimals, // TODO: Replace with a proper icon
action = () => { TransformBackToPawn(); }
};
}
}
private void TransformBackToPawn()
{
Building building = (Building)this.parent;
Map map = building.Map;
// 同步燃料到食物
var refuelableComp = building.GetComp<CompRefuelableNutrition>();
var buildingMorphable = building as Building_Morphable;
var needs = storedPawn.needs;
if (refuelableComp != null && needs?.food != null)
{
needs.food.CurLevelPercentage = refuelableComp.Fuel / refuelableComp.Props.fuelCapacity;
}
if (buildingMorphable != null && needs?.rest != null)
{
needs.rest.CurLevelPercentage = buildingMorphable.virtualRest / buildingMorphable.VirtualRestMax;
}
// 如果是因为燃料耗尽而被弹出清空Pawn的食物需求
if(wasEjectedForFuel && needs?.food != null)
{
needs.food.CurLevel = 0;
}
// 移除建筑
building.DeSpawn(DestroyMode.Vanish);
// 重新生成Pawn
GenSpawn.Spawn(storedPawn, building.Position, map, WipeMode.Vanish);
// 重新初始化Pawn在地图上所需的组件
PawnComponentsUtility.AddComponentsForSpawn(storedPawn);
// 选中Pawn
if (Find.Selector.IsSelected(building))
{
Find.Selector.Select(storedPawn);
}
}
}
}

View File

@@ -0,0 +1,15 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityTransform : CompProperties_AbilityEffect
{
public ThingDef buildingDef;
public CompProperties_AbilityTransform()
{
compClass = typeof(CompAbilityEffect_Transform);
}
}
}

View File

@@ -0,0 +1,15 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_Morphable : CompProperties
{
public float restGainMultiplier = 1f; // Default to 1.0 if not specified in XML
public CompProperties_Morphable()
{
compClass = typeof(CompMorphable);
}
}
}

View File

@@ -0,0 +1,83 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public static class NecroticTransformationUtility
{
/// <summary>
/// 检查一个尸体是否可以被我们的逻辑转化为变异体。
/// 这是对原版 MutantUtility.CanResurrectAsShambler 的复制,但移除了对 canBecomeShambler 的检查。
/// </summary>
public static bool CanResurrect(Corpse corpse, bool ignoreIndoors = false)
{
// 只保留最核心、最必要的检查,移除所有可能导致不稳定的条件
if (corpse?.InnerPawn == null) return false;
if (!corpse.InnerPawn.RaceProps.IsFlesh) return false;
return true;
}
/// <summary>
/// 将一个Pawn复活为指定的自定义变异体.
/// 这个方法是模仿原版 MutantUtility.ResurrectAsShambler,
/// 但允许传入一个自定义的 MutantDef.
/// </summary>
public static void ResurrectAsCustomMutant(Pawn pawn, MutantDef mutantDef, Faction faction = null, int lifespanTicks = -1)
{
if (pawn?.Corpse == null || mutantDef == null)
{
return;
}
RotStage rotStage = pawn.Corpse.GetRotStage();
// 创建并附加Pawn_MutantTracker使用我们从XML传入的mutantDef
pawn.mutant = new Pawn_MutantTracker(pawn, mutantDef, rotStage);
// **调用原版健康再生方法此方法会读取MutantDef中的配置如removeAllInjuries并执行**
MutantUtility.RegenerateHealth(pawn);
// 添加变异体核心Hediff
Hediff hediff = pawn.health.AddHediff(mutantDef.hediff);
// 如果是我们自己的可配置变异体Hediff则调用其上升动画
if (hediff is Hediff_ConfigurableMutant configurableMutant)
{
configurableMutant.StartRising(lifespanTicks);
}
// 设置生命周期
var disappearsComp = hediff.TryGetComp<HediffComp_DisappearsAndKills>();
if (disappearsComp != null)
{
if (lifespanTicks > 0)
{
disappearsComp.disappearsAfterTicks = lifespanTicks;
disappearsComp.ticksToDisappear = lifespanTicks;
}
else
{
disappearsComp.disabled = true;
}
}
// 如果没有提供派系,则尝试使用变异体定义的默认派系
if (faction == null && mutantDef.defaultFaction != null)
{
faction = Find.FactionManager.FirstFactionOfDef(mutantDef.defaultFaction);
}
// 设置派系
if (faction != null && pawn.Faction != faction)
{
pawn.SetFaction(faction);
}
// 移除 pawn.mutant.Turn(clearLord: true);
// Turn() 方法应该由 Hediff_Shambler.FinishRising() 在复活过程的最后阶段调用,
// 而不应该由我们在这里手动调用。
// Hediff_Shambler 的 StartRising() 会启动这个流程。
}
}
}

View File

@@ -0,0 +1,187 @@
using RimWorld;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class OPToxicGas : Gas
{
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, true);
this.destroyTick = Find.TickManager.TicksGame + this.def.gas.expireSeconds.RandomInRange.SecondsToTicks();
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look<int>(ref this.destroyTick, "destroyTick", 0, false);
}
protected override void Tick()
{
bool flag = this.destroyTick <= Find.TickManager.TicksGame;
if (flag)
{
this.Destroy(DestroyMode.Vanish);
}
this.graphicRotation += this.graphicRotationSpeed;
bool flag2 = !base.Destroyed && Find.TickManager.TicksGame % OPToxicDefGetValue.OPToxicGetSevUpVal(this.def) == 0;
if (flag2)
{
Map map = base.Map;
IntVec3 position = base.Position;
List<Thing> thingList = position.GetThingList(map);
bool flag3 = thingList.Count > 0;
if (flag3)
{
for (int i = 0; i < thingList.Count; i++)
{
bool flag4 = thingList[i] is Pawn && !(thingList[i] as Pawn).RaceProps.IsMechanoid && thingList[i].Position == position;
if (flag4)
{
this.DoOPToxicGas(this, thingList[i]);
}
}
}
}
}
public void DoOPToxicGas(Thing Gas, Thing targ)
{
Pawn pawn = targ as Pawn;
bool flag = pawn != null && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Breathing);
if (flag)
{
HediffDef namedSilentFail = DefDatabase<HediffDef>.GetNamedSilentFail(OPToxicDefGetValue.OPToxicGetHediff(Gas.def));
bool flag2 = namedSilentFail != null;
if (flag2)
{
Pawn_HealthTracker health = pawn.health;
bool flag3 = health == null;
Hediff hediff;
if (flag3)
{
hediff = null;
}
else
{
HediffSet hediffSet = health.hediffSet;
hediff = ((hediffSet != null) ? hediffSet.GetFirstHediffOfDef(namedSilentFail, false) : null);
}
float num = 1f - pawn.GetStatValue(StatDefOf.ToxicResistance, true, -1);
float num2 = OPToxicDefGetValue.OPToxicGetSev(Gas.def);
bool flag4 = num2 < 0.01f;
if (flag4)
{
num2 = 0.01f;
}
float num3 = Rand.Range(0.01f * num, num2 * num);
bool flag5 = hediff != null && num3 > 0f;
if (flag5)
{
hediff.Severity += num3;
}
else
{
Hediff hediff2 = HediffMaker.MakeHediff(namedSilentFail, pawn, null);
hediff2.Severity = num3;
pawn.health.AddHediff(hediff2, null, null, null);
}
}
}
}
}
public class OPToxicDefGetValue
{
public static string OPToxicGetHediff(ThingDef thingdef)
{
bool flag = thingdef.HasModExtension<OPToxicDefs>();
string result;
if (flag)
{
result = thingdef.GetModExtension<OPToxicDefs>().OPToxicHediff;
}
else
{
result = null;
}
return result;
}
public static float OPToxicGetSev(ThingDef thingdef)
{
bool flag = thingdef.HasModExtension<OPToxicDefs>();
float result;
if (flag)
{
result = thingdef.GetModExtension<OPToxicDefs>().OPToxicSeverity;
}
else
{
result = 0f;
}
return result;
}
public static int OPToxicGetSevUpVal(ThingDef thingdef)
{
bool flag = thingdef.HasModExtension<OPToxicDefs>();
int result;
if (flag)
{
result = thingdef.GetModExtension<OPToxicDefs>().OPSevUpTickPeriod;
}
else
{
result = 120;
}
return result;
}
}
public class OPToxicDefs : DefModExtension
{
public string OPToxicHediff;
public float OPToxicSeverity;
public int OPSevUpTickPeriod = 120;
}
public class DamageWorker_OPToxic : DamageWorker
{
public override void ExplosionStart(Explosion explosion, List<IntVec3> cellsToAffect)
{
bool flag = this.def.explosionHeatEnergyPerCell > float.Epsilon;
if (flag)
{
GenTemperature.PushHeat(explosion.Position, explosion.Map, this.def.explosionHeatEnergyPerCell * (float)cellsToAffect.Count);
}
FleckMaker.Static(explosion.Position, explosion.Map, FleckDefOf.ExplosionFlash, explosion.radius * 6f);
FleckMaker.Static(explosion.Position, explosion.Map, FleckDefOf.ExplosionFlash, explosion.radius * 6f);
this.ExplosionVisualEffectCenter(explosion);
}
public override DamageWorker.DamageResult Apply(DamageInfo dinfo, Thing victim)
{
DamageWorker.DamageResult damageResult = new DamageWorker.DamageResult();
bool flag = victim.def.category == ThingCategory.Pawn && victim.def.useHitPoints && dinfo.Def.harmsHealth;
if (flag)
{
float amount = dinfo.Amount;
damageResult.totalDamageDealt = (float)Mathf.Min(victim.HitPoints, GenMath.RoundRandom(amount));
victim.HitPoints -= Mathf.RoundToInt(damageResult.totalDamageDealt);
bool flag2 = victim.HitPoints <= 0;
if (flag2)
{
victim.HitPoints = 0;
victim.Kill(new DamageInfo?(dinfo), null);
}
}
return damageResult;
}
}
}

View File

@@ -0,0 +1,22 @@
using Verse;
using UnityEngine;
namespace ArachnaeSwarm
{
public class PawnRenderNodeWorker_AttachmentBody_NoFlight : PawnRenderNodeWorker_AttachmentBody
{
public override bool CanDrawNow(PawnRenderNode node, PawnDrawParms parms)
{
if (parms.pawn.Flying)
{
return false;
}
return base.CanDrawNow(node, parms);
}
public override Vector3 ScaleFor(PawnRenderNode node, PawnDrawParms parms)
{
return base.ScaleFor(node, parms);
}
}
}

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Reflection;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class BulletWithTrail : Bullet
{
private TrackingBulletDef trackingDefInt;
private int Fleck_MakeFleckTick;
private Vector3 lastTickPosition;
public TrackingBulletDef TrackingDef
{
get
{
if (trackingDefInt == null)
{
trackingDefInt = def.GetModExtension<TrackingBulletDef>();
if (trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
return trackingDefInt;
}
}
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
{
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
lastTickPosition = origin;
}
protected override void Tick()
{
base.Tick();
// 处理拖尾特效
if (TrackingDef != null && TrackingDef.tailFleckDef != null)
{
Fleck_MakeFleckTick++;
if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks)
{
if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax))
{
Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks;
}
Map map = base.Map;
int randomInRange = TrackingDef.fleckMakeFleckNum.RandomInRange;
Vector3 currentPosition = base.ExactPosition;
Vector3 previousPosition = lastTickPosition;
for (int i = 0; i < randomInRange; i++)
{
float num = (currentPosition - previousPosition).AngleFlat();
float velocityAngle = TrackingDef.fleckAngle.RandomInRange + num;
float randomInRange2 = TrackingDef.fleckScale.RandomInRange;
float randomInRange3 = TrackingDef.fleckSpeed.RandomInRange;
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, randomInRange2);
dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange;
dataStatic.velocityAngle = velocityAngle;
dataStatic.velocitySpeed = randomInRange3;
map.flecks.CreateFleck(dataStatic);
}
}
}
lastTickPosition = base.ExactPosition;
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref Fleck_MakeFleckTick, "Fleck_MakeFleckTick", 0);
Scribe_Values.Look(ref lastTickPosition, "lastTickPosition", Vector3.zero);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
if (this.trackingDefInt == null)
{
this.trackingDefInt = this.def.GetModExtension<TrackingBulletDef>();
if (this.trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef is null for projectile {this.def.defName} after PostLoadInit. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
public class ExplosiveTrackingBulletDef : DefModExtension
{
public float explosionRadius = 1.9f;
public DamageDef damageDef;
public int explosionDelay = 0;
public SoundDef soundExplode;
public FleckDef preExplosionFlash;
public ThingDef postExplosionSpawnThingDef;
public float postExplosionSpawnChance = 0f;
public int postExplosionSpawnThingCount = 1;
public GasType? gasType; // 修改为可空类型
public ThingDef postExplosionSpawnThingDefWater; // 新增
public ThingDef preExplosionSpawnThingDef; // 新增
public float preExplosionSpawnChance = 0f; // 新增
public int preExplosionSpawnThingCount = 0; // 新增
public float screenShakeFactor = 1f; // 新增
public bool applyDamageToExplosionCellsNeighbors = false;
public bool doExplosionDamageAfterThingDestroyed = false;
public float preExplosionSpawnMinMeleeThreat = -1f;
public float explosionChanceToStartFire = 0f; // 从bool改为float并设置默认值
public bool explosionDamageFalloff = false;
public bool doExplosionVFX = true;
}
}

View File

@@ -0,0 +1,93 @@
using Verse;
using RimWorld;
using System.Collections.Generic;
namespace ArachnaeSwarm
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>XML<4D><4C> <projectile> <20>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
/// </summary>
public class ProjectileProperties_ConfigurableHellsphereCannon : ProjectileProperties
{
// --- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> explosionChanceToStartFire ---
// ʹ<><CAB9> 'new' <20>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><E6BBBB><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>ֶ<EFBFBD>
public new float explosionRadius = 4.9f;
public new float explosionChanceToStartFire = 0f; // <--- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>XML<4D><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public new bool applyDamageToExplosionCellsNeighbors = false;
public new ThingDef preExplosionSpawnThingDef = null;
public new float preExplosionSpawnChance = 0f;
public new int preExplosionSpawnThingCount = 1;
public new ThingDef postExplosionSpawnThingDef = null;
public new float postExplosionSpawnChance = 0f;
public new int postExplosionSpawnThingCount = 1;
public new GasType? postExplosionGasType = null;
public new float screenShakeFactor = 1f;
public new ThingDef postExplosionSpawnThingDefWater = null;
public new ThingDef postExplosionSpawnSingleThingDef = null;
public new ThingDef preExplosionSpawnSingleThingDef = null;
// <20><>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>ֶΣ<D6B6><CEA3><EFBFBD><EFBFBD><EFBFBD>Ҫ 'new' <20>ؼ<EFBFBD><D8BC><EFBFBD>
public SoundDef explosionSound = null;
public bool damageFalloff = false;
public bool doVisualEffects = true;
public bool doSoundEffects = true;
public float? postExplosionGasRadiusOverride = null;
public int postExplosionGasAmount = 255;
public float? direction = null;
public FloatRange? affectedAngle = null;
public float excludeRadius = 0f;
public SimpleCurve flammabilityChanceCurve = null;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><E0A3AC>XML<4D>е<EFBFBD> <thingClass> ָ<><D6B8><EFBFBD><EFBFBD>
/// </summary>
public class Projectile_ConfigurableHellsphereCannon : Projectile
{
public ProjectileProperties_ConfigurableHellsphereCannon Props => (ProjectileProperties_ConfigurableHellsphereCannon)def.projectile;
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
Map map = base.Map;
base.Impact(hitThing, blockedByShield);
GenExplosion.DoExplosion(
center: base.Position,
map: map,
radius: Props.explosionRadius,
damType: base.DamageDef,
instigator: launcher,
damAmount: DamageAmount,
armorPenetration: ArmorPenetration,
explosionSound: Props.explosionSound,
weapon: equipmentDef,
projectile: def,
intendedTarget: intendedTarget.Thing,
postExplosionSpawnThingDef: Props.postExplosionSpawnThingDef,
postExplosionSpawnChance: Props.postExplosionSpawnChance,
postExplosionSpawnThingCount: Props.postExplosionSpawnThingCount,
postExplosionGasType: Props.postExplosionGasType,
postExplosionGasRadiusOverride: Props.postExplosionGasRadiusOverride,
postExplosionGasAmount: Props.postExplosionGasAmount,
applyDamageToExplosionCellsNeighbors: Props.applyDamageToExplosionCellsNeighbors,
preExplosionSpawnThingDef: Props.preExplosionSpawnThingDef,
preExplosionSpawnChance: Props.preExplosionSpawnChance,
preExplosionSpawnThingCount: Props.preExplosionSpawnThingCount,
// --- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>ֶ<EFBFBD> ---
chanceToStartFire: Props.explosionChanceToStartFire, // <--- <20><><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><CBB4><EFBFBD>
damageFalloff: Props.damageFalloff,
direction: Props.direction,
affectedAngle: Props.affectedAngle,
doVisualEffects: Props.doVisualEffects,
propagationSpeed: base.DamageDef.expolosionPropagationSpeed,
excludeRadius: Props.excludeRadius,
doSoundEffects: Props.doSoundEffects,
postExplosionSpawnThingDefWater: Props.postExplosionSpawnThingDefWater,
screenShakeFactor: Props.screenShakeFactor,
flammabilityChanceCurve: Props.flammabilityChanceCurve,
postExplosionSpawnSingleThingDef: Props.postExplosionSpawnSingleThingDef,
preExplosionSpawnSingleThingDef: Props.preExplosionSpawnSingleThingDef
);
}
}
}

View File

@@ -0,0 +1,194 @@
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class CruiseMissileProperties : DefModExtension
{
public DamageDef customDamageDef;
public int customDamageAmount = 5;
public float customExplosionRadius = 1.1f;
public SoundDef customSoundExplode;
public bool useSubExplosions = true;
public int subExplosionCount = 3;
public float subExplosionRadius = 1.9f;
public int subExplosionDamage = 30;
public float subExplosionSpread = 6f;
public DamageDef subDamageDef;
public SoundDef subSoundExplode;
// 新增的弹道配置参数
public float bezierArcHeightFactor = 0.05f; // 贝塞尔曲线高度因子
public float bezierMinArcHeight = 2f; // 贝塞尔曲线最小高度
public float bezierMaxArcHeight = 6f; // 贝塞尔曲线最大高度
public float bezierHorizontalOffsetFactor = 0.1f; // 贝塞尔曲线水平偏移因子
public float bezierSideOffsetFactor = 0.2f; // 贝塞尔曲线侧向偏移因子
public float bezierRandomOffsetScale = 0.5f; // 贝塞尔曲线随机偏移缩放
}
public class Projectile_CruiseMissile : Projectile_Explosive
{
private CruiseMissileProperties settings;
private bool flag2;
private Vector3 Randdd;
private Vector3 position2;
public Vector3 ExPos;
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
settings = def.GetModExtension<CruiseMissileProperties>() ?? new CruiseMissileProperties();
}
private void RandFactor()
{
// 调整随机范围用于控制C形弹道的随机偏移
Randdd = new Vector3(
Rand.Range(-settings.bezierRandomOffsetScale, settings.bezierRandomOffsetScale), // X轴的随机偏移
Rand.Range(0f, 0f), // Y轴高度不进行随机保持平稳
Rand.Range(-settings.bezierRandomOffsetScale, settings.bezierRandomOffsetScale) // Z轴的随机偏移
);
flag2 = true;
}
public Vector3 BPos(float t)
{
if (!flag2) RandFactor();
// 计算水平距离
float horizontalDistance = Vector3.Distance(new Vector3(origin.x, 0, origin.z),
new Vector3(destination.x, 0, destination.z));
// 动态调整控制点高度使其更扁平使用XML配置的高度因子
float arcHeight = Mathf.Clamp(horizontalDistance * settings.bezierArcHeightFactor, settings.bezierMinArcHeight, settings.bezierMaxArcHeight);
// 计算从起点到终点的方向向量
Vector3 direction = (destination - origin).normalized;
// 计算垂直于方向向量的水平向量用于侧向偏移确保C形弯曲方向一致
Vector3 perpendicularDirection = Vector3.Cross(direction, Vector3.up).normalized;
// 调整控制点以形成扁平 C 形使用XML配置的偏移因子
// P1: 在起点附近,向前偏移,向上偏移,并向一侧偏移
Vector3 p1 = origin + direction * horizontalDistance * settings.bezierHorizontalOffsetFactor + Vector3.up * arcHeight + perpendicularDirection * horizontalDistance * settings.bezierSideOffsetFactor + Randdd;
// P2: 在终点附近,向后偏移,向上偏移,并向同一侧偏移
Vector3 p2 = destination - direction * horizontalDistance * settings.bezierHorizontalOffsetFactor + Vector3.up * arcHeight + perpendicularDirection * horizontalDistance * settings.bezierSideOffsetFactor + Randdd;
return BezierCurve(origin, p1, p2, destination, t);
}
private Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
float u = 1 - t;
return u * u * u * p0
+ 3 * u * u * t * p1
+ 3 * u * t * t * p2
+ t * t * t * p3;
}
private IEnumerable<IntVec3> GetValidCells(Map map)
{
if (map == null || settings == null) yield break;
var cells = GenRadial.RadialCellsAround(
base.Position,
settings.subExplosionSpread,
false
).Where(c => c.InBounds(map));
var randomizedCells = cells.InRandomOrder().Take(settings.subExplosionCount);
foreach (var cell in randomizedCells)
{
yield return cell;
}
}
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
var map = base.Map;
base.Impact(hitThing, blockedByShield);
DoExplosion(
base.Position,
map,
settings.customExplosionRadius,
settings.customDamageDef,
settings.customDamageAmount,
settings.customSoundExplode
);
if (settings.useSubExplosions)
{
foreach (var cell in GetValidCells(map))
{
DoExplosion(
cell,
map,
settings.subExplosionRadius,
settings.subDamageDef,
settings.subExplosionDamage,
settings.subSoundExplode
);
}
}
}
private void DoExplosion(IntVec3 pos, Map map, float radius, DamageDef dmgDef, int dmgAmount, SoundDef sound)
{
GenExplosion.DoExplosion(
pos,
map,
radius,
dmgDef,
launcher,
dmgAmount,
ArmorPenetration,
sound
);
}
protected override void DrawAt(Vector3 position, bool flip = false)
{
position2 = BPos(DistanceCoveredFraction - 0.01f);
ExPos = position = BPos(DistanceCoveredFraction);
base.DrawAt(position, flip);
}
protected override void Tick()
{
if (intendedTarget.Thing is Pawn pawn && pawn.Spawned && !pawn.Destroyed)
{
if ((pawn.Dead || pawn.Downed) && DistanceCoveredFraction < 0.6f)
{
FindNextTarget(pawn.DrawPos);
}
destination = pawn.DrawPos;
}
base.Tick();
}
private void FindNextTarget(Vector3 center)
{
var map = base.Map;
if (map == null) return;
foreach (IntVec3 cell in GenRadial.RadialCellsAround(IntVec3.FromVector3(center), 7f, true))
{
if (!cell.InBounds(map)) continue;
Pawn target = cell.GetFirstPawn(map);
if (target != null && target.Faction.HostileTo(launcher?.Faction))
{
intendedTarget = target;
return;
}
}
intendedTarget = CellRect.CenteredOn(IntVec3.FromVector3(center), 7).RandomCell;
}
}
}

View File

@@ -0,0 +1,185 @@
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class Projectile_ExplosiveTrackingBullet : Projectile_TrackingBullet
{
private ExplosiveTrackingBulletDef explosiveDefInt;
private int ticksToDetonation;
public ExplosiveTrackingBulletDef ExplosiveDef
{
get
{
if (explosiveDefInt == null)
{
explosiveDefInt = def.GetModExtension<ExplosiveTrackingBulletDef>();
if (explosiveDefInt == null)
{
Log.ErrorOnce($"ExplosiveTrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345679);
this.explosiveDefInt = new ExplosiveTrackingBulletDef();
}
}
return explosiveDefInt;
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref this.ticksToDetonation, "ticksToDetonation", 0, false);
}
protected override void Tick()
{
base.Tick(); // Call base Projectile_TrackingBullet Tick logic
bool flag = this.ticksToDetonation > 0;
if (flag)
{
this.ticksToDetonation--;
bool flag2 = this.ticksToDetonation <= 0;
if (flag2)
{
this.Explode();
}
}
}
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
bool flag = hitThing == null || blockedByShield || ExplosiveDef.explosionDelay == 0; // Use ExplosiveDef for explosionDelay
if (flag)
{
this.Explode();
}
else
{
this.landed = true;
this.ticksToDetonation = ExplosiveDef.explosionDelay; // Use ExplosiveDef for explosionDelay
GenExplosion.NotifyNearbyPawnsOfDangerousExplosive(this, ExplosiveDef.damageDef ?? DamageDefOf.Bomb, this.launcher.Faction, this.launcher); // Use ExplosiveDef for damageDef
// 停止追踪并清空速度,确保子弹停止移动
this.homing = false;
this.curSpeed = Vector3.zero;
}
}
protected virtual void Explode()
{
Map map = base.Map;
// ModExtension_Cone modExtension = this.def.GetModExtension<ModExtension_Cone>(); // Not used in this explosive logic
this.DoExplosion(map); // Call the helper DoExplosion with map
// Cone explosion logic (if needed, based on ModExtension_Cone) - Currently not implemented for this class
// bool flag = modExtension != null;
// if (flag)
// {
// ProjectileProperties projectile = this.def.projectile;
// ModExtension_Cone modExtension_Cone = modExtension;
// IntVec3 position = base.Position;
// Map map2 = map;
// Quaternion exactRotation = this.ExactRotation;
// DamageDef damageDef = projectile.damageDef;
// Thing launcher = base.Launcher;
// int damageAmount = this.DamageAmount;
// float armorPenetration = this.ArmorPenetration;
// SoundDef soundExplode = this.def.projectile.soundExplode;
// ThingDef equipmentDef = this.equipmentDef;
// ThingDef def = this.def;
// Thing thing = this.intendedTarget.Thing;
// ThingDef postExplosionSpawnThingDef = null;
// float postExplosionSpawnChance = 0f;
// int postExplosionSpawnThingCount = 1;
// float screenShakeFactor = this.def.projectile.screenShakeFactor;
// modExtension_Cone.DoConeExplosion(position, map2, exactRotation, damageDef, launcher, damageAmount, armorPenetration, soundExplode, equipmentDef, def, thing, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, null, null, 255, false, null, 0f, 1, 0f, false, null, null, 1f, 0f, null, screenShakeFactor, null, null);
// }
// Explosion effect (if needed, based on def.projectile.explosionEffect) - Currently not implemented for this class
// bool flag2 = this.def.projectile.explosionEffect != null;
// if (flag2)
// {
// Effecter effecter = this.def.projectile.explosionEffect.Spawn();
// bool flag3 = this.def.projectile.explosionEffectLifetimeTicks != 0;
// if (flag3)
// {
// map.effecterMaintainer.AddEffecterToMaintain(effecter, base.Position.ToVector3().ToIntVec3(), this.def.projectile.explosionEffectLifetimeTicks);
// }
// else
// {
// effecter.Trigger(new TargetInfo(base.Position, map, false), new TargetInfo(base.Position, map, false), -1);
// effecter.Cleanup();
// }
// }
this.Destroy(DestroyMode.Vanish);
}
protected void DoExplosion(Map map)
{
IntVec3 position = base.Position;
float explosionRadius = ExplosiveDef.explosionRadius; // Use ExplosiveDef for explosionRadius
DamageDef damageDef = ExplosiveDef.damageDef ?? DamageDefOf.Bomb; // Use ExplosiveDef for damageDef
Thing launcher = this.launcher;
int damageAmount = this.DamageAmount;
float armorPenetration = this.ArmorPenetration;
SoundDef soundExplode = ExplosiveDef.soundExplode; // Use ExplosiveDef for soundExplode
ThingDef equipmentDef = this.equipmentDef;
ThingDef def = this.def; // This is the projectile's ThingDef
Thing thing = this.intendedTarget.Thing;
ThingDef postExplosionSpawnThingDef = ExplosiveDef.postExplosionSpawnThingDef; // Use ExplosiveDef for postExplosionSpawnThingDef
ThingDef postExplosionSpawnThingDefWater = ExplosiveDef.postExplosionSpawnThingDefWater; // Use ExplosiveDef for postExplosionSpawnThingDefWater
float postExplosionSpawnChance = ExplosiveDef.postExplosionSpawnChance; // Use ExplosiveDef for postExplosionSpawnChance
int postExplosionSpawnThingCount = ExplosiveDef.postExplosionSpawnThingCount; // Use ExplosiveDef for postExplosionSpawnThingCount
GasType? postExplosionGasType = ExplosiveDef.gasType; // Use ExplosiveDef for gasType
ThingDef preExplosionSpawnThingDef = ExplosiveDef.preExplosionSpawnThingDef; // Use ExplosiveDef for preExplosionSpawnThingDef
float preExplosionSpawnChance = ExplosiveDef.preExplosionSpawnChance; // Use ExplosiveDef for preExplosionSpawnChance
int preExplosionSpawnThingCount = ExplosiveDef.preExplosionSpawnThingCount; // Use ExplosiveDef for preExplosionSpawnThingCount
bool applyDamageToExplosionCellsNeighbors = ExplosiveDef.applyDamageToExplosionCellsNeighbors; // Use ExplosiveDef for applyDamageToExplosionCellsNeighbors
float explosionChanceToStartFire = ExplosiveDef.explosionChanceToStartFire; // Use ExplosiveDef for explosionChanceToStartFire
bool explosionDamageFalloff = ExplosiveDef.explosionDamageFalloff; // Use ExplosiveDef for explosionDamageFalloff
float? direction = new float?(this.origin.AngleToFlat(this.destination)); // This remains from original logic
float screenShakeFactor = ExplosiveDef.screenShakeFactor; // Use ExplosiveDef for screenShakeFactor
bool doExplosionVFX = ExplosiveDef.doExplosionVFX; // Use ExplosiveDef for doExplosionVFX
GenExplosion.DoExplosion(
center: ExactPosition.ToIntVec3(), // 爆炸中心
map: map, // 地图
radius: explosionRadius, // 爆炸半径
damType: damageDef, // 伤害类型
instigator: launcher, // 制造者
damAmount: damageAmount, // 伤害量
armorPenetration: armorPenetration, // 护甲穿透
explosionSound: soundExplode, // 爆炸音效
weapon: equipmentDef, // 武器
projectile: def, // 弹药定义
intendedTarget: thing, // 预期目标
postExplosionSpawnThingDef: postExplosionSpawnThingDef, // 爆炸后生成物
postExplosionSpawnChance: postExplosionSpawnChance, // 爆炸后生成几率
postExplosionSpawnThingCount: postExplosionSpawnThingCount, // 爆炸后生成数量
postExplosionGasType: postExplosionGasType, // 气体类型
postExplosionGasRadiusOverride: null, // 爆炸气体半径覆盖
postExplosionGasAmount: 255, // 爆炸气体数量
applyDamageToExplosionCellsNeighbors: applyDamageToExplosionCellsNeighbors, // 是否对爆炸单元格邻居造成伤害
preExplosionSpawnThingDef: preExplosionSpawnThingDef, // 爆炸前生成物
preExplosionSpawnChance: preExplosionSpawnChance, // 爆炸前生成几率
preExplosionSpawnThingCount: preExplosionSpawnThingCount, // 爆炸前生成数量
chanceToStartFire: explosionChanceToStartFire, // 是否有几率点燃
damageFalloff: explosionDamageFalloff, // 爆炸伤害衰减
direction: direction, // 方向
ignoredThings: null, // 忽略的物体
affectedAngle: null, // 受影响角度
doVisualEffects: doExplosionVFX, // 是否显示视觉效果
propagationSpeed: 1f, // 传播速度
excludeRadius: 0f, // 排除半径
doSoundEffects: true, // 是否播放音效
postExplosionSpawnThingDefWater: postExplosionSpawnThingDefWater, // 爆炸后在水中生成物
screenShakeFactor: screenShakeFactor, // 屏幕震动因子
flammabilityChanceCurve: null, // 易燃性几率曲线
overrideCells: null, // 覆盖单元格
postExplosionSpawnSingleThingDef: null, // 爆炸后生成单个物体
preExplosionSpawnSingleThingDef: null // 爆炸前生成单个物体
);
}
}
}

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Reflection;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class Projectile_ExplosiveWithTrail : Projectile_Explosive
{
private TrackingBulletDef trackingDefInt;
private int Fleck_MakeFleckTick;
private Vector3 lastTickPosition;
public TrackingBulletDef TrackingDef
{
get
{
if (trackingDefInt == null)
{
trackingDefInt = def.GetModExtension<TrackingBulletDef>();
if (trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
return trackingDefInt;
}
}
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
{
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
lastTickPosition = origin;
}
protected override void Tick()
{
base.Tick();
// 处理拖尾特效
if (TrackingDef != null && TrackingDef.tailFleckDef != null)
{
Fleck_MakeFleckTick++;
if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks)
{
if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax))
{
Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks;
}
Map map = base.Map;
int randomInRange = TrackingDef.fleckMakeFleckNum.RandomInRange;
Vector3 currentPosition = base.ExactPosition;
Vector3 previousPosition = lastTickPosition;
for (int i = 0; i < randomInRange; i++)
{
float num = (currentPosition - previousPosition).AngleFlat();
float velocityAngle = TrackingDef.fleckAngle.RandomInRange + num;
float randomInRange2 = TrackingDef.fleckScale.RandomInRange;
float randomInRange3 = TrackingDef.fleckSpeed.RandomInRange;
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, randomInRange2);
dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange;
dataStatic.velocityAngle = velocityAngle;
dataStatic.velocitySpeed = randomInRange3;
map.flecks.CreateFleck(dataStatic);
}
}
}
lastTickPosition = base.ExactPosition;
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref Fleck_MakeFleckTick, "Fleck_MakeFleckTick", 0);
Scribe_Values.Look(ref lastTickPosition, "lastTickPosition", Vector3.zero);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
if (this.trackingDefInt == null)
{
this.trackingDefInt = this.def.GetModExtension<TrackingBulletDef>();
if (this.trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef is null for projectile {this.def.defName} after PostLoadInit. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
}
}
}
}

View File

@@ -0,0 +1,232 @@
using System.Collections.Generic;
using System.Reflection;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class Projectile_TrackingBullet : Bullet
{
private TrackingBulletDef trackingDefInt;
protected Vector3 exactPositionInt;
public Vector3 curSpeed;
public bool homing = true;
private int destroyTicksAfterLosingTrack = -1; // 失去追踪后多少tick自毁-1表示不自毁
private int Fleck_MakeFleckTick; // 拖尾特效的计时器
private Vector3 lastTickPosition; // 记录上一帧的位置,用于计算移动方向
private static class NonPublicFields
{
public static FieldInfo Projectile_AmbientSustainer = typeof(Projectile).GetField("ambientSustainer", BindingFlags.Instance | BindingFlags.NonPublic);
public static FieldInfo ThingWithComps_comps = typeof(ThingWithComps).GetField("comps", BindingFlags.Instance | BindingFlags.NonPublic);
public static MethodInfo ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
}
public TrackingBulletDef TrackingDef
{
get
{
if (trackingDefInt == null)
{
trackingDefInt = def.GetModExtension<TrackingBulletDef>();
if (trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
return trackingDefInt;
}
}
public override Vector3 ExactPosition => exactPositionInt;
public override Quaternion ExactRotation => Quaternion.LookRotation(curSpeed);
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
{
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
exactPositionInt = origin.Yto0() + Vector3.up * def.Altitude;
// 初始化子弹速度,指向目标,并考虑初始旋转角度
Vector3 initialDirection = (destination - origin).Yto0().normalized;
float degrees = Rand.Range(0f - TrackingDef.initRotateAngle, TrackingDef.initRotateAngle);
Vector2 v = new Vector2(initialDirection.x, initialDirection.z);
v = v.RotatedBy(degrees);
Vector3 rotatedDirection = new Vector3(v.x, 0f, v.y);
curSpeed = rotatedDirection * def.projectile.SpeedTilesPerTick;
ReflectInit();
lastTickPosition = origin; // 初始化 lastTickPosition
}
protected void ReflectInit()
{
// 确保私有字段的访问
if (!def.projectile.soundAmbient.NullOrUndefined())
{
// This line might cause issues if ambientSustainer is not directly settable or if Projectile type changes.
// For simplicity, we might omit it for now or find a safer way.
// ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
}
// comps = (List<ThingComp>)NonPublicFields.ThingWithComps_comps.GetValue(this); // 如果需要CompTick需要这个
}
public virtual void MovementTick()
{
Vector3 vect = ExactPosition + curSpeed;
ShootLine shootLine = new ShootLine(ExactPosition.ToIntVec3(), vect.ToIntVec3());
Vector3 vectorToTarget = (intendedTarget.Cell.ToVector3() - ExactPosition).Yto0();
if (homing)
{
// 首先检查目标是否是一个有效的 Thing
if (!intendedTarget.HasThing)
{
homing = false; // 如果目标是地面,则禁用追踪
}
// 如果目标消失或距离太远,停止追踪
else if (!intendedTarget.IsValid || !intendedTarget.Thing.Spawned || (intendedTarget.Cell.ToVector3() - ExactPosition).magnitude > def.projectile.speed * 2f) // 假设2倍速度为最大追踪距离
{
homing = false;
destroyTicksAfterLosingTrack = TrackingDef.destroyTicksAfterLosingTrack.RandomInRange; // 失去追踪后根据XML配置的范围自毁
}
else
{
// 计算需要转向的方向
Vector3 desiredDirection = vectorToTarget.normalized;
Vector3 currentDirection = curSpeed.normalized;
// 计算方向差异
Vector3 directionDifference = desiredDirection - currentDirection;
// 如果方向差异过大,可能失去追踪,或者直接转向
if (directionDifference.sqrMagnitude > 0.001f) // 避免浮点数精度问题
{
// 调整当前速度,使其更接近目标方向
curSpeed += directionDifference * TrackingDef.homingSpeed * curSpeed.magnitude;
curSpeed = curSpeed.normalized * def.projectile.SpeedTilesPerTick; // 保持速度恒定
}
}
}
exactPositionInt = ExactPosition + curSpeed; // 更新位置
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref exactPositionInt, "exactPosition");
Scribe_Values.Look(ref curSpeed, "curSpeed");
Scribe_Values.Look(ref homing, "homing", defaultValue: true);
Scribe_Values.Look(ref destroyTicksAfterLosingTrack, "destroyTicksAfterLosingTrack", -1);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
ReflectInit();
if (this.trackingDefInt == null)
{
this.trackingDefInt = this.def.GetModExtension<TrackingBulletDef>();
if (this.trackingDefInt == null)
{
Log.ErrorOnce($"TrackingBulletDef is null for projectile {this.def.defName} after PostLoadInit. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
this.trackingDefInt = new TrackingBulletDef();
}
}
}
}
protected override void Tick()
{
base.Tick(); // 调用父类Bullet的Tick处理 ticksToImpact 减少和最终命中
if (destroyTicksAfterLosingTrack > 0)
{
destroyTicksAfterLosingTrack--;
if (destroyTicksAfterLosingTrack <= 0)
{
Destroy(); // 如果自毁计时器归零,直接销毁
return;
}
}
// 处理拖尾特效
if (TrackingDef != null && TrackingDef.tailFleckDef != null)
{
Fleck_MakeFleckTick++;
// 只有当达到延迟时间后才开始生成Fleck
if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks)
{
if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax))
{
Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
}
Map map = base.Map;
int randomInRange = TrackingDef.fleckMakeFleckNum.RandomInRange;
Vector3 currentPosition = ExactPosition;
Vector3 previousPosition = lastTickPosition;
for (int i = 0; i < randomInRange; i++)
{
float num = (currentPosition - previousPosition).AngleFlat();
float velocityAngle = TrackingDef.fleckAngle.RandomInRange + num;
float randomInRange2 = TrackingDef.fleckScale.RandomInRange;
float randomInRange3 = TrackingDef.fleckSpeed.RandomInRange;
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, randomInRange2);
dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange;
dataStatic.velocityAngle = velocityAngle;
dataStatic.velocitySpeed = randomInRange3;
map.flecks.CreateFleck(dataStatic);
}
}
}
lastTickPosition = ExactPosition; // 更新上一帧位置
// 保存移动前的精确位置
Vector3 exactPositionBeforeMove = exactPositionInt;
MovementTick(); // 调用追踪移动逻辑,更新 exactPositionInt (即新的 ExactPosition)
// 检查是否超出地图边界
if (!ExactPosition.InBounds(base.Map))
{
// 如果超出地图,直接销毁,不触发 ImpactSomething()
Destroy();
return;
}
// 在调用 ProjectileCheckForFreeInterceptBetween 之前,添加近距离命中检测
if (intendedTarget != null && intendedTarget.Thing != null && intendedTarget.Thing.Spawned)
{
float distanceToTarget = (ExactPosition - intendedTarget.Thing.DrawPos).magnitude;
if (distanceToTarget <= TrackingDef.impactThreshold)
{
Impact(intendedTarget.Thing); // 强制命中目标
return; // 命中后立即返回,不再执行后续逻辑
}
}
// 检查是否有东西在路径上拦截
// ProjectileCheckForFreeInterceptBetween 会在内部处理命中,并调用 ImpactSomething()
// 所以这里不需要额外的 ImpactSomething() 调用
object[] parameters = new object[2] { exactPositionBeforeMove, exactPositionInt }; // 传入移动前和移动后的位置
// 调用 ProjectileCheckForFreeInterceptBetween
// 如果它返回 true说明有拦截并且拦截逻辑已在内部处理。
// 如果返回 false说明没有拦截子弹继续飞行。
NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
}
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
// 默认Impact逻辑可以根据需要扩展
base.Impact(hitThing, blockedByShield);
}
}
}

View File

@@ -0,0 +1,157 @@
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
// A new, dedicated extension class for the penetrating beam.
public class Wula_BeamPierce_Extension : DefModExtension
{
public int maxHits = 3;
public float damageFalloff = 0.25f;
public bool preventFriendlyFire = false;
public ThingDef beamMoteDef;
public float beamWidth = 1f;
public float beamStartOffset = 0f;
}
public class Projectile_WulaPenetratingBeam : Bullet
{
private int hitCounter = 0;
private List<Thing> alreadyDamaged = new List<Thing>();
// It now gets its properties from the new, dedicated extension.
private Wula_BeamPierce_Extension Props => def.GetModExtension<Wula_BeamPierce_Extension>();
public override Vector3 ExactPosition => destination + Vector3.up * def.Altitude;
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
{
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
Wula_BeamPierce_Extension props = Props;
if (props == null)
{
Log.Error("Projectile_WulaBeam requires a Wula_BeamPierce_Extension in its def.");
Destroy(DestroyMode.Vanish);
return;
}
this.hitCounter = 0;
this.alreadyDamaged.Clear();
bool shouldPreventFriendlyFire = preventFriendlyFire || props.preventFriendlyFire;
Map map = this.Map;
// --- Corrected Start Position Calculation ---
// The beam should start from the gun's muzzle, not the pawn's center.
Vector3 endPosition = usedTarget.Cell.ToVector3Shifted();
Vector3 castPosition = origin + (endPosition - origin).Yto0().normalized * props.beamStartOffset;
// --- Vanilla Beam Drawing Logic ---
if (props.beamMoteDef != null)
{
// Calculate the offset exactly like the vanilla Beam class does.
// The offset for the mote is calculated from the launcher's true position, not the cast position.
Vector3 moteOffset = (endPosition - launcher.Position.ToVector3Shifted()).Yto0().normalized * props.beamStartOffset;
MoteMaker.MakeInteractionOverlay(props.beamMoteDef, launcher, usedTarget.ToTargetInfo(map), moteOffset, Vector3.zero);
}
float distance = Vector3.Distance(castPosition, endPosition);
Vector3 direction = (endPosition - castPosition).normalized;
var thingsOnPath = new HashSet<Thing>();
for (float i = 0; i < distance; i += 1.0f)
{
IntVec3 cell = (castPosition + direction * i).ToIntVec3();
if (cell.InBounds(map))
{
thingsOnPath.AddRange(map.thingGrid.ThingsListAt(cell));
}
}
// CRITICAL FIX: Manually add the intended target to the list.
// This guarantees the primary target is always processed, even if the loop sampling misses its exact cell.
if (intendedTarget.HasThing)
{
thingsOnPath.Add(intendedTarget.Thing);
}
int maxHits = props.maxHits;
bool infinitePenetration = maxHits < 0;
foreach (Thing thing in thingsOnPath)
{
if (!infinitePenetration && hitCounter >= maxHits) break;
// 统一处理 Pawn 和 Building 的伤害逻辑
// 确保 Thing 未被伤害过且不是发射者
if (thing != launcher && !alreadyDamaged.Contains(thing))
{
bool shouldDamage = false;
Pawn pawn = thing as Pawn;
Building building = thing as Building;
if (pawn != null) // 如果是 Pawn
{
if (intendedTarget.Thing == pawn) shouldDamage = true;
else if (pawn.HostileTo(launcher)) shouldDamage = true;
else if (!shouldPreventFriendlyFire) shouldDamage = true;
}
else if (building != null) // 如果是 Building
{
shouldDamage = true; // 默认对 Building 造成伤害
}
if (shouldDamage)
{
ApplyPathDamage(thing, props); // 传递 Thing
}
}
// 只有当遇到完全阻挡的 Thing 且不是 Pawn 或 Building 时才停止穿透
else if (thing.def.Fillage == FillCategory.Full && thing.def.blockLight && !(thing is Pawn) && !(thing is Building))
{
break;
}
}
this.Destroy(DestroyMode.Vanish);
}
private void ApplyPathDamage(Thing targetThing, Wula_BeamPierce_Extension props) // 接受 Thing 参数
{
float damageMultiplier = 1f;
if (targetThing is Pawn) // 只有 Pawn 才计算穿透衰减
{
damageMultiplier = Mathf.Pow(1f - props.damageFalloff, hitCounter);
}
// Building 不受穿透衰减影响,或者 Building 的穿透衰减始终为 1 (不衰减)
int damageAmount = (int)(this.DamageAmount * damageMultiplier);
if (damageAmount <= 0) return;
var dinfo = new DamageInfo(
this.def.projectile.damageDef,
damageAmount,
this.ArmorPenetration * damageMultiplier,
this.ExactRotation.eulerAngles.y,
this.launcher,
null,
this.equipmentDef,
DamageInfo.SourceCategory.ThingOrUnknown,
this.intendedTarget.Thing);
targetThing.TakeDamage(dinfo); // 对 targetThing 造成伤害
alreadyDamaged.Add(targetThing);
if (targetThing is Pawn) // 只有 Pawn 才增加 hitCounter
{
hitCounter++;
}
}
protected override void Tick() { }
protected override void Impact(Thing hitThing, bool blockedByShield = false) { }
}
}

View File

@@ -0,0 +1,201 @@
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
// Final, robust extension class for configuring path-based penetration.
public class Wula_PathPierce_Extension : DefModExtension
{
// Set to a positive number for limited hits, or -1 for infinite penetration.
public int maxHits = 3;
// The percentage of damage lost per hit. 0.25 means 25% damage loss per hit.
public float damageFalloff = 0.25f;
// If true, this projectile will never cause friendly fire, regardless of game settings.
public bool preventFriendlyFire = false;
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
public int fleckDelayTicks = 10; // 拖尾特效延迟生成时间tick
}
public class Projectile_WulaLineAttack : Bullet
{
private int hitCounter = 0;
private List<Thing> alreadyDamaged = new List<Thing>();
private Vector3 lastTickPosition;
private int Fleck_MakeFleckTick; // 拖尾特效的计时器
public int Fleck_MakeFleckTickMax = 1; // 拖尾特效的生成频率
public IntRange Fleck_MakeFleckNum = new IntRange(1, 1); // 每次生成的粒子数量
public FloatRange Fleck_Angle = new FloatRange(-180f, 180f); // 粒子角度
public FloatRange Fleck_Scale = new FloatRange(1f, 1f); // 粒子大小
public FloatRange Fleck_Speed = new FloatRange(0f, 0f); // 粒子速度
public FloatRange Fleck_Rotation = new FloatRange(-180f, 180f); // 粒子旋转
private Wula_PathPierce_Extension Props => def.GetModExtension<Wula_PathPierce_Extension>();
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref hitCounter, "hitCounter", 0);
Scribe_Collections.Look(ref alreadyDamaged, "alreadyDamaged", LookMode.Reference);
Scribe_Values.Look(ref lastTickPosition, "lastTickPosition");
if (alreadyDamaged == null)
{
alreadyDamaged = new List<Thing>();
}
}
public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
{
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
this.lastTickPosition = origin;
this.alreadyDamaged.Clear();
this.hitCounter = 0;
// Friendly fire is prevented if EITHER the game setting is true OR the XML extension is true.
this.preventFriendlyFire = preventFriendlyFire || (Props?.preventFriendlyFire ?? false);
}
protected override void Tick()
{
Vector3 startPos = this.lastTickPosition;
base.Tick();
if (this.Destroyed) return;
this.Fleck_MakeFleckTick++;
// 只有当达到延迟时间后才开始生成Fleck
if (this.Fleck_MakeFleckTick >= Props.fleckDelayTicks)
{
if (this.Fleck_MakeFleckTick >= (Props.fleckDelayTicks + this.Fleck_MakeFleckTickMax))
{
this.Fleck_MakeFleckTick = Props.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
}
Map map = base.Map;
int randomInRange = this.Fleck_MakeFleckNum.RandomInRange;
Vector3 currentPosition = this.ExactPosition; // Current position of the bullet
Vector3 previousPosition = this.lastTickPosition; // Previous position of the bullet
for (int i = 0; i < randomInRange; i++)
{
float currentBulletAngle = ExactRotation.eulerAngles.y; // 使用子弹当前的水平旋转角度
float fleckRotationAngle = currentBulletAngle; // Fleck 的旋转角度与子弹方向一致
float velocityAngle = this.Fleck_Angle.RandomInRange + currentBulletAngle; // Fleck 的速度角度基于子弹方向加上随机偏移
float randomInRange2 = this.Fleck_Scale.RandomInRange;
float randomInRange3 = this.Fleck_Speed.RandomInRange;
if (Props?.tailFleckDef != null)
{
FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, Props.tailFleckDef, randomInRange2);
dataStatic.rotation = fleckRotationAngle;
dataStatic.rotationRate = this.Fleck_Rotation.RandomInRange;
dataStatic.velocityAngle = velocityAngle;
dataStatic.velocitySpeed = randomInRange3;
map.flecks.CreateFleck(dataStatic);
}
}
}
if (this.Destroyed) return;
Vector3 endPos = this.ExactPosition;
CheckPathForDamage(startPos, endPos);
this.lastTickPosition = endPos;
}
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
CheckPathForDamage(lastTickPosition, this.ExactPosition);
if (hitThing != null && alreadyDamaged.Contains(hitThing))
{
base.Impact(null, blockedByShield);
}
else
{
base.Impact(hitThing, blockedByShield);
}
}
private void CheckPathForDamage(Vector3 startPos, Vector3 endPos)
{
if (startPos == endPos) return;
int maxHits = Props?.maxHits ?? 1;
bool infinitePenetration = maxHits < 0;
if (!infinitePenetration && hitCounter >= maxHits) return;
Map map = this.Map;
float distance = Vector3.Distance(startPos, endPos);
Vector3 direction = (endPos - startPos).normalized;
for (float i = 0; i < distance; i += 0.8f)
{
if (!infinitePenetration && hitCounter >= maxHits) break;
Vector3 checkPos = startPos + direction * i;
var thingsInCell = new HashSet<Thing>(map.thingGrid.ThingsListAt(checkPos.ToIntVec3()));
foreach (Thing thing in thingsInCell)
{
if (thing is Pawn pawn && pawn != this.launcher && !alreadyDamaged.Contains(pawn))
{
bool shouldDamage = false;
// Case 1: Always damage the intended target if it's a pawn. This allows hunting.
if (this.intendedTarget.Thing == pawn)
{
shouldDamage = true;
}
// Case 2: Always damage hostile pawns in the path.
else if (pawn.HostileTo(this.launcher))
{
shouldDamage = true;
}
// Case 3: Damage non-hostiles (friendlies, neutrals) if the shot itself isn't marked to prevent friendly fire.
else if (!this.preventFriendlyFire)
{
shouldDamage = true;
}
if (shouldDamage)
{
ApplyPathDamage(pawn);
if (!infinitePenetration && hitCounter >= maxHits) break;
}
}
}
}
}
private void ApplyPathDamage(Pawn pawn)
{
Wula_PathPierce_Extension props = Props;
float falloff = props?.damageFalloff ?? 0.25f;
// Damage falloff now applies universally, even for infinite penetration.
float damageMultiplier = Mathf.Pow(1f - falloff, hitCounter);
int damageAmount = (int)(this.DamageAmount * damageMultiplier);
if (damageAmount <= 0) return;
var dinfo = new DamageInfo(
this.def.projectile.damageDef,
damageAmount,
this.ArmorPenetration * damageMultiplier,
this.ExactRotation.eulerAngles.y,
this.launcher,
null,
this.equipmentDef,
DamageInfo.SourceCategory.ThingOrUnknown,
this.intendedTarget.Thing);
pawn.TakeDamage(dinfo);
alreadyDamaged.Add(pawn);
hitCounter++;
}
}
}

Some files were not shown because too many files have changed in this diff Show More