37 Commits

Author SHA1 Message Date
ProjectKoi-Kalo\Kalo
e5feb47e8b 暂存 2025-09-03 09:13:03 +08:00
ProjectKoi-Kalo\Kalo
9e4eda256f 修质量 2025-09-02 21:49:46 +08:00
ProjectKoi-Kalo\Kalo
9b5a8a58d3 怪了好使了 2025-09-02 21:43:35 +08:00
ProjectKoi-Kalo\Kalo
8a7a947669 暂存 2025-09-02 21:28:25 +08:00
ProjectKoi-Kalo\Kalo
ce3e84116e Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-02 18:39:45 +08:00
Tourswen
94e4cb54ba 各种改动巴拉巴拉 2025-09-02 17:29:53 +08:00
Tourswen
418739ac5b 墙体、女王需求等巴拉巴拉 2025-09-02 16:06:41 +08:00
ProjectKoi-Kalo\Kalo
6129bb1b50 暂存文档 2025-09-02 15:48:16 +08:00
ProjectKoi-Kalo\Kalo
d335b2008c 暂存 2025-09-02 15:06:36 +08:00
ProjectKoi-Kalo\Kalo
8672eb9f40 暂存 2025-09-02 14:33:33 +08:00
ProjectKoi-Kalo\Kalo
b1d6df2523 呃呃害人 2025-09-02 12:48:59 +08:00
ProjectKoi-Kalo\Kalo
e78c858d5a 文件截断了补一下 2025-09-02 12:42:37 +08:00
ProjectKoi-Kalo\Kalo
8688e469f6 暂存 2025-09-02 12:40:02 +08:00
ProjectKoi-Kalo\Kalo
4e80aa3432 style(1.6): 修复阿拉克涅菌毯定义中的 XML 标签
- 闭合 designationCategory 标签以修复 XML 结构问题
2025-09-02 12:23:50 +08:00
ProjectKoi-Kalo\Kalo
952f1ae851 Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-02 12:22:29 +08:00
ProjectKoi-Kalo\Kalo
61a7013946 暂存 2025-09-02 12:21:49 +08:00
Tourswen
259eb3530e Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-02 12:01:24 +08:00
Tourswen
bf8a13ae60 破茧提示以及其他若干 2025-09-02 12:00:17 +08:00
ProjectKoi-Kalo\Kalo
06b0a74cbd 产奶 2025-09-02 11:52:27 +08:00
ProjectKoi-Kalo\Kalo
f6cd9bfd6c 存一下 2025-09-02 11:31:37 +08:00
Tourswen
cebccfebe5 巴拉巴拉更新 2025-09-02 00:57:06 +08:00
Tourswen
7ae4b5db88 Update ARA_RaceQueen.xml 2025-09-01 23:17:56 +08:00
Tourswen
a4dd99c751 2025-9-1 2025-09-01 23:06:07 +08:00
ProjectKoi-Kalo\Kalo
f3381f5d62 暂存翻译 2025-09-01 20:54:36 +08:00
ProjectKoi-Kalo\Kalo
e6d855924f 暂存 2025-09-01 20:39:33 +08:00
ProjectKoi-Kalo\Kalo
315156f705 暂存 2025-09-01 19:34:25 +08:00
ProjectKoi-Kalo\Kalo
5330c9e84f Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-01 18:52:43 +08:00
ProjectKoi-Kalo\Kalo
9e75459d1f 节点虫暂存 2025-09-01 18:52:40 +08:00
Tourswen
d10cb48592 修红字 2025-09-01 18:30:01 +08:00
Tourswen
d72909063f 调整文件位置 2025-09-01 17:28:55 +08:00
Tourswen
dd6ddccc9a Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm 2025-09-01 17:24:54 +08:00
Tourswen
b218494149 女皇种背景、描述、技能修改 2025-09-01 17:23:15 +08:00
ProjectKoi-Kalo\Kalo
9ab3300ac6 暂存 2025-09-01 16:56:48 +08:00
ProjectKoi-Kalo\Kalo
e58fac54f8 存食物需求的ability 2025-09-01 16:42:08 +08:00
Tourswen
3203db0728 Update ARA_Bodyparts.xml 2025-09-01 15:03:54 +08:00
Tourswen
0d53f76a98 Update ARA_Bodyparts.xml 2025-09-01 15:00:40 +08:00
ProjectKoi-Kalo\Kalo
fc51e18424 调吐酸 2025-09-01 14:16:51 +08:00
80 changed files with 5516 additions and 1121 deletions

Binary file not shown.

View File

@@ -1,12 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<AbilityDef ParentName="AbilityTouchBase">
<defName>ARA_BindDrone</defName>
<label>信息素标记</label>
<description>使用信息素标记一只阿拉克涅督虫,受到标记的督虫和其麾下的辅虫将誓死效忠于女皇种,并与其建立心灵链接。</description>
<iconPath>UI/Commands/EggSpew</iconPath> <!-- Placeholder: You'll need to create this icon -->
<jobDef>CastAbilityOnThing</jobDef>
<targetRequired>true</targetRequired>
<cooldownTicksRange>60</cooldownTicksRange> <!-- 1 second cooldown -->
<AbilityDef>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<warmupTime>0</warmupTime>
<range>99</range>
<targetParams>
<canTargetPawns>true</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
<canTargetAnimals>true</canTargetAnimals>
<canTargetMechs>false</canTargetMechs>
<canTargetCorpses>false</canTargetCorpses>
<canTargetSelf>false</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="ArachnaeSwarm.CompProperties_AbilityBindDrone">
<!-- No custom properties needed for now -->
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_EggSpew</defName>
<label>生育虫卵</label>
<description>向目标区域发射一个卵囊和酸性污泥喷射。污泥会粘在目标上并灼烧它们</description>
<description>从卵巢中排出一颗休眠的虫卵,阿拉克涅女皇种可以通过与其交互将其激活,并选择孵化的督虫虫族类型——参阅虫卵的具体信息,了解各个督虫的特点</description>
<iconPath>UI/Commands/EggSpew</iconPath>
<cooldownTicksRange>5000</cooldownTicksRange> <!-- 2 hours -->
<cooldownTicksRange>5000</cooldownTicksRange>
<aiCanUse>true</aiCanUse>
<displayOrder>300</displayOrder>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
@@ -14,24 +45,34 @@
<warmupStartSound>AcidSpray_Warmup</warmupStartSound>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>14.9</range>
<warmupTime>0.25</warmupTime>
<range>1</range>
<warmupTime>12</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<violent>false</violent>
<targetable>false</targetable>
<targetParams>
<canTargetLocations>true</canTargetLocations>
<canTargetSelf>True</canTargetSelf>
</targetParams>
</verbProperties>
<comps>
<li Class="CompProperties_AbilityLaunchProjectile">
<projectileDef>ARA_Proj_EggSac</projectileDef>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>4</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityBodyPartCheck">
<requiredPart>ARA_Ovary</requiredPart>
<failMessage>卵巢受损或缺失,无法生育</failMessage>
</li>
</comps>
</AbilityDef>
<AbilityDef>
<defName>ARA_AcidSprayBurst</defName>
<label>酸液连射</label>
<description>快速连续喷射多次腐蚀性酸液,覆盖一片区域。</description>
<label>女皇种酸液轰炸</label>
<description>阿拉克涅女皇种向目标地点喷射大量腐蚀性酸液,喷射将持续数秒以完全覆盖一片区域。</description>
<iconPath>UI/Abilities/AcidSpray</iconPath>
<cooldownTicksRange>5000</cooldownTicksRange> <!-- 2 hours -->
<aiCanUse>true</aiCanUse>
@@ -42,7 +83,7 @@
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>32.9</range>
<warmupTime>0.25</warmupTime>
<warmupTime>2</warmupTime>
<soundCast>AcidSpray_Resolve</soundCast>
<targetParams>
<canTargetLocations>true</canTargetLocations>
@@ -52,19 +93,28 @@
<li Class="ArachnaeSwarm.CompProperties_AbilitySprayLiquidMulti">
<!-- CompProperties_AbilitySprayLiquid 的属性 -->
<projectileDef>ARA_Proj_StrongSludgeSpray</projectileDef>
<numCellsToHit>6</numCellsToHit>
<numCellsToHit>13</numCellsToHit>
<sprayEffecter>AcidSpray_Directional</sprayEffecter>
<!-- CompProperties_AbilitySprayLiquidMulti 新增的属性 -->
<shotCount>32</shotCount> <!-- 总共发射5次 -->
<ticksBetweenShots>3</ticksBetweenShots> <!-- 每次发射间隔12 Ticks (0.2秒) -->
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
<needDef>Food</needDef>
<needCost>0.5</needCost>
<failMessage>营养值不足,需要进食</failMessage>
</li>
<li Class="ArachnaeSwarm.CompProperties_AbilityBodyPartCheck">
<requiredPart>ARA_Acid_sac</requiredPart>
<failMessage>酸囊受损或缺失,无法喷射酸液</failMessage>
</li>
</comps>
</AbilityDef>
<ThingDef>
<defName>ARA_Proj_StrongSludgeSpray</defName>
<label>虫族酸液</label>
<label>阿拉克涅虫族酸液</label>
<thingClass>Projectile_Liquid</thingClass>
<category>Projectile</category>
<tickerType>Normal</tickerType>
@@ -78,14 +128,14 @@
<drawSize>0.85</drawSize>
</graphicData>
<projectile>
<damageDef>AcidBurn</damageDef>
<damageDef>ARA_AcidBurn</damageDef>
<speed>25</speed>
<damageAmountBase>18</damageAmountBase>
<damageAmountBase>2</damageAmountBase>
<arcHeightFactor>0.4</arcHeightFactor>
<armorPenetrationBase>0.1</armorPenetrationBase>
<stoppingPower>1</stoppingPower>
<shadowSize>0</shadowSize>
<spawnTerrain>InsectSludge</spawnTerrain>
<spawnTerrain>ARA_InsectSludge</spawnTerrain>
<terrainChance>0.75</terrainChance>
<filth>Filth_Slime</filth>
<filthCount>1</filthCount>
@@ -94,11 +144,11 @@
</ThingDef>
<ThingDef ParentName="BaseGrenadeProjectile">
<defName>ARA_Proj_EggSac</defName>
<label>虫卵</label>
<label>阿拉克涅虫卵</label>
<thingClass>Projectile_SpawnsThing</thingClass>
<graphicData>
<texPath>Things/Projectile/EggSac</texPath>
<graphicClass>Graphic_Random</graphicClass>
<texPath>ArachnaeSwarm/Building/ARA_EggSac</texPath>
<graphicClass>Graphic_Single</graphicClass>
</graphicData>
<projectile>
<damageDef>Bullet</damageDef>
@@ -108,5 +158,4 @@
<tryAdjacentFreeSpaces>true</tryAdjacentFreeSpaces>
</projectile>
</ThingDef>
</Defs>
</Defs>

View File

@@ -1,39 +1,76 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AlienRace.AlienBackstoryDef Name="DragonianBackStory" Abstract="True">
<bodyTypeMale>ARA_QUEEN_Thin</bodyTypeMale>
<bodyTypeFemale>ARA_QUEEN_Thin</bodyTypeFemale>
<AlienRace.AlienBackstoryDef Name="ARA_BaseBackStory" Abstract="True">
<requiresSpawnCategory>true</requiresSpawnCategory>
</AlienRace.AlienBackstoryDef>
<!-- 일반 --> <!-- 유년기 -->
<AlienRace.AlienBackstoryDef>
<defName>Arachnae_BS</defName>
<title>阿拉克涅虫族</title>
<titleShort>阿拉克涅虫族</titleShort>
<description>[PAWN_nameDef]是阿拉克涅虫族.</description>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Queen_BS_Child_1</defName>
<title>本能猎手</title>
<titleShort>本能猎手</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅虫族女皇种,她与上百个姐妹一起降生并被封闭在繁育腔室中。\n\n当封堵女皇种繁育腔室的蜂蜡被工蜂打开时[PAWN_nameDef]屹立于腔室之中——浑身沾满血液和组织液,脚下踏着姐妹们残破的肢体和身躯——她是毫无疑问的从生存游戏中胜出的唯一赢家。</description>
<slot>Childhood</slot>
<skillGains>
<Shooting>2</Shooting>
<Melee>2</Melee>
</skillGains>
<forcedHediffs>
<li>ARA_HiveMindMaster</li>
</forcedHediffs>
<spawnCategories>
<li>ArachnaeQueen_spawnCategoriesA</li>
</spawnCategories>
<requiresSpawnCategory>true</requiresSpawnCategory>
</AlienRace.AlienBackstoryDef>
<!-- 일반 --> <!-- 성년기 -->
<AlienRace.AlienBackstoryDef ParentName="DragonianBackStory">
<defName>Arachnae_BS_B</defName>
<title>阿拉克涅女皇种</title>
<titleShort>阿拉克涅女皇种</titleShort>
<description>[PAWN_nameDef]是阿拉克涅女皇种.</description>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Queen_BS_Adult_1</defName>
<title>见习女皇</title>
<titleShort>见习女皇</titleShort>
<description>[PAWN_nameDef]顺利地在虫巢中长大后,她离开了生养她的巢穴并来到一片陌生的地域,着手准备建立自己的势力。\n\n[PAWN_nameDef]知道自己势单力薄,比起其他娇生惯养的姐妹,她在很多事情上更愿意亲力亲为。</description>
<slot>Adulthood</slot>
<skillGains>
<Shooting>3</Shooting>
<Melee>3</Melee>
<Medicine>3</Medicine>
<Intellectual>3</Intellectual>
<Social>3</Social>
</skillGains>
<workDisables>ManualDumb,Mining,PlantWork,Animals,Crafting,Cooking,Constructing,Hunting</workDisables>
<spawnCategories>
<li>ArachnaeQueen_spawnCategoriesB</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Child_1</defName>
<title>阿拉克涅督虫</title>
<titleShort>督虫</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅督虫——这个种姓的阿拉克涅虫族是虫巢的中坚力量,服从于女皇种的指挥的同时,也指挥着麾下的辅虫。她们从诞生之初便肩负着不同的使命,并且在较短的寿命中尽心尽力地服侍虫群。</description>
<slot>Childhood</slot>
<spawnCategories>
<li>ArachnaeNode_spawnCategoriesA</li>
</spawnCategories>
<forcedHediffs>
<li>ARA_HiveMindDrone</li>
</forcedHediffs>
<requiresSpawnCategory>true</requiresSpawnCategory>
</AlienRace.AlienBackstoryDef>
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
<defName>Arachnae_Node_BS_Adult_Myrmecocystus</defName>
<title>阿拉克涅蜜罐种</title>
<titleShort>蜜罐种</titleShort>
<description>[PAWN_nameDef]是一只阿拉克涅蜜罐种督虫。基因的选择性表达使其长出了肿胀的囊袋和复杂的口器,这使得她可以吞噬那些未经过处理的尸体和各种杂食,并通过消化器官将其转变为阿拉克涅虫蜜以供其他虫族食用。\n\n[PAWN_nameDef]在战斗中并不是一个值得正视的对手,她虽然可以将胃酸喷出以抵抗近距离的来访者,但是自身没有可以接入武装器官的副肢,脆弱臃肿的特性也决定了她几乎无法躲开任何攻击。</description>
<slot>Adulthood</slot>
<spawnCategories>
<li>ArachnaeNode_spawnCategories_Myrmecocystus</li>
</spawnCategories>
</AlienRace.AlienBackstoryDef>
</Defs>

View File

@@ -14,7 +14,7 @@
<!-- 背部组织,仅包含骨骼和甲片 -->
<li>
<def>ARA_Dorsum</def>
<coverage>0.036</coverage>
<coverage>0</coverage>
<groups>
<li>Torso</li>
</groups>
@@ -42,7 +42,7 @@
<!-- 胸部组织,包含骨骼和各类重点维生器官 -->
<li>
<def>ARA_Sternum</def>
<coverage>0.036</coverage>
<coverage>0</coverage>
<groups>
<li>Torso</li>
</groups>
@@ -74,7 +74,7 @@
<li>Torso</li>
</groups>
</li>
<!---->
<!--,4个 -->
<li>
<def>Lung</def>
<customLabel>左肺(其一)</customLabel>
@@ -111,7 +111,7 @@
<li>Torso</li>
</groups>
</li>
<!-- 肾脏 -->
<!-- 肾脏,2个 -->
<li>
<def>Kidney</def>
<customLabel>left kidney</customLabel>
@@ -130,7 +130,7 @@
<li>Torso</li>
</groups>
</li>
<!-- 肝脏 -->
<!-- 肝脏,2个 -->
<li>
<def>Liver</def>
<coverage>0.025</coverage>
@@ -154,13 +154,52 @@
<!-- 尾部组织群 -->
<li>
<def>ARA_Tail</def>
<coverage>0.025</coverage>
<coverage>0.02</coverage>
<height>Bottom</height>
<depth>Inside</depth>
<groups>
<li>Torso</li>
</groups>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>ARA_Chitin_Shell</def>
<coverage>0.01</coverage>
<depth>Outside</depth>
<groups>
<li>Torso</li>
</groups>
</li>
<!-- 性腺 -->
<li>
<def>ARA_Gonad</def>
<coverage>0.005</coverage>
<depth>Inside</depth>
<groups>
<li>ARA_Genitalias</li>
</groups>
</li>
<!-- 卵巢 -->
<li>
<def>ARA_Ovary</def>
<coverage>0.01</coverage>
<depth>Inside</depth>
<groups>
<li>ARA_Genitalias</li>
</groups>
</li>
<!-- 酸囊 -->
<li>
<def>ARA_Acid_sac</def>
<coverage>0.005</coverage>
<depth>Inside</depth>
<groups>
<li>ARA_Acid_sacs</li>
</groups>
</li>
</parts>
</li>
<!-- 脖子往上头部 -->
<li>
<def>Neck</def>
<coverage>0.075</coverage>
@@ -178,6 +217,15 @@
<li>HeadAttackTool</li>
</groups>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>ARA_Chitin_Shell</def>
<coverage>0.02</coverage>
<depth>Outside</depth>
<groups>
<li>UpperHead</li>
</groups>
</li>
<li>
<def>Skull</def>
<coverage>0.18</coverage>
@@ -277,9 +325,10 @@
</li>
</parts>
</li>
<!-- 左右副肢体 -->
<li>
<def>Shoulder</def>
<customLabel>left shoulder</customLabel>
<customLabel>左副肢关节</customLabel>
<coverage>0.12</coverage>
<woundAnchorTag>LeftShoulder</woundAnchorTag>
<flipGraphic>true</flipGraphic>
@@ -289,93 +338,39 @@
<parts>
<li>
<def>Clavicle</def>
<customLabel>left clavicle</customLabel>
<customLabel>左副肢外骨骼</customLabel>
<coverage>0.09</coverage>
<height>Top</height>
<depth>Inside</depth>
<depth>Outside</depth>
<flipGraphic>true</flipGraphic>
<groups>
<li>Torso</li>
<li>Shoulders</li>
</groups>
</li>
<li>
<def>Arm</def>
<customLabel>left arm</customLabel>
<customLabel>左副肢</customLabel>
<coverage>0.77</coverage>
<flipGraphic>true</flipGraphic>
<groups>
<li>Arms</li>
</groups>
<parts>
<li>
<def>Humerus</def>
<customLabel>left humerus</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Arms</li>
</groups>
</li>
<li>
<def>Radius</def>
<customLabel>left radius</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Arms</li>
</groups>
</li>
<li>
<def>Hand</def>
<customLabel>left hand</customLabel>
<customLabel>左鳌钳</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<flipGraphic>true</flipGraphic>
<groups>
<li>Hands</li>
<li>HeadClaw</li>
</groups>
<parts>
<li>
<def>Finger</def>
<customLabel>left pinky</customLabel>
<coverage>0.06</coverage>
<groups>
<li>Hands</li>
<li>LeftHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>left ring finger</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Hands</li>
<li>LeftHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>left middle finger</customLabel>
<coverage>0.08</coverage>
<groups>
<li>Hands</li>
<li>LeftHand</li>
<li>MiddleFingers</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>left index finger</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Hands</li>
<li>LeftHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>left thumb</customLabel>
<coverage>0.08</coverage>
<customLabel>右鳌钳口</customLabel>
<coverage>0.14</coverage>
<groups>
<li>Hands</li>
<li>LeftHand</li>
@@ -389,99 +384,49 @@
</li>
<li>
<def>Shoulder</def>
<customLabel>right shoulder</customLabel>
<customLabel>右副肢关节</customLabel>
<coverage>0.12</coverage>
<woundAnchorTag>RightShoulder</woundAnchorTag>
<woundAnchorTag>LeftShoulder</woundAnchorTag>
<flipGraphic>true</flipGraphic>
<groups>
<li>Shoulders</li>
</groups>
<parts>
<li>
<def>Clavicle</def>
<customLabel>right clavicle</customLabel>
<customLabel>右副肢外骨骼</customLabel>
<coverage>0.09</coverage>
<height>Top</height>
<depth>Inside</depth>
<depth>Outside</depth>
<flipGraphic>true</flipGraphic>
<groups>
<li>Torso</li>
<li>Shoulders</li>
</groups>
</li>
<li>
<def>Arm</def>
<customLabel>right arm</customLabel>
<customLabel>右副肢</customLabel>
<coverage>0.77</coverage>
<flipGraphic>true</flipGraphic>
<groups>
<li>Arms</li>
</groups>
<parts>
<li>
<def>Humerus</def>
<customLabel>right humerus</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Arms</li>
</groups>
</li>
<li>
<def>Radius</def>
<customLabel>right radius</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Arms</li>
</groups>
</li>
<li>
<def>Hand</def>
<customLabel>right hand</customLabel>
<customLabel>右鳌钳</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<flipGraphic>true</flipGraphic>
<groups>
<li>Hands</li>
<li>HeadClaw</li>
</groups>
<parts>
<li>
<def>Finger</def>
<customLabel>right pinky</customLabel>
<coverage>0.06</coverage>
<groups>
<li>Hands</li>
<li>RightHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>right ring finger</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Hands</li>
<li>RightHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>right middle finger</customLabel>
<coverage>0.08</coverage>
<groups>
<li>Hands</li>
<li>RightHand</li>
<li>MiddleFingers</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>right index finger</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Hands</li>
<li>RightHand</li>
</groups>
</li>
<li>
<def>Finger</def>
<customLabel>right thumb</customLabel>
<coverage>0.08</coverage>
<customLabel>右鳌钳口</customLabel>
<coverage>0.14</coverage>
<groups>
<li>Hands</li>
<li>RightHand</li>
@@ -493,17 +438,20 @@
</li>
</parts>
</li>
<!-- 腰尾链接 -->
<li>
<def>Waist</def>
<customLabel>体节分界</customLabel>
<coverage>0</coverage>
<height>Bottom</height>
<groups>
<li>Waist</li>
</groups>
</li>
<!-- 四条腿 -->
<li>
<def>Leg</def>
<customLabel>left leg</customLabel>
<customLabel>左前腿</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<groups>
@@ -512,154 +460,120 @@
<woundAnchorTag>LeftLeg</woundAnchorTag>
<flipGraphic>true</flipGraphic>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>ARA_Chitin_Shell</def>
<coverage>0.02</coverage>
<depth>Outside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
<!-- 骨骼 -->
<li>
<def>Femur</def>
<customLabel>left femur</customLabel>
<customLabel>左前腿外骨骼</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
<li>
<def>Tibia</def>
<customLabel>left tibia</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
<li>
<def>Foot</def>
<customLabel>left foot</customLabel>
<coverage>0.1</coverage>
<flipGraphic>true</flipGraphic>
<groups>
<li>Feet</li>
</groups>
<parts>
<li>
<def>Toe</def>
<customLabel>left little toe</customLabel>
<coverage>0.06</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>left fourth toe</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>left middle toe</customLabel>
<coverage>0.08</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>left second toe</customLabel>
<coverage>0.09</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>left big toe</customLabel>
<coverage>0.09</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
</parts>
</li>
</parts>
</li>
<li>
<def>Leg</def>
<customLabel>right leg</customLabel>
<customLabel>右前腿</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<groups>
<li>Legs</li>
</groups>
<woundAnchorTag>RightLeg</woundAnchorTag>
<woundAnchorTag>LeftLeg</woundAnchorTag>
<flipGraphic>true</flipGraphic>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>ARA_Chitin_Shell</def>
<coverage>0.02</coverage>
<depth>Outside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
<!-- 骨骼 -->
<li>
<def>Femur</def>
<customLabel>right femur</customLabel>
<customLabel>右前腿外骨骼</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
</parts>
</li>
<li>
<def>Leg</def>
<customLabel>左后腿</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<groups>
<li>Legs</li>
</groups>
<woundAnchorTag>LeftLeg</woundAnchorTag>
<flipGraphic>true</flipGraphic>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>Tibia</def>
<customLabel>right tibia</customLabel>
<def>ARA_Chitin_Shell</def>
<coverage>0.02</coverage>
<depth>Outside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
<!-- 骨骼 -->
<li>
<def>Femur</def>
<customLabel>左后腿外骨骼</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Legs</li>
</groups>
</li>
</parts>
</li>
<li>
<def>Leg</def>
<customLabel>右后腿</customLabel>
<coverage>0.14</coverage>
<height>Bottom</height>
<groups>
<li>Legs</li>
</groups>
<woundAnchorTag>LeftLeg</woundAnchorTag>
<flipGraphic>true</flipGraphic>
<parts>
<!-- 甲片,防御作用 -->
<li>
<def>Foot</def>
<customLabel>right foot</customLabel>
<coverage>0.1</coverage>
<def>ARA_Chitin_Shell</def>
<coverage>0.02</coverage>
<depth>Outside</depth>
<groups>
<li>Feet</li>
<li>Legs</li>
</groups>
</li>
<!-- 骨骼 -->
<li>
<def>Femur</def>
<customLabel>右后腿外骨骼</customLabel>
<coverage>0.1</coverage>
<depth>Inside</depth>
<groups>
<li>Legs</li>
</groups>
<parts>
<li>
<def>Toe</def>
<customLabel>right little toe</customLabel>
<coverage>0.06</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>right fourth toe</customLabel>
<coverage>0.07</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>right middle toe</customLabel>
<coverage>0.08</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>right second toe</customLabel>
<coverage>0.09</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
<li>
<def>Toe</def>
<customLabel>right big toe</customLabel>
<coverage>0.09</coverage>
<groups>
<li>Feet</li>
</groups>
</li>
</parts>
</li>
</parts>
</li>
@@ -717,51 +631,177 @@
</tags>
<destroyableByDamage>false</destroyableByDamage>
</BodyPartDef>
<BodyPartDef>
<defName></defName>
<label>中央能源炉</label>
<hitPoints>120</hitPoints>
<skinCovered>false</skinCovered>
<!-- <solid>true</solid> -->
<tags>
<li>BloodPumpingSource</li>
<li>BreathingSource</li>
<li>BloodFiltrationKidney</li>
<li>BloodFiltrationLiver</li>
<li>MetabolismSource</li>
<li>EatingSource</li>
<li>Spine</li>
<li>Pelvis</li>
<li>ManipulationLimbSegment</li>
<li>TalkingSource</li>
</tags>
<spawnThingOnRemoved>WULA_Energy_Furnace_Base</spawnThingOnRemoved>
</BodyPartDef>
<BodyPartDef>
<defName>WULA_Addons_Antenna_Bodypart</defName>
<label>上行链路天线</label>
<defName>ARA_Gonad</defName>
<label>性腺</label>
<hitPoints>30</hitPoints>
<permanentInjuryChanceFactor>0</permanentInjuryChanceFactor>
<skinCovered>false</skinCovered>
<!-- <solid>true</solid> -->
<bleedRate>0</bleedRate>
<destroyableByDamage>false</destroyableByDamage>
<tags>
<li>ConsciousnessSource</li>
</tags>
<solid>false</solid>
<bleedRate>2</bleedRate>
</BodyPartDef>
<BodyPartDef>
<defName>WULA_Skeleton_Bodypart</defName>
<label>合金骨架</label>
<hitPoints>30</hitPoints>
<defName>ARA_Ovary</defName>
<label>卵巢</label>
<hitPoints>2</hitPoints>
<permanentInjuryChanceFactor>0</permanentInjuryChanceFactor>
<skinCovered>false</skinCovered>
<solid>true</solid>
<bleedRate>0</bleedRate>
<destroyableByDamage>false</destroyableByDamage>
<tags>
<li>ManipulationLimbSegment</li>
</tags>
<solid>false</solid>
<bleedRate>2</bleedRate>
</BodyPartDef>
</Defs>
<BodyPartDef>
<defName>ARA_Acid_sac</defName>
<label>酸囊</label>
<hitPoints>10</hitPoints>
<permanentInjuryChanceFactor>0.1</permanentInjuryChanceFactor>
<skinCovered>false</skinCovered>
<solid>false</solid>
<bleedRate>1.5</bleedRate>
</BodyPartDef>
<BodyPartGroupDef>
<defName>ARA_Genitalias</defName>
<label>女皇生殖器官</label>
<listOrder>120</listOrder>
</BodyPartGroupDef>
<BodyPartGroupDef>
<defName>ARA_Acid_sacs</defName>
<label>酸腺器官</label>
<listOrder>125</listOrder>
</BodyPartGroupDef>
<!-- EN: beetle-like with claw -->
<BodyDef>
<defName>ARA_BeetleLikeWithClaw</defName>
<label>带头颚甲虫类</label> <!-- EN: beetle-like with claw -->
<corePart>
<def>Shell</def>
<customLabel></customLabel> <!-- EN: shell -->
<height>Middle</height>
<depth>Outside</depth>
<parts>
<li>
<def>Elytra</def>
<customLabel>左鞘翅</customLabel> <!-- EN: left elytra -->
<coverage>0.05</coverage>
</li>
<li>
<def>Elytra</def>
<customLabel>右鞘翅</customLabel> <!-- EN: right elytra -->
<coverage>0.05</coverage>
</li>
<li>
<def>Stomach</def>
<coverage>0.05</coverage>
<depth>Inside</depth>
</li>
<li>
<def>InsectHeart</def>
<customLabel>心脏</customLabel> <!-- EN: heart -->
<coverage>0.03</coverage>
<depth>Inside</depth>
</li>
<li>
<def>Pronotum</def>
<customLabel>前胸背板</customLabel> <!-- EN: pronotum -->
<coverage>0.18</coverage>
<height>Top</height>
<parts>
<li>
<def>InsectHead</def>
<customLabel></customLabel> <!-- EN: head -->
<coverage>0.65</coverage>
<groups>
<li>HeadAttackTool</li>
</groups>
<parts>
<li>
<def>Brain</def>
<coverage>0.2</coverage>
<depth>Inside</depth>
</li>
<li>
<def>Eye</def>
<customLabel>左眼</customLabel> <!-- EN: left eye -->
<coverage>0.12</coverage>
</li>
<li>
<def>Eye</def>
<customLabel>右眼</customLabel> <!-- EN: right eye -->
<coverage>0.12</coverage>
</li>
<li>
<def>Antenna</def>
<customLabel>左触角</customLabel> <!-- EN: left antenna -->
<coverage>0.08</coverage>
</li>
<li>
<def>Antenna</def>
<customLabel>右触角</customLabel> <!-- EN: right antenna -->
<coverage>0.08</coverage>
</li>
<li>
<def>InsectNostril</def>
<customLabel></customLabel> <!-- EN: nostril -->
<coverage>0.06</coverage>
</li>
<li>
<def>InsectMouth</def>
<customLabel>口器</customLabel> <!-- EN: mouth -->
<coverage>0.08</coverage>
<groups>
<li>Mouth</li>
</groups>
</li>
<li>
<def>HeadClaw</def>
<customLabel>头颚</customLabel> <!-- EN: head claw -->
<coverage>0.15</coverage>
<groups>
<li>HeadClaw</li>
</groups>
</li>
</parts>
</li>
</parts>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左前肢</customLabel> <!-- EN: front left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右前肢</customLabel> <!-- EN: front right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左中肢</customLabel> <!-- EN: middle left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右中肢</customLabel> <!-- EN: middle right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左后肢</customLabel> <!-- EN: rear left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右后肢</customLabel> <!-- EN: rear right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
</parts>
</corePart>
</BodyDef>
</Defs>

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!-- EN: beetle-like with claw -->
<BodyDef>
<defName>ARA_BeetleLikeWithClaw</defName>
<label>带头颚甲虫类</label> <!-- EN: beetle-like with claw -->
<corePart>
<def>Shell</def>
<customLabel></customLabel> <!-- EN: shell -->
<height>Middle</height>
<depth>Outside</depth>
<parts>
<li>
<def>Elytra</def>
<customLabel>左鞘翅</customLabel> <!-- EN: left elytra -->
<coverage>0.05</coverage>
</li>
<li>
<def>Elytra</def>
<customLabel>右鞘翅</customLabel> <!-- EN: right elytra -->
<coverage>0.05</coverage>
</li>
<li>
<def>Stomach</def>
<coverage>0.05</coverage>
<depth>Inside</depth>
</li>
<li>
<def>InsectHeart</def>
<customLabel>心脏</customLabel> <!-- EN: heart -->
<coverage>0.03</coverage>
<depth>Inside</depth>
</li>
<li>
<def>Pronotum</def>
<customLabel>前胸背板</customLabel> <!-- EN: pronotum -->
<coverage>0.18</coverage>
<height>Top</height>
<parts>
<li>
<def>InsectHead</def>
<customLabel></customLabel> <!-- EN: head -->
<coverage>0.65</coverage>
<groups>
<li>HeadAttackTool</li>
</groups>
<parts>
<li>
<def>Brain</def>
<coverage>0.2</coverage>
<depth>Inside</depth>
</li>
<li>
<def>Eye</def>
<customLabel>左眼</customLabel> <!-- EN: left eye -->
<coverage>0.12</coverage>
</li>
<li>
<def>Eye</def>
<customLabel>右眼</customLabel> <!-- EN: right eye -->
<coverage>0.12</coverage>
</li>
<li>
<def>Antenna</def>
<customLabel>左触角</customLabel> <!-- EN: left antenna -->
<coverage>0.08</coverage>
</li>
<li>
<def>Antenna</def>
<customLabel>右触角</customLabel> <!-- EN: right antenna -->
<coverage>0.08</coverage>
</li>
<li>
<def>InsectNostril</def>
<customLabel></customLabel> <!-- EN: nostril -->
<coverage>0.06</coverage>
</li>
<li>
<def>InsectMouth</def>
<customLabel>口器</customLabel> <!-- EN: mouth -->
<coverage>0.08</coverage>
<groups>
<li>Mouth</li>
</groups>
</li>
<li>
<def>HeadClaw</def>
<customLabel>头颚</customLabel> <!-- EN: head claw -->
<coverage>0.15</coverage>
<groups>
<li>HeadClaw</li>
</groups>
</li>
</parts>
</li>
</parts>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左前肢</customLabel> <!-- EN: front left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右前肢</customLabel> <!-- EN: front right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左中肢</customLabel> <!-- EN: middle left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右中肢</customLabel> <!-- EN: middle right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>左后肢</customLabel> <!-- EN: rear left leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
<li>
<def>InsectLeg</def>
<customLabel>右后肢</customLabel> <!-- EN: rear right leg -->
<coverage>0.06</coverage>
<height>Bottom</height>
</li>
</parts>
</corePart>
</BodyDef>
</Defs>

View File

@@ -1,393 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!--<BodyTypeDef Abstract="True" Name="Juvenile">
<headOffset>(0.04, 0.34)</headOffset>
<bedOffset>-0.08</bedOffset>
<bodyNakedGraphicPath>Things/Pawn/Humanlike/Bodies/Naked_Child</bodyNakedGraphicPath>
<bodyDessicatedGraphicPath>Things/Pawn/Humanlike/Bodies/Dessicated/Dessicated_Child</bodyDessicatedGraphicPath>
</BodyTypeDef>
<BodyTypeDef ParentName="Juvenile">
<defName>Baby</defName>
<woundScale>0.5</woundScale>
<bodyGraphicScale>(0.5, 0.5)</bodyGraphicScale>
<woundAnchors>
<li>
<rotation>South</rotation>
<group>Torso</group>
<offset>(0,0,-0.04)</offset>
<range>0.1</range>
<debugColor>(1,0,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftLeg</tag>
<offset>(0.04,0,-0.08)</offset>
<range>0.02</range>
<debugColor>(0,1,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightLeg</tag>
<offset>(-0.04,0,-0.08)</offset>
<range>0.02</range>
<debugColor>(0,0,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftShoulder</tag>
<offset>(0.04,0,0.075)</offset>
<range>0.06</range>
<debugColor>(1,1,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightShoulder</tag>
<offset>(-0.04,0,0.075)</offset>
<range>0.06</range>
<debugColor>(1,0,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<group>FullHead</group>
<offset>(0, 0, 0.15)</offset>
<range>0.07</range>
<layer>Head</layer>
<debugColor>(0,1,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<offset>(-0.0455, 0, 0.215)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<offset>(0.0455, 0, 0.215)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<group>FullHead</group>
<offset>(-0.025, 0, 0.18)</offset>
<range>0.06</range>
<layer>Head</layer>
<debugColor>(0,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<group>Torso</group>
<offset>(0,0,-0.07)</offset>
<range>0.1</range>
<debugColor>(1,0,0,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftShoulder</tag>
<offset>(-0.03,0,0.065)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(1,1,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>LeftLeg</tag>
<offset>(-0.03,0,-0.1)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(0,1,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightShoulder</tag>
<offset>(0.03,0,0.065)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(1,0,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>RightLeg</tag>
<offset>(0.05,0,-0.1)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(0,0,1,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<narrowCrown>true</narrowCrown>
<offset>(0.008, 0, 0.19)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<narrowCrown>true</narrowCrown>
<offset>(-0.008, 0, 0.19)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<offset>(0.06, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<offset>(-0.06, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
</woundAnchors>
<attachPoints>
<li>
<offset>(-.1, 0, .25)</offset>
<type>PlatformRestraint0</type>
</li>
<li>
<offset>(.1, 0, .25)</offset>
<type>PlatformRestraint1</type>
</li>
<li>
<offset>(.1, 0, -.2)</offset>
<type>PlatformRestraint2</type>
</li>
<li>
<offset>(-.1, 0, -.2)</offset>
<type>PlatformRestraint3</type>
</li>
</attachPoints>
<attachPointsDessicated>
<li>
<offset>(-.1, 0, .25)</offset>
<type>PlatformRestraint0</type>
</li>
<li>
<offset>(.1, 0, .25)</offset>
<type>PlatformRestraint1</type>
</li>
<li>
<offset>(.1, 0, -.2)</offset>
<type>PlatformRestraint2</type>
</li>
<li>
<offset>(-.1, 0, -.2)</offset>
<type>PlatformRestraint3</type>
</li>
</attachPointsDessicated>
</BodyTypeDef>
<BodyTypeDef ParentName="Juvenile">
<defName>Child</defName>
<woundScale>0.7</woundScale>
<bodyGraphicScale>(0.6, 0.65)</bodyGraphicScale>
<woundAnchors>
<li>
<rotation>South</rotation>
<group>Torso</group>
<offset>(0,0,-0.07)</offset>
<range>0.1</range>
<debugColor>(1,0,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftLeg</tag>
<offset>(0.05,0,-0.12)</offset>
<range>0.03</range>
<debugColor>(0,1,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightLeg</tag>
<offset>(-0.05,0,-0.12)</offset>
<range>0.03</range>
<debugColor>(0,0,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftShoulder</tag>
<offset>(0.06,0,0.025)</offset>
<range>0.07</range>
<debugColor>(1,1,0,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightShoulder</tag>
<offset>(-0.06,0,0.025)</offset>
<range>0.07</range>
<debugColor>(1,0,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<group>FullHead</group>
<offset>(0, 0, 0.2)</offset>
<range>0.1</range>
<layer>Head</layer>
<debugColor>(0,1,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<offset>(-0.073, 0, 0.18)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>South</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<offset>(0.073, 0, 0.18)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<group>FullHead</group>
<offset>(-0.12, 0, 0.21)</offset>
<range>0.12</range>
<layer>Head</layer>
<debugColor>(0,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<group>Torso</group>
<offset>(0,0,-0.07)</offset>
<range>0.12</range>
<debugColor>(1,0,0,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftShoulder</tag>
<offset>(-0.03,0,0.1)</offset>
<range>0.066</range>
<canMirror>false</canMirror>
<debugColor>(1,1,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>LeftLeg</tag>
<offset>(-0.03,0,-0.13)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(0,1,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightShoulder</tag>
<offset>(0.035,0,0.007)</offset>
<range>0.066</range>
<canMirror>false</canMirror>
<debugColor>(1,0,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>RightLeg</tag>
<offset>(0.05,0,-0.15)</offset>
<range>0.03</range>
<canMirror>false</canMirror>
<debugColor>(0,0,1,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<narrowCrown>true</narrowCrown>
<offset>(0.08, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<narrowCrown>true</narrowCrown>
<offset>(-0.08, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
<li>
<rotation>East</rotation>
<tag>RightEye</tag>
<canMirror>false</canMirror>
<offset>(0.11, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(1,1,1,1)</debugColor>
</li>
<li>
<rotation>West</rotation>
<tag>LeftEye</tag>
<canMirror>false</canMirror>
<offset>(-0.11, 0, 0.2)</offset>
<range>0</range>
<layer>Head</layer>
<debugColor>(0,0,0,1)</debugColor>
</li>
</woundAnchors>
<attachPoints>
<li>
<offset>(-.22, 0, .1)</offset>
<type>PlatformRestraint0</type>
</li>
<li>
<offset>(.22, 0, .1)</offset>
<type>PlatformRestraint1</type>
</li>
<li>
<offset>(.1, 0, -.4)</offset>
<type>PlatformRestraint2</type>
</li>
<li>
<offset>(-.1, 0, -.4)</offset>
<type>PlatformRestraint3</type>
</li>
</attachPoints>
<attachPointsDessicated>
<li>
<offset>(-.22, 0, .1)</offset>
<type>PlatformRestraint0</type>
</li>
<li>
<offset>(.22, 0, .1)</offset>
<type>PlatformRestraint1</type>
</li>
<li>
<offset>(.1, 0, -.4)</offset>
<type>PlatformRestraint2</type>
</li>
<li>
<offset>(-.1, 0, -.4)</offset>
<type>PlatformRestraint3</type>
</li>
</attachPointsDessicated>
</BodyTypeDef> -->
<BodyTypeDef>
<defName>ARA_QUEEN_Thin</defName>
<headOffset>(0.09, 0.34)</headOffset>
@@ -579,5 +191,4 @@
</li>
</attachPointsDessicated>
</BodyTypeDef>
</Defs>

View File

@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>ARA_AcidCoverd</defName>
<label>虫族酸液</label>
<description>你的身上沾上了虫族强酸,可能会痛一会</description>
<label>阿拉克涅酸液</label>
<description>一支拥有酸囊的阿拉克涅虫族向此人喷射了强酸,沾染的液体将使得此人痛不欲生,盔甲和表皮软化,并持续灼烧它的身体</description>
<defaultLabelColor>(1, 1, 0.8)</defaultLabelColor>
<hediffClass>ArachnaeSwarm.HediffCurseFlame</hediffClass>
<comps>
@@ -18,8 +17,8 @@
</comps>
<modExtensions>
<li Class="ArachnaeSwarm.CurseFlameModExt">
<damageDefName>ARA_AcidBurn</damageDefName>
<damageRange>1~5</damageRange>
<damageDefName>AcidBurn</damageDefName>
<damageRange>1~2</damageRange>
<damageIntervalTicks>40</damageIntervalTicks>
</li>
</modExtensions>
@@ -85,5 +84,4 @@
</li>
</stages>
</HediffDef>
</Defs>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>ARA_HiveMindMaster</defName>
<label>阿拉克涅主巢</label>
<description>虫群意识的中心节点, 作为主脑统御整个阿拉克涅虫群.</description>
<hediffClass>ArachnaeSwarm.Hediff_HiveMindMaster</hediffClass>
<defaultLabelColor>(0.8, 0.3, 0.8)</defaultLabelColor>
<isBad>false</isBad>
<scenarioCanAdd>true</scenarioCanAdd>
<maxSeverity>100</maxSeverity>
<stages>
<li>
<label>连接至 {0} 个虫群工蜂</label>
<minSeverity>0</minSeverity>
<!-- Stat offsets will be added here later -->
<disablesNeeds>
<li>Joy</li>
<li>Beauty</li>
<li>Comfort</li>
<li>Outdoors</li>
<li>Chemical_Alcohol</li>
</disablesNeeds>
<enablesNeeds>
<li>Indoors</li>
</enablesNeeds>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_HiveMindDrone</defName>
<label>阿拉克涅工蜂</label>
<description>阿拉克涅工蜂通过心灵与阿拉克涅女皇种相链接。如果女皇死亡,工蜂也将停止生命活动。</description>
<hediffClass>ArachnaeSwarm.Hediff_HiveMindDrone</hediffClass>
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
<isBad>false</isBad>
<scenarioCanAdd>true</scenarioCanAdd>
<comps>
<li Class="ArachnaeSwarm.HediffCompProperties_HiveMindDrone">
<unlinkedDieDelayTicks>6400</unlinkedDieDelayTicks> <!-- Default to 30 seconds -->
</li>
<li Class="HediffCompProperties_MessageAfterTicks">
<ticks>1</ticks>
<letterLabel>{0_labelShort} 诞生</letterLabel>
<letterText>一只新的阿拉克涅督虫 {0_labelShort} 已经破茧而出!她正在四处徘徊,等待女皇种与其建立链接——使用阿拉克涅女皇种的信息素标记技能完成链接,否则督虫将在一段时间后死亡!</letterText>
<letterType>HumanPregnancy</letterType>
</li>
</comps>
<stages>
</stages>
</HediffDef>
</Defs>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<![CDATA[
<DutyDef>
<defName>ARA_DefendAndExpandHive</defName>
<thinkNode Class="ThinkNode_Priority">
<subNodes>
<li Class="JobGiver_HiveDefense">
<needLOSToAcquireNonPawnTargets>true</needLOSToAcquireNonPawnTargets>
<targetAcquireRadius>30</targetAcquireRadius>
<chaseTarget>false</chaseTarget>
</li>
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbHours>2.5</mtbHours>
<subNodes>
<li Class="ArachnaeSwarm.JobGiver_MaintainBuildings">
<maintainableThingDefs>
<li>ARA_InteractiveEggSac</li> <!-- 默认维护Hive -->
</maintainableThingDefs>
</li>
</subNodes>
</li>
<li Class="ArachnaeSwarm.JobGiver_MaintainBuildings">
<maintainableThingDefs>
<li>ARA_InteractiveEggSac</li> <!-- 默认维护Hive -->
</maintainableThingDefs>
<onlyIfDamagingState>true</onlyIfDamagingState>
</li>
<li Class="ThinkNode_ConditionalBodySize">
<min>0.7</min>
<subNodes>
<li Class="ThinkNode_ConditionalHiveCanReproduce">
<subNodes>
<li Class="ThinkNode_ChancePerHour_InsectDigChance">
<subNodes>
<li Class="JobGiver_MineRandom" />
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="ThinkNode_PrioritySorter">
<subNodes>
<li Class="JobGiver_GetFood" />
<li Class="JobGiver_GetRest" />
</subNodes>
</li>
</subNodes>
</li>
<li Class="JobGiver_WanderHive">
<maxDanger>Deadly</maxDanger>
</li>
</subNodes>
</thinkNode>
</DutyDef>
]]>
</Defs>

View File

@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>ARA_IncubateJob</defName>
<driverClass>ArachnaeSwarm.JobDriver_Incubate</driverClass>
<reportString>incubating TargetA.</reportString>
<reportString> TargetA 注入信息素.</reportString>
</JobDef>
</Defs>

View File

@@ -15,4 +15,19 @@
</silhouetteGraphicData>
</LifeStageDef>
<LifeStageDef>
<defName>ArachnaeNode_Myrmecocystus_Adult</defName>
<label>adult</label>
<workerClass MayRequire="Ludeon.RimWorld.Biotech">LifeStageWorker_HumanlikeAdult</workerClass>
<visible>false</visible>
<reproductive>true</reproductive>
<sittingOffset>0.18</sittingOffset>
<silhouetteGraphicData>
<texPath>Things/Pawn/Humanlike/Silhouettes/Silhouette_HumanAdult</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1</drawSize>
</silhouetteGraphicData>
<milkable>true</milkable>
</LifeStageDef>
</Defs>

View File

@@ -1,22 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<PawnKindDef Name="ArachnaeQueenBasePawnKind" Abstract="True">
<race>ArachnaeQueen_Race</race>
<combatPower>30</combatPower>
<combatPower>500</combatPower>
<isFighter>true</isFighter>
<trader>false</trader>
<chemicalAddictionChance>0</chemicalAddictionChance>
<apparelIgnoreSeasons>true</apparelIgnoreSeasons>
<forceNormalGearQuality>true</forceNormalGearQuality>
<initialWillRange>2~40</initialWillRange>
<initialResistanceRange>2~40</initialResistanceRange>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<maxGenerationAge>30</maxGenerationAge>
<!-- <minGenerationAge>4</minGenerationAge> -->
<minGenerationAge>10</minGenerationAge>
<canBeScattered>false</canBeScattered>
<abilities>
<li>ARA_EggSpew</li>
<li>ARA_AcidSprayBurst</li>
<li>ARA_BindDrone</li>
</abilities>
<xenotypeSet>
<xenotypeChances>
@@ -42,10 +41,10 @@
<startingHediffs>
</startingHediffs>
</PawnKindDef>
<PawnKindDef Name="ArachnaeQueen_Colonist" ParentName="ArachnaeQueenBasePawnKind">
<defName>ARA_ArachnaeQueen</defName>
<label>阿拉克涅女皇种</label>
<race>ArachnaeQueen_Race</race>
<defaultFactionType>PlayerColony</defaultFactionType>
<invNutrition>2.55</invNutrition>
<backstoryFiltersOverride>
@@ -60,4 +59,61 @@
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
<PawnKindDef Name="ArachnaeNodeABasePawnKind" Abstract="True">
<combatPower>50</combatPower>
<isFighter>true</isFighter>
<trader>false</trader>
<chemicalAddictionChance>0</chemicalAddictionChance>
<apparelIgnoreSeasons>true</apparelIgnoreSeasons>
<forceNormalGearQuality>true</forceNormalGearQuality>
<initialWillRange>99~99</initialWillRange>
<initialResistanceRange>99~99</initialResistanceRange>
<maxGenerationAge>30</maxGenerationAge>
<minGenerationAge>10</minGenerationAge>
<canBeScattered>false</canBeScattered>
<abilities>
</abilities>
<xenotypeSet>
<xenotypeChances>
<Baseliner MayRequire="Ludeon.RimWorld.Biotech">0</Baseliner>
<Dirtmole MayRequire="Ludeon.RimWorld.Biotech">0</Dirtmole>
<Genie MayRequire="Ludeon.RimWorld.Biotech">0</Genie>
<Hussar MayRequire="Ludeon.RimWorld.Biotech">0</Hussar>
<Sanguophage MayRequire="Ludeon.RimWorld.Biotech">0</Sanguophage>
<Neanderthal MayRequire="Ludeon.RimWorld.Biotech">0</Neanderthal>
<Pigskin MayRequire="Ludeon.RimWorld.Biotech">0</Pigskin>
<Impid MayRequire="Ludeon.RimWorld.Biotech">0</Impid>
<Waster MayRequire="Ludeon.RimWorld.Biotech">0</Waster>
<Yttakin MayRequire="Ludeon.RimWorld.Biotech">0</Yttakin>
<Highmate MayRequire="Ludeon.RimWorld.Biotech">0</Highmate>
</xenotypeChances>
</xenotypeSet>
<useFactionXenotypes>false</useFactionXenotypes>
<requiredWorkTags>
<li>Violent</li>
</requiredWorkTags>
<startingHediffs>
</startingHediffs>
</PawnKindDef>
<PawnKindDef Name="ArachnaeNodeA_Colonist" ParentName="ArachnaeNodeABasePawnKind">
<defName>ArachnaeNode_Race_Myrmecocystus</defName>
<label>阿拉克涅蜜罐种</label>
<race>ArachnaeNode_Race_Myrmecocystus</race>
<defaultFactionType>PlayerColony</defaultFactionType>
<invNutrition>2.55</invNutrition>
<backstoryFiltersOverride>
<li>
<categories>
<li>ArachnaeNode_spawnCategoriesA</li>
<li>ArachnaeNode_spawnCategories_Myrmecocystus</li>
</categories>
</li>
</backstoryFiltersOverride>
<apparelTags>
</apparelTags>
<apparelMoney>0</apparelMoney>
</PawnKindDef>
</Defs>

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="BaseInsect">
<defName>ArachnaeBase_Race_Scavenger</defName>
<label>阿拉克涅食腐虫</label>
<description>是阿拉克涅食腐虫的描述。</description>
<statBases>
<MoveSpeed>3.65</MoveSpeed>
<ComfyTemperatureMin>-25</ComfyTemperatureMin>
<MarketValue>200</MarketValue>
<LeatherAmount>0</LeatherAmount>
<ArmorRating_Blunt>0.18</ArmorRating_Blunt>
<ArmorRating_Sharp>0.18</ArmorRating_Sharp>
<Wildness>0.3</Wildness>
</statBases>
<uiIconScale>1.1</uiIconScale>
<tools>
<li>
<label>head claw</label>
<capacities>
<li>Cut</li>
</capacities>
<power>7</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadClaw</linkedBodyPartsGroup>
</li>
<li>
<label>head</label>
<capacities>
<li>Blunt</li>
</capacities>
<power>6</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.2</chanceFactor>
</li>
</tools>
<race>
<thinkTreeMain>ARA_InsectWorker</thinkTreeMain>
<body>BeetleLikeWithClaw</body>
<baseHungerRate>0.25</baseHungerRate>
<baseBodySize>0.8</baseBodySize>
<baseHealthScale>1.7</baseHealthScale>
<useMeatFrom>Megaspider</useMeatFrom>
<lifeExpectancy>6</lifeExpectancy>
<trainability>Advanced</trainability>
<specialTrainables>
<li MayRequire="Ludeon.RimWorld.Odyssey">Dig</li>
</specialTrainables>
<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>
<soundMeleeHitPawn>Pawn_Melee_SmallScratch_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_SmallScratch_HitBuilding</soundMeleeHitBuilding>
<soundMeleeMiss>Pawn_Melee_SmallScratch_Miss</soundMeleeMiss>
<headPosPerRotation>
<li>(0.0, 0, 0.14)</li>
<li>(0.07, 0, 0.08)</li>
<li>(0.0, 0, -0.12)</li>
<li>(-0.07, 0, 0.08)</li>
</headPosPerRotation>
<deathAction Class="DeathActionProperties_Vanish">
<workerClass>DeathActionWorker_Vanish</workerClass>
</deathAction>
<mechEnabledWorkTypes Inherit="False">
<li>Hauling</li>
<li>Mining</li>
<li>Construction</li>
<li>Crafting</li>
<li>Smithing</li>
<li>Tailoring</li>
<li>Cooking</li>
<li>Research</li>
<li>PlantCutting</li>
<li>Growing</li>
<li>Cleaning</li>
<li>Doctor</li>
<li>Firefighter</li>
</mechEnabledWorkTypes>
<mechFixedSkillLevel>10</mechFixedSkillLevel>
</race>
<comps>
<li Class="ArachnaeSwarm.CompProperties_WorkForNonMechs"/>
</comps>
<tradeTags>
<li>AnimalInsect</li>
</tradeTags>
</ThingDef>
<PawnKindDef ParentName="InsectKindBase">
<defName>ArachnaeBase_Race_Scavenger</defName>
<label>阿拉克涅食腐虫</label>
<race>ArachnaeBase_Race_Scavenger</race>
<combatPower>75</combatPower>
<ecoSystemWeight>0.35</ecoSystemWeight>
<forceDeathOnDowned>true</forceDeathOnDowned>
<forceNoDeathNotification>true</forceNoDeathNotification>
<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>
</Defs>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<![CDATA[
<!-- 该文件仅做备用 -->
<!-- 定义一个基础的ThingDef作为阿拉克涅Pawn的基类 -->
<ThingDef Name="Arachnae_PawnBase" ParentName="BasePawn" Abstract="True">
<!-- 屠宰产品设置 -->
@@ -39,21 +42,13 @@
<MinimumContainmentStrength MayRequire="Ludeon.RimWorld.Anomaly">120</MinimumContainmentStrength>
</statBases>
</ThingDef>
<!-- 定义阿拉克涅女皇种族继承自Arachnae_PawnBase -->
<AlienRace.ThingDef_AlienRace ParentName="Arachnae_PawnBase" Name="ArachnaeQueenBase">
<!-- 伤害倍数设置 -->
<damageMultipliers>
</damageMultipliers>
<!-- 组件设置 -->
<comps>
</comps>
<!-- 定义名称 -->
<defName>ArachnaeQueen_Race</defName>
<!-- 显示标签 -->
<defName>ArachnaeQueen222_Race</defName>
<label>阿拉克涅女皇种</label>
<!-- 描述 -->
<description>总之是阿拉克涅女皇原型机咯</description>
<description>阿拉克涅女皇种是阿拉克涅虫巢中唯一可以生育督虫的个体,并且是虫巢意识金字塔的核心,肩负着引领阿拉克涅虫群前进的伟大使命。她与麾下的虫族的灵能链接所构成的蜂群意识网络可以使得虫群以极高的效率运转,但是一旦女皇种死亡,其麾下的虫群将全部死亡!</description>
<uiIconScale>1.0</uiIconScale>
<!-- 外星种族设置 -->
<alienRace>
<!-- 通用设置 -->
@@ -65,15 +60,15 @@
<!-- 女性生育能力年龄因子 -->
<femaleFertilityAgeFactor>
<points>
<li>(1, 1)</li>
<li>(9999, 1)</li>
<li>(1, 0)</li>
<li>(9999, 0)</li>
</points>
</femaleFertilityAgeFactor>
<!-- 男性生育能力年龄因子 -->
<maleFertilityAgeFactor>
<points>
<li>(1, 1)</li>
<li>(9999, 1)</li>
<li>(1, 0)</li>
<li>(9999, 0)</li>
</points>
</maleFertilityAgeFactor>
</reproduction>
@@ -204,24 +199,6 @@
</disallowedTraits>
<!-- 强制种族特性条目 -->
<forcedRaceTraitEntries>
<li>
<options>
<li>
<defName Degree="1">Beauty</defName>
</li>
<li>
<defName Degree="2">Beauty</defName>
</li>
</options>
<count>1</count>
<chance>100</chance>
</li>
<li>
<defName Degree="2">NaturalMood</defName>
<chance>100</chance>
<commonalityMale>0</commonalityMale>
<commonalityFemale>100</commonalityFemale>
</li>
</forcedRaceTraitEntries>
<!-- 外星种族部位生成器 -->
@@ -289,7 +266,6 @@
</alienPartGenerator>
</generalSettings>
<!-- 图形路径设置 -->
<graphicPaths> <!-- 纹理 -->
<!-- 皮肤颜色 -->
@@ -297,7 +273,7 @@
<!-- 皮肤着色器 -->
<skinShader>Cutout</skinShader>
<!-- 头部纹理路径 -->
<head>Pawns/General/Invisible/Inv</head>
<head>Pawns/ARA_HiveQueen/Heads/Average_Normal</head>
<!-- 身体纹理路径 -->
<body>Pawns/ARA_HiveQueen/Bodies/Naked_Thin</body>
<!-- 骨骼纹理路径 -->
@@ -488,9 +464,9 @@
</alienRace>
<!-- 基础属性设置 -->
<statBases> <!-- 能力值 -->
<statBases>
<!-- 市场价值 -->
<MarketValue>2000</MarketValue> <!-- 价格 -->
<MarketValue>2000</MarketValue>
<RoyalFavorValue>5</RoyalFavorValue>
<!-- 移动速度 -->
@@ -501,7 +477,7 @@
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<EatingSpeed>2</EatingSpeed>
<!-- 女皇很长时间才需要补充一次食物 -->
<MaxNutrition>5</MaxNutrition>
<MaxNutrition>0.5</MaxNutrition>
<!-- 女皇的负重,设为0以避免女皇能背东西 -->
<CarryingCapacity>0</CarryingCapacity>
@@ -547,107 +523,126 @@
<!-- 工具设置(攻击方式) -->
<tools>
<li>
<label>head claw</label>
<label>头顶</label>
<capacities>
<li>Poke</li>
</capacities>
<power>16</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.01</chanceFactor>
</li>
<li>
<label>踩踏</label>
<capacities>
<li>Blunt</li>
<li>Poke</li>
</capacities>
<power>35</power>
<cooldownTime>2.5</cooldownTime>
<linkedBodyPartsGroup>Legs</linkedBodyPartsGroup>
</li>
<li>
<label>腿部穿刺</label>
<capacities>
<li>Stab</li>
</capacities>
<power>50</power>
<cooldownTime>3</cooldownTime>
<linkedBodyPartsGroup>Legs</linkedBodyPartsGroup>
</li>
<li>
<label>钳击</label>
<capacities>
<li>Cut</li>
</capacities>
<power>30</power>
<cooldownTime>2.6</cooldownTime>
<linkedBodyPartsGroup>HeadClaw</linkedBodyPartsGroup>
</li>
<li>
<label>head</label>
<capacities>
<li>Blunt</li>
</capacities>
<power>14</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.2</chanceFactor>
<linkedBodyPartsGroup>Hands</linkedBodyPartsGroup>
</li>
</tools>
<race>
<!-- 身体类型 -->
<body>ArachnaeQueen_Body</body>
<fleshType>Normal</fleshType>
<!-- 思考树 -->
<thinkTreeMain>Humanlike</thinkTreeMain>
<thinkTreeConstant>HumanlikeConstant</thinkTreeConstant>
<intelligence>Humanlike</intelligence>
<makesFootprints>true</makesFootprints>
<lifeExpectancy>850</lifeExpectancy>
<!-- 肉和皮革的定义 -->
<leatherDef>Leather_Light</leatherDef>
<specificMeatDef>Meat_Megaspider</specificMeatDef>
<nameCategory>HumanStandard</nameCategory>
<bloodDef>Filth_BloodInsect</bloodDef> <!---->
<bloodSmearDef>Filth_BloodSmear</bloodSmearDef>
<!-- 身形大小 -->
<baseBodySize>10</baseBodySize>
<!-- 血量上限 -->
<baseHealthScale>10</baseHealthScale>
<!-- 食物类型,可以在种族限制定义,不需要在这改 -->
<foodType>OmnivoreHuman</foodType>
<!-- 妊娠天数,对女皇来说没啥用 -->
<gestationPeriodDays>60</gestationPeriodDays>
<meatMarketValue>1.85</meatMarketValue>
<renderTree>Humanlike</renderTree>
<!-- 无法被异常尸体锁定 -->
<hasUnnaturalCorpse>false</hasUnnaturalCorpse>
<lifeStageAges>
<li>
<def>EusocialInsectAdult</def>
<soundWounded>Pawn_HiveQueen_Wounded</soundWounded>
<soundDeath>Pawn_HiveQueen_Death</soundDeath>
<soundCall>Pawn_HiveQueen_Call</soundCall>
<soundAngry>Pawn_HiveQueen_Angry</soundAngry>
</li>
</lifeStageAges>
<!-- 什么年龄段可以做什么工作 -->
<lifeStageWorkSettings MayRequire="Ludeon.RimWorld.Biotech">
<Firefighter>0</Firefighter>
<Patient>0</Patient>
<Doctor>0</Doctor>
<PatientBedRest>0</PatientBedRest>
<Childcare MayRequire="Ludeon.RimWorld.Biotech">0</Childcare>
<BasicWorker>0</BasicWorker>
<Warden>0</Warden>
<Handling>0</Handling>
<Cooking>0</Cooking>
<Hunting>0</Hunting>
<Construction>0</Construction>
<Growing>0</Growing>
<Mining>0</Mining>
<PlantCutting>0</PlantCutting>
<Smithing>0</Smithing>
<Tailoring>0</Tailoring>
<Art>0</Art>
<Crafting>0</Crafting>
<Hauling>0</Hauling>
<Cleaning>0</Cleaning>
<Research>0</Research>
<DarkStudy MayRequire="Ludeon.RimWorld.Anomaly">0</DarkStudy>
</lifeStageWorkSettings>
<soundMeleeHitPawn>Pawn_Melee_BigBash_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_BigBash_HitBuilding</soundMeleeHitBuilding>
<soundMeleeMiss>Pawn_Melee_BigBash_Miss</soundMeleeMiss>
<soundMeleeDodge>Pawn_MeleeDodge</soundMeleeDodge>
<!-- 阴影绘制 -->
<specialShadowData>
<volume>(0.3, 0.8, 0.4)</volume>
<offset>(0,0,-0.3)</offset>
</specialShadowData>
<!-- 生成时的年龄曲线 -->
<ageGenerationCurve>
<points>
<li MayRequire="Ludeon.RimWorld.Biotech">(0,0)</li>
<li>(100,0)</li>
<li>(150,1)</li>
<li>(200,0)</li>
</points>
</ageGenerationCurve>
<race>
<!-- 身体类型 -->
<body>ArachnaeQueen_Body</body>
<!-- 思考树 -->
<thinkTreeMain>Humanlike</thinkTreeMain>
<thinkTreeConstant>HumanlikeConstant</thinkTreeConstant>
<intelligence>Humanlike</intelligence>
<makesFootprints>true</makesFootprints>
<lifeExpectancy>300</lifeExpectancy>
<!-- 肉和皮革的定义 -->
<leatherDef>Leather_Light</leatherDef>
<specificMeatDef>Meat_Megaspider</specificMeatDef>
<nameCategory>HumanStandard</nameCategory>
<bloodDef>Filth_BloodInsect</bloodDef>
<bloodSmearDef>Filth_BloodSmear</bloodSmearDef>
<!-- 身形大小 -->
<baseBodySize>10</baseBodySize>
<!-- 血量上限 -->
<baseHealthScale>10</baseHealthScale>
<!-- 食物类型,可以在种族限制定义,不需要在这改 -->
<foodType>OmnivoreHuman</foodType>
<!-- 妊娠天数,对女皇来说没啥用 -->
<gestationPeriodDays>60</gestationPeriodDays>
<meatMarketValue>1.85</meatMarketValue>
<renderTree>Humanlike</renderTree>
<!-- 无法被异常尸体锁定 -->
<hasUnnaturalCorpse>false</hasUnnaturalCorpse>
<lifeStageAges Inherit="False">
<li>
<def>EusocialInsectAdult</def>
<soundWounded>Pawn_HiveQueen_Wounded</soundWounded>
<soundDeath>Pawn_HiveQueen_Death</soundDeath>
<soundCall>Pawn_HiveQueen_Call</soundCall>
<soundAngry>Pawn_HiveQueen_Angry</soundAngry>
</li>
</lifeStageAges>
<!-- 什么年龄段可以做什么工作 -->
<lifeStageWorkSettings MayRequire="Ludeon.RimWorld.Biotech">
<Firefighter>0</Firefighter>
<Patient>0</Patient>
<Doctor>0</Doctor>
<PatientBedRest>0</PatientBedRest>
<Childcare MayRequire="Ludeon.RimWorld.Biotech">0</Childcare>
<BasicWorker>0</BasicWorker>
<Warden>0</Warden>
<Handling>0</Handling>
<Cooking>0</Cooking>
<Hunting>0</Hunting>
<Construction>0</Construction>
<Growing>0</Growing>
<Mining>0</Mining>
<PlantCutting>0</PlantCutting>
<Smithing>0</Smithing>
<Tailoring>0</Tailoring>
<Art>0</Art>
<Crafting>0</Crafting>
<Hauling>0</Hauling>
<Cleaning>0</Cleaning>
<Research>0</Research>
<DarkStudy MayRequire="Ludeon.RimWorld.Anomaly">0</DarkStudy>
</lifeStageWorkSettings>
<soundMeleeHitPawn>Pawn_Melee_BigBash_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_BigBash_HitBuilding</soundMeleeHitBuilding>
<soundMeleeMiss>Pawn_Melee_BigBash_Miss</soundMeleeMiss>
<soundMeleeDodge>Pawn_MeleeDodge</soundMeleeDodge>
<!-- 阴影绘制 -->
<specialShadowData>
<volume>(0.3, 0.8, 0.4)</volume>
<offset>(0,0,-0.3)</offset>
</specialShadowData>
<!-- 生成时的年龄曲线 -->
<ageGenerationCurve>
<points>
<li MayRequire="Ludeon.RimWorld.Biotech">(0,0)</li>
<li>(20,0)</li>
<li>(25,1)</li>
<li>(30,0)</li>
</points>
</ageGenerationCurve>
<hediffGiverSets>
<li>OrganicStandard</li>
@@ -676,18 +671,8 @@
<li MayRequire="Ludeon.RimWorld.Biotech">ImplantIUD</li>
<li MayRequire="Ludeon.RimWorld.Biotech">RemoveIUD</li>
<li MayRequire="Ludeon.RimWorld.Biotech">TerminatePregnancy</li>
</recipes>
<!-- <comps>
<li Class="CompProperties_SpreadSludge">
<mtbTicks>15000</mtbTicks>
<abilityDef>ARA_EggSpew</abilityDef>
</li>
<li Class="CompProperties_LetterOnRevealed">
<label>Hive queen</label>
<text>You've discovered the center of the nest. It's guarded by a massive insect queen!</text>
<letterDef>ThreatBig</letterDef>
</li>
</comps> -->
</recipes>
</AlienRace.ThingDef_AlienRace>
]]>
</Defs>

View File

@@ -0,0 +1,580 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<AlienRace.ThingDef_AlienRace Name="ARA_NodeBase" ParentName="ARA_PawnBase" Abstract="True">
<alienRace>
<!-- 核心设置 -->
<generalSettings>
<!-- 男性生成几率 -->
<maleGenderProbability>0</maleGenderProbability>
<!-- 无视年龄疾病 -->
<immuneToAge>true</immuneToAge>
<!-- 在口角中造成的最大伤害 -->
<maxDamageForSocialfight>4</maxDamageForSocialfight>
<!-- 免疫人类的异形歧视 -->
<immuneToXenophobia>false</immuneToXenophobia>
<!-- 最小的可生成成人背景的年龄 -->
<minAgeForAdulthood>0</minAgeForAdulthood>
<!-- 手术继承自人类 -->
<humanRecipeImport>false</humanRecipeImport>
<!-- 睡觉定义 -->
<canLayDown>true</canLayDown>
<!-- 各种零件定义 -->
<alienPartGenerator Inherit="False">
<!-- 允许的头部 -->
<headTypes Inherit="False">
<li>Female_AverageNormal</li>
<!-- <li>Female_AverageWide</li>
<li>Female_AveragePointy</li> -->
</headTypes>
<!-- 身体类型 -->
<bodyTypes Inherit="False">
<li>Thin</li>
</bodyTypes>
<!-- 颜色设置 -->
<colorChannels Inherit="false">
<!-- 皮肤是特殊的,因为现在由基因定义肤色 -->
<li>
<name>skin</name>
<first Class="AlienRace.ColorGenerator_SkinColorMelanin">
<minMelanin>0</minMelanin>
<maxMelanin>0</maxMelanin>
</first>
</li>
<!-- 头发颜色 -->
<li>
<name>hair</name>
<first Class="ColorGenerator_Options">
<options>
<li>
<weight>15</weight>
<min>(0.4,0.3,0.5)</min>
<max>(0.6,0.1,0.7)</max>
</li>
<li>
<weight>6</weight>
<min>(0.9,0.9,0.9)</min>
<max>(0.9,0.9,0.9)</max>
</li>
<li>
<weight>6</weight>
<min>(1,0.8,0.8)</min>
<max>(1,0.9,0.9)</max>
</li>
<li>
<weight>3</weight>
<min>(1,1,1)</min>
<max>(1,1,1)</max>
</li>
</options>
</first>
</li>
</colorChannels>
<!-- 额外身体部件 -->
<bodyAddons>
</bodyAddons>
<!-- 图像放大 -->
<!-- <borderScale>4</borderScale>
<atlasScale>4</atlasScale> -->
<!-- <customDrawSize>(4,4)</customDrawSize>
<customHeadDrawSize>(1.0,1.0)</customHeadDrawSize>
<customPortraitDrawSize>(2,2)</customPortraitDrawSize> -->
</alienPartGenerator>
<growthAges>
<li>0</li>
</growthAges>
<!-- 年龄工作效率等的覆盖 -->
<ageStatOverrides>
<WorkSpeedGlobal>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</WorkSpeedGlobal>
<ShootingAccuracyChildFactor MayRequire="Ludeon.RimWorld.Biotech">
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</ShootingAccuracyChildFactor>
<MarketValue>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</MarketValue>
<MeleeHitChance>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</MeleeHitChance>
<AimingDelayFactor>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</AimingDelayFactor>
<ArrestSuccessChance>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0, 1)</li>
</points>
</curve>
</ArrestSuccessChance>
</ageStatOverrides>
<!-- 生育设置,将妊娠设为男性来避免开局刷妊娠 -->
<reproduction>
<gestatingGender>Male</gestatingGender>
<femaleFertilityAgeFactor>
<points>
<li>(0,0)</li>
<li>(1,0)</li>
<li>(999,0)</li>
<li>(9999,0)</li>
</points>
</femaleFertilityAgeFactor>
</reproduction>
<growthFactorByAge>
<points>
<li>(0,1)</li>
<li>(12,0.5)</li>
</points>
</growthFactorByAge>
</generalSettings>
<!-- 图形,留空 -->
<graphicPaths>
<!-- 皮肤颜色 -->
<skinColor>(1,1,1,1)</skinColor>
<!-- 皮肤着色器 -->
<skinShader>Cutout</skinShader>
<!-- <body>ArachnaeSwarm/Things/ARA_HiveQueen/Bodies/</body>
<head>ArachnaeSwarm/Things/ARA_HiveQueen/Heads/</head>
<skeleton>Things/Pawn/Humanlike/Bodies/Dessicated/Dessicated_Thin</skeleton>
<stump>ArachnaeSwarm/Things/ARA_HiveQueen/Bodies/</stump> -->
</graphicPaths>
<!-- 风格设置 -->
<styleSettings>
<!-- 头发 -->
<li>
<key>HairDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
<!-- 纹身 -->
<li>
<key>TattooDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
<!-- 胡须 -->
<li>
<key>BeardDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
</styleSettings>
<!-- 种族的允许和禁止特化设置 -->
<raceRestriction>
<!-- 无法拥有的内源性基因 -->
<blackEndoCategories MayRequire="Ludeon.RimWorld.Biotech">
<li MayRequire="Ludeon.RimWorld.Biotech">HairColor</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Melanin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">BodyType</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Ears</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Nose</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Voice</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Headbone</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Head</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Jaw</li>
</blackEndoCategories>
<!-- 无法拥有的Tag基因 -->
<blackGeneTags MayRequire="Ludeon.RimWorld.Biotech">
<li MayRequire="Ludeon.RimWorld.Biotech">EyeColor</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Tail</li>
<li MayRequire="Ludeon.RimWorld.Biotech">BeardStyle</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Fur</li>
</blackGeneTags>
<!-- 无法拥有的基因列表 -->
<blackGeneList>
<li MayRequire="Ludeon.RimWorld.Biotech">Furskin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Brow_Heavy</li>
</blackGeneList>
<!-- 禁止的异形变种 -->
<blackXenotypeList>
<li MayRequire="Ludeon.RimWorld.Biotech">Dirtmole</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Genie</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Hussar</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Sanguophage</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Neanderthal</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Pigskin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Impid</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Waster</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Yttakin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Highmate</li>
</blackXenotypeList>
<!-- 允许的异形类型 -->
<whiteXenotypeList MayRequire="Ludeon.RimWorld.Biotech">
<li MayRequire="Ludeon.RimWorld.Biotech">Baseliner</li>
</whiteXenotypeList>
<onlyUseRaceRestrictedXenotypes>false</onlyUseRaceRestrictedXenotypes>
<!-- 食物列表 -->
<foodList>
</foodList>
<onlyEatRaceRestrictedFood>false</onlyEatRaceRestrictedFood>
<!-- 可以穿戴的衣服 -->
<apparelList>
</apparelList>
<blackApparelList>
<li>Apparel_AdvancedHelmet</li>
<li>Apparel_ArmorHelmetRecon</li>
<li>Apparel_BowlerHat</li>
<li>Apparel_CowboyHat</li>
<li>Apparel_HatHood</li>
<li>Apparel_PowerArmorHelmet</li>
<li>Apparel_PsychicFoilHelmet</li>
<li>Apparel_SimpleHelmet</li>
<li>Apparel_TribalHeaddress</li>
<li>Apparel_Tuque</li>
<li>Apparel_WarMask</li>
<li>Apparel_WarVeil</li>
<li>Apparel_ArmorRecon</li>
<li>Apparel_BasicShirt</li>
<li>Apparel_Cape</li>
<li>Apparel_CollarShirt</li>
<li>Apparel_Duster</li>
<li>Apparel_FlakJacket</li>
<li>Apparel_FlakPants</li>
<li>Apparel_FlakVest</li>
<li>Apparel_Jacket</li>
<li>Apparel_Pants</li>
<li>Apparel_Parka</li>
<li>Apparel_PlateArmor</li>
<li>Apparel_PowerArmor</li>
<li>Apparel_Robe</li>
<li>Apparel_TribalA</li>
<li>Apparel_Sash</li>
<li>Apparel_Bandolier</li>
<li>Apparel_Broadwrap</li>
<li>Apparel_Headwrap</li>
<li>Apparel_Shadecone</li>
<li>Apparel_AuthorityCap</li>
<li>Apparel_Flophat</li>
<li>Apparel_Slicecap</li>
<li>Apparel_Tailcap</li>
<li>Apparel_VisageMask</li>
</blackApparelList>
<!-- 生育能力 -->
<onlyReproduceWithRestrictedRaces>true</onlyReproduceWithRestrictedRaces>
<canReproduce>false</canReproduce>
<!-- 允许的工作台类型,放开以供其他种族使用 -->
<!-- <workGiverList>
<li>WULA_Large_Mechine_proudctor_Bills</li>
</workGiverList> -->
<!-- 允许的特质类型 -->
<traitList>
</traitList>
<blackTraitList>
<li>BodyPurist</li>
<li>Cannibal</li>
<li>CreepyBreathing</li>
<li>DislikesWomen</li>
<li>Gourmand</li>
<li>QuickSleeper</li>
<li>Wimp</li>
<li>Beauty</li>
<li>DrugDesire</li>
<li>Immunity</li>
<li>PsychicSensitivity</li>
</blackTraitList>
</raceRestriction>
<!-- 想法设置 -->
<thoughtSettings>
<!-- 不会产生的想法 -->
<cannotReceiveThoughts>
<li>AteWithoutTable</li>
</cannotReceiveThoughts>
<!-- 该种族特有想法 -->
<restrictedThoughts>
</restrictedThoughts>
</thoughtSettings>
<!-- 关系设置,不会生成任何随机关系 -->
<relationSettings>
<relationChanceModifierLover>0</relationChanceModifierLover>
<relationChanceModifierExLover>0</relationChanceModifierExLover>
<relationChanceModifierFiance>0</relationChanceModifierFiance>
<relationChanceModifierSpouse>0</relationChanceModifierSpouse>
<relationChanceModifierExSpouse>0</relationChanceModifierExSpouse>
<relationChanceModifierParent>0</relationChanceModifierParent>
<relationChanceModifierChild>0</relationChanceModifierChild>
<relationChanceModifierSibling>0</relationChanceModifierSibling>
</relationSettings>
</alienRace>
<!-- 基础属性设置 -->
<statBases>
<!-- 市场价值 -->
<MarketValue>100</MarketValue>
<RoyalFavorValue>5</RoyalFavorValue>
<!-- 移动速度 -->
<MoveSpeed>3</MoveSpeed>
<Mass>50</Mass>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<EatingSpeed>2</EatingSpeed>
<MaxNutrition>0.5</MaxNutrition>
<!-- 女皇的负重,设为0以避免女皇能背东西 -->
<CarryingCapacity>50</CarryingCapacity>
<MeatAmount>150</MeatAmount>
<LeatherAmount>100</LeatherAmount>
<PainShockThreshold>0.85</PainShockThreshold>
<PsychicSensitivity>1.5</PsychicSensitivity>
<MentalBreakThreshold>0</MentalBreakThreshold>
<ToxicResistance>0.5</ToxicResistance>
<ToxicEnvironmentResistance MayRequire="Ludeon.RimWorld.Biotech">0.5</ToxicEnvironmentResistance>
<Flammability>0.1</Flammability>
<MeleeDodgeChance>0.75</MeleeDodgeChance>
<!-- <MeleeHitChance>1</MeleeHitChance> -->
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
<!-- <SocialImpact>1</SocialImpact> -->
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
<ArmorRating_Sharp>0.3</ArmorRating_Sharp>
<ArmorRating_Heat>0.4</ArmorRating_Heat>
<!-- 虫群拥有惊人的愈合速度 -->
<InjuryHealingFactor>5</InjuryHealingFactor>
<!-- 在野外采集的营养 -->
<ForagedNutritionPerDay>0</ForagedNutritionPerDay>
</statBases>
<race>
<!-- <fleshType>WULA_Fleshtype</fleshType> -->
<!-- AI行为勿改 -->
<thinkTreeMain>ARA_Humanlike</thinkTreeMain>
<!-- 智力水平 -->
<intelligence>Humanlike</intelligence>
<!-- 血液,不流血 -->
<bloodDef>Filth_MachineBits</bloodDef>
<!-- 基础血量,很高 -->
<baseHealthScale>1.5</baseHealthScale>
<!-- 解剖产物 -->
<leatherDef>Steel</leatherDef>
<specificMeatDef>Steel</specificMeatDef>
<!-- 身体类型 -->
<body>ArachnaeQueen_Body</body>
<!-- 年龄阶段,较短 -->
<lifeExpectancy>12</lifeExpectancy>
<lifeStageWorkSettings MayRequire="Ludeon.RimWorld.Biotech">
<Firefighter>0</Firefighter>
<Patient>0</Patient>
<Doctor>0</Doctor>
<PatientBedRest>0</PatientBedRest>
<Childcare MayRequire="Ludeon.RimWorld.Biotech">0</Childcare>
<BasicWorker>0</BasicWorker>
<Warden>0</Warden>
<Handling>0</Handling>
<Cooking>0</Cooking>
<Hunting>0</Hunting>
<Construction>0</Construction>
<Growing>0</Growing>
<Mining>0</Mining>
<PlantCutting>0</PlantCutting>
<Smithing>0</Smithing>
<Tailoring>0</Tailoring>
<Art>0</Art>
<Crafting>0</Crafting>
<Hauling>0</Hauling>
<Cleaning>0</Cleaning>
<Research>0</Research>
<DarkStudy MayRequire="Ludeon.RimWorld.Anomaly">0</DarkStudy>
</lifeStageWorkSettings>
<lifeStageAges Inherit="False">
<li>
<def>ARA_Queen_Adult</def>
<minAge>0</minAge>
</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>
</race>
<!-- 工具设置(攻击方式) -->
<tools>
<li>
<label>头顶</label>
<capacities>
<li>Poke</li>
</capacities>
<power>8</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.01</chanceFactor>
</li>
</tools>
<recipes Inherit="False">
</recipes>
<comps>
<!-- <li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.DrawFaceGraphicsComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.HeadControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.EyeballControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.LidControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.BrowControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.MouthControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.SkinControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.FacialAnimationControllerComp</compClass>
</li> -->
<!--<li>
<compClass>FacialAnimation.EmotionControllerComp</compClass>
</li>-->
<!-- <li Class="CompProperties_DrugAddict"/> -->
</comps>
</AlienRace.ThingDef_AlienRace>
<!-- 定义阿拉克涅节点虫种族 -->
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
<defName>ArachnaeNode_Race_Myrmecocystus</defName>
<label>阿拉克涅蜜罐种</label>
<description>阿拉克涅督虫种之一,拥有非常广泛的食谱,可以吞下许多未经处理的生物并将其分解为阿拉克涅虫蜜,以滋养虫群。此外,这种督虫还指挥着三只食腐虫,它们会负责处理各种各样的猎物,并在危急时刻喷射酸液对抗入侵者,以保卫阿拉克涅虫巢的财产。</description>
<alienRace>
<graphicPaths>
<body>ArachnaeSwarm/Things/ARA_Myrmecocystus/Bodies/</body>
<head>ArachnaeSwarm/Things/ARA_Myrmecocystus/Heads/</head>
<skeleton>Things/Pawn/Humanlike/Bodies/Dessicated/Dessicated_Thin</skeleton>
<stump>ArachnaeSwarm/Things/ARA_Myrmecocystus/Bodies/</stump>
</graphicPaths>
</alienRace>
<comps>
<li Class="CompProperties_Milkable">
<milkDef>ARA_InsectJelly</milkDef>
<milkIntervalDays>1</milkIntervalDays>
<milkAmount>14</milkAmount>
</li>
<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>Spelopede</pawnKind>
<count>3</count>
<cooldownTicks>6000</cooldownTicks>
</li>
</productionQueue>
<spawnEffecter>CocoonDestroyed</spawnEffecter>
<!--<spawnedMechEffecter>WarUrchinSpawned</spawnedMechEffecter>-->
</li>
</comps>
<!-- 基础属性设置 -->
<statBases>
<!-- 移动速度 -->
<MoveSpeed>2</MoveSpeed>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<EatingSpeed>5</EatingSpeed>
<MaxNutrition>1</MaxNutrition>
<CarryingCapacity>100</CarryingCapacity>
<MeatAmount>45</MeatAmount>
<LeatherAmount>50</LeatherAmount>
<MeleeDodgeChance>0.5</MeleeDodgeChance>
<!-- <MeleeHitChance>1</MeleeHitChance> -->
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
<!-- <SocialImpact>1</SocialImpact> -->
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>0.18</ArmorRating_Blunt>
<ArmorRating_Sharp>0.27</ArmorRating_Sharp>
<ArmorRating_Heat>0.2</ArmorRating_Heat>
</statBases>
<race>
<foodType>OmnivoreHuman,CarnivoreAnimal,OvivoreAnimal,VegetarianRoughAnimal</foodType>
<!-- 身体类型 -->
<body>BeetleLikeWithClaw</body>
<!-- 身形大小 -->
<baseBodySize>2.5</baseBodySize>
<!-- 血量上限 -->
<baseHealthScale>3</baseHealthScale>
<lifeStageAges Inherit="False">
<li>
<def>ArachnaeNode_Myrmecocystus_Adult</def>
<minAge>0</minAge>
</li>
</lifeStageAges>
</race>
<!-- 工具设置(攻击方式) -->
<tools Inherit="False">
<li>
<label>头颚</label>
<capacities>
<li>Bite</li>
</capacities>
<power>12</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadClaw</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>1</chanceFactor>
</li>
</tools>
</AlienRace.ThingDef_AlienRace>
</Defs>

View File

@@ -0,0 +1,740 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef Abstract="True" Name="ARA_PawnBase" ParentName="BasePawn">
<statBases>
<MarketValue>1750</MarketValue>
<MoveSpeed>4.6</MoveSpeed>
<ComfyTemperatureMin>16</ComfyTemperatureMin>
<ComfyTemperatureMax>26</ComfyTemperatureMax>
<LeatherAmount>75</LeatherAmount>
<RoyalFavorValue>3</RoyalFavorValue>
<Wildness>0.75</Wildness> <!-- Hidden except for wild people -->
</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>
<thinkTreeMain>Humanlike</thinkTreeMain>
<thinkTreeConstant>HumanlikeConstant</thinkTreeConstant>
<intelligence>Humanlike</intelligence>
<makesFootprints>true</makesFootprints>
<lifeExpectancy>80</lifeExpectancy>
<bloodDef>Filth_Blood</bloodDef>
<bloodSmearDef>Filth_BloodSmear</bloodSmearDef>
<leatherDef>Leather_Human</leatherDef>
<nameCategory>HumanStandard</nameCategory>
<body>Human</body>
<renderTree>Humanlike</renderTree>
<baseBodySize>1</baseBodySize>
<baseHealthScale>1</baseHealthScale>
<foodType>OmnivoreHuman</foodType>
<gestationPeriodDays>18</gestationPeriodDays>
<meatMarketValue>0.8</meatMarketValue>
<manhunterOnDamageChance>0.50</manhunterOnDamageChance>
<manhunterOnTameFailChance>0.10</manhunterOnTameFailChance>
<soundCallIntervalRange>2000~5000</soundCallIntervalRange>
<canBecomeShambler>true</canBecomeShambler>
<knowledgeCategory MayRequire="Ludeon.RimWorld.Anomaly">Basic</knowledgeCategory>
<anomalyKnowledge>1</anomalyKnowledge>
<hasUnnaturalCorpse>true</hasUnnaturalCorpse>
<litterSizeCurve>
<points>
<li>(0.5, 0)</li>
<li>(1, 1)</li>
<li>(1.01, 0.02)</li>
<li>(3.5, 0)</li>
</points>
</litterSizeCurve>
<lifeStageAges>
<li>
<def>HumanlikeBaby</def>
<minAge>0</minAge>
</li>
<li>
<def>HumanlikeChild</def>
<minAge>3</minAge>
</li>
<li MayRequire="Ludeon.RimWorld.Biotech">
<def>HumanlikePreTeenager</def>
<minAge>9</minAge>
</li>
<li>
<def>HumanlikeTeenager</def>
<minAge>13</minAge>
</li>
<li>
<def>HumanlikeAdult</def>
<minAge>18</minAge>
</li>
</lifeStageAges>
<lifeStageWorkSettings MayRequire="Ludeon.RimWorld.Biotech">
<Firefighter>7</Firefighter>
<Patient>0</Patient>
<Doctor>10</Doctor>
<PatientBedRest>0</PatientBedRest>
<Childcare MayRequire="Ludeon.RimWorld.Biotech">0</Childcare>
<BasicWorker>3</BasicWorker>
<Warden>10</Warden>
<Handling>7</Handling>
<Cooking>7</Cooking>
<Hunting>7</Hunting>
<Construction>10</Construction>
<Growing>7</Growing>
<Mining>7</Mining>
<PlantCutting>7</PlantCutting>
<Smithing>13</Smithing>
<Tailoring>7</Tailoring>
<Art>10</Art>
<Crafting>7</Crafting>
<Hauling>3</Hauling>
<Cleaning>3</Cleaning>
<Research>13</Research>
<DarkStudy MayRequire="Ludeon.RimWorld.Anomaly">13</DarkStudy>
</lifeStageWorkSettings>
<soundMeleeDodge>Pawn_MeleeDodge</soundMeleeDodge>
<specialShadowData>
<volume>(0.3, 0.8, 0.4)</volume>
<offset>(0,0,-0.3)</offset>
</specialShadowData>
<ageGenerationCurve>
<points>
<li MayRequire="Ludeon.RimWorld.Biotech">(0,0)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(0.001,43)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(8,86)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(12.5,118)</li> <!-- Exclude 12.5-13 years to avoid spawning pawns who are very close to becoming adults -->
<li MayRequire="Ludeon.RimWorld.Biotech">(12.51,0)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(13,0)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(13.001,122)</li> <!-- End exclude -->
<li MayRequire="Ludeon.RimWorld.Biotech">(13.999,130)</li>
<li>(14,0)</li>
<li MayRequire="Ludeon.RimWorld.Biotech">(14.001,130)</li>
<li>(16,100)</li>
<li>(50,100)</li>
<li>(60,30)</li>
<li>(70,18)</li>
<li>(80,10)</li>
<li>(90,3)</li>
<li>(100,0)</li>
</points>
</ageGenerationCurve>
<hediffGiverSets>
<li>OrganicStandard</li>
<li>Human</li>
</hediffGiverSets>
</race>
<recipes>
<li>ExciseCarcinoma</li>
<li>AdministerMechSerumHealer</li>
<li>RemoveBodyPart</li>
<li>Euthanize</li>
<li>Anesthetize</li>
<li>CureScaria</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Vasectomy</li>
<li MayRequire="Ludeon.RimWorld.Biotech">ReverseVasectomy</li>
<li MayRequire="Ludeon.RimWorld.Biotech">TubalLigation</li>
<li MayRequire="Ludeon.RimWorld.Biotech">ExtractOvum</li>
<li MayRequire="Ludeon.RimWorld.Royalty">CureBloodRot</li>
<li MayRequire="Ludeon.RimWorld.Royalty">CureAbasia</li>
<li MayRequire="Ludeon.RimWorld.Biotech">ExtractHemogenPack</li>
<li MayRequire="Ludeon.RimWorld.Biotech">BloodTransfusion</li>
<li MayRequire="Ludeon.RimWorld.Biotech">ImplantXenogerm</li>
<li MayRequire="Ludeon.RimWorld.Biotech">ImplantIUD</li>
<li MayRequire="Ludeon.RimWorld.Biotech">RemoveIUD</li>
<li MayRequire="Ludeon.RimWorld.Biotech">TerminatePregnancy</li>
<li MayRequire="Ludeon.RimWorld.Anomaly">SurgicalInspection</li>
<li MayRequire="Ludeon.RimWorld.Anomaly">BlissLobotomy</li>
<li MayRequire="Ludeon.RimWorld.Anomaly">GhoulInfusion</li>
<li MayRequire="Ludeon.RimWorld.Odyssey">RemovePorcupineQuill</li>
</recipes>
<ingredient>
<mergeCompatibilityTags>
<li>HumanMeat</li>
</mergeCompatibilityTags>
</ingredient>
<comps>
<li MayRequire="Ludeon.RimWorld.Anomaly" Class="CompProperties_HoldingPlatformTarget">
<baseEscapeIntervalMtbDays>120</baseEscapeIntervalMtbDays>
<getsColdContainmentBonus>true</getsColdContainmentBonus>
</li>
<li MayRequire="Ludeon.RimWorld.Anomaly" Class="CompProperties_Studiable">
<frequencyTicks>120000</frequencyTicks>
<minMonolithLevelForStudy>1</minMonolithLevelForStudy>
<requiresImprisonment>true</requiresImprisonment>
</li>
</comps>
</ThingDef>
<AlienRace.ThingDef_AlienRace Name="ARA_QueenBase" ParentName="ARA_PawnBase">
<defName>ArachnaeQueen_Race</defName>
<label>阿拉克涅女皇种</label>
<description>阿拉克涅女皇种是阿拉克涅虫巢中唯一可以生育督虫的个体,并且是虫巢意识金字塔的核心,肩负着引领阿拉克涅虫群前进的伟大使命。她与麾下的虫族的灵能链接所构成的蜂群意识网络可以使得虫群以极高的效率运转,但是一旦女皇种死亡,其麾下的虫群将全部死亡!</description>
<alienRace>
<!-- 核心设置 -->
<generalSettings>
<!-- 男性生成几率 -->
<maleGenderProbability>0</maleGenderProbability>
<!-- 无视年龄疾病 -->
<immuneToAge>true</immuneToAge>
<!-- 在口角中造成的最大伤害 -->
<maxDamageForSocialfight>15</maxDamageForSocialfight>
<!-- 免疫人类的异形歧视 -->
<immuneToXenophobia>false</immuneToXenophobia>
<!-- 最小的可生成成人背景的年龄 -->
<minAgeForAdulthood>0</minAgeForAdulthood>
<!-- 手术继承自人类 -->
<humanRecipeImport>false</humanRecipeImport>
<!-- 睡觉定义 -->
<canLayDown>false</canLayDown>
<!-- 各种零件定义 -->
<alienPartGenerator Inherit="False">
<!-- 允许的头部 -->
<headTypes Inherit="False">
<li>Female_AverageNormal</li>
<!-- <li>Female_AverageWide</li>
<li>Female_AveragePointy</li> -->
</headTypes>
<!-- 身体类型 -->
<bodyTypes Inherit="False">
<li>Thin</li>
</bodyTypes>
<!-- 颜色设置 -->
<colorChannels Inherit="false">
<!-- 皮肤是特殊的,因为现在由基因定义肤色 -->
<li>
<name>skin</name>
<first Class="AlienRace.ColorGenerator_SkinColorMelanin">
<minMelanin>0</minMelanin>
<maxMelanin>0</maxMelanin>
</first>
</li>
<!-- 头发颜色 -->
<li>
<name>hair</name>
<first Class="ColorGenerator_Options">
<options>
<li>
<weight>15</weight>
<min>(0.4,0.3,0.5)</min>
<max>(0.6,0.1,0.7)</max>
</li>
<li>
<weight>6</weight>
<min>(0.9,0.9,0.9)</min>
<max>(0.9,0.9,0.9)</max>
</li>
<li>
<weight>6</weight>
<min>(1,0.8,0.8)</min>
<max>(1,0.9,0.9)</max>
</li>
<li>
<weight>3</weight>
<min>(1,1,1)</min>
<max>(1,1,1)</max>
</li>
</options>
</first>
</li>
</colorChannels>
<!-- 额外身体部件 -->
<bodyAddons>
</bodyAddons>
<!-- 图像放大 -->
<borderScale>4</borderScale>
<atlasScale>4</atlasScale>
<customDrawSize>(4,4)</customDrawSize>
<customHeadDrawSize>(1.0,1.0)</customHeadDrawSize>
<customPortraitDrawSize>(2,2)</customPortraitDrawSize>
</alienPartGenerator>
<growthAges>
<li>0</li>
</growthAges>
<!-- 年龄工作效率等的覆盖 -->
<ageStatOverrides>
<WorkSpeedGlobal>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</WorkSpeedGlobal>
<ShootingAccuracyChildFactor MayRequire="Ludeon.RimWorld.Biotech">
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</ShootingAccuracyChildFactor>
<MarketValue>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</MarketValue>
<MeleeHitChance>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</MeleeHitChance>
<AimingDelayFactor>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0,1)</li>
</points>
</curve>
</AimingDelayFactor>
<ArrestSuccessChance>
<useBiologicalYears>true</useBiologicalYears>
<curve>
<points>
<li>(0, 1)</li>
</points>
</curve>
</ArrestSuccessChance>
</ageStatOverrides>
<!-- 生育设置,将妊娠设为男性来避免开局刷妊娠 -->
<reproduction>
<gestatingGender>Male</gestatingGender>
<femaleFertilityAgeFactor>
<points>
<li>(0,0)</li>
<li>(1,0)</li>
<li>(999,0)</li>
<li>(9999,0)</li>
</points>
</femaleFertilityAgeFactor>
</reproduction>
<growthFactorByAge>
<points>
<li>(0,0)</li>
<li>(1,0)</li>
<li>(999,0)</li>
<li>(9999,0)</li>
</points>
</growthFactorByAge>
</generalSettings>
<!-- 图形 -->
<graphicPaths>
<!-- 皮肤颜色 -->
<skinColor>(1,1,1,1)</skinColor>
<!-- 皮肤着色器 -->
<skinShader>Cutout</skinShader>
<body>ArachnaeSwarm/Things/ARA_HiveQueen/Bodies/</body>
<head>ArachnaeSwarm/Things/ARA_HiveQueen/Heads/</head>
<skeleton>Things/Pawn/Humanlike/Bodies/Dessicated/Dessicated_Thin</skeleton>
<stump>ArachnaeSwarm/Things/ARA_HiveQueen/Bodies/</stump>
</graphicPaths>
<!-- 风格设置 -->
<styleSettings>
<!-- 头发 -->
<li>
<key>HairDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
<!-- 纹身 -->
<li>
<key>TattooDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
<!-- 胡须 -->
<li>
<key>BeardDef</key>
<value>
<hasStyle>false</hasStyle>
</value>
</li>
</styleSettings>
<!-- 种族的允许和禁止特化设置 -->
<raceRestriction>
<!-- 无法拥有的内源性基因 -->
<blackEndoCategories MayRequire="Ludeon.RimWorld.Biotech">
<li MayRequire="Ludeon.RimWorld.Biotech">HairColor</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Melanin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">BodyType</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Ears</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Nose</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Voice</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Headbone</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Head</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Jaw</li>
</blackEndoCategories>
<!-- 无法拥有的Tag基因 -->
<blackGeneTags MayRequire="Ludeon.RimWorld.Biotech">
<li MayRequire="Ludeon.RimWorld.Biotech">EyeColor</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Tail</li>
<li MayRequire="Ludeon.RimWorld.Biotech">BeardStyle</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Fur</li>
</blackGeneTags>
<!-- 无法拥有的基因列表 -->
<blackGeneList>
<li MayRequire="Ludeon.RimWorld.Biotech">Furskin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Brow_Heavy</li>
</blackGeneList>
<!-- 禁止的异形变种 -->
<blackXenotypeList>
<li MayRequire="Ludeon.RimWorld.Biotech">Dirtmole</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Genie</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Hussar</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Sanguophage</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Neanderthal</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Pigskin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Impid</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Waster</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Yttakin</li>
<li MayRequire="Ludeon.RimWorld.Biotech">Highmate</li>
</blackXenotypeList>
<!-- 异种类型列表 -->
<xenotypeList>
</xenotypeList>
<onlyUseRaceRestrictedXenotypes>true</onlyUseRaceRestrictedXenotypes>
<!-- 食物列表 -->
<foodList>
</foodList>
<onlyEatRaceRestrictedFood>false</onlyEatRaceRestrictedFood>
<!-- 可以穿戴的衣服 -->
<apparelList>
</apparelList>
<blackApparelList>
</blackApparelList>
<!-- 仅使用种族限制的服装 -->
<onlyUseRaceRestrictedApparel>true</onlyUseRaceRestrictedApparel>
<!-- 生育能力 -->
<onlyReproduceWithRestrictedRaces>true</onlyReproduceWithRestrictedRaces>
<canReproduce>false</canReproduce>
<!-- 允许的工作台类型,放开以供其他种族使用 -->
<!-- <workGiverList>
<li>WULA_Large_Mechine_proudctor_Bills</li>
</workGiverList> -->
<!-- 允许的特质类型 -->
<traitList>
</traitList>
<blackTraitList>
<li>BodyPurist</li>
<li>Cannibal</li>
<li>CreepyBreathing</li>
<li>DislikesWomen</li>
<li>Gourmand</li>
<li>QuickSleeper</li>
<li>Wimp</li>
<li>Beauty</li>
<li>DrugDesire</li>
<li>Immunity</li>
<li>PsychicSensitivity</li>
</blackTraitList>
</raceRestriction>
<!-- 想法设置 -->
<thoughtSettings>
<!-- 不会产生的想法 -->
<cannotReceiveThoughts>
<li>Naked</li>
<li>ApparelDamaged</li>
<li>ProsthophileHappy</li>
<li>ProsthophobeUnhappy</li>
<li>BrawlerUnhappy</li>
<li>PyromaniacHappy</li>
<li>Greedy</li>
<li>Jealous</li>
<li>SharedBed</li>
<li>AteWithoutTable</li>
<li>SleptOutside</li>
<li>SleptOnGround</li>
<li>SleptInCold</li>
<li>SleptInHeat</li>
<li>Ugly</li>
<li>AteKibble</li>
<li>AteInsectMeatDirect</li>
<li>AteInsectMeatAsIngredient</li>
<li>AteRawFood</li>
<li>AteHumanlikeMeatDirect</li>
<li>AteHumanlikeMeatAsIngredient</li>
<li>KnowButcheredHumanlikeCorpse</li>
<li>ButcheredHumanlikeCorpseOpinion</li>
<li>AteRawHumanlikeMeat</li>
</cannotReceiveThoughts>
<!-- 该种族特有想法 -->
<restrictedThoughts>
</restrictedThoughts>
</thoughtSettings>
<!-- 关系设置,不会生成任何随机关系 -->
<relationSettings>
<relationChanceModifierLover>0</relationChanceModifierLover>
<relationChanceModifierExLover>0</relationChanceModifierExLover>
<relationChanceModifierFiance>0</relationChanceModifierFiance>
<relationChanceModifierSpouse>0</relationChanceModifierSpouse>
<relationChanceModifierExSpouse>0</relationChanceModifierExSpouse>
<relationChanceModifierParent>0</relationChanceModifierParent>
<relationChanceModifierChild>0</relationChanceModifierChild>
<relationChanceModifierSibling>0</relationChanceModifierSibling>
</relationSettings>
</alienRace>
<!-- 基础属性设置 -->
<statBases>
<!-- 市场价值 -->
<MarketValue>2000</MarketValue>
<RoyalFavorValue>5</RoyalFavorValue>
<!-- 移动速度 -->
<MoveSpeed>1.75</MoveSpeed>
<Mass>250</Mass>
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
<EatingSpeed>2</EatingSpeed>
<!-- 女皇很长时间才需要补充一次食物 -->
<MaxNutrition>0.5</MaxNutrition>
<!-- 女皇的负重,设为0以避免女皇能背东西 -->
<CarryingCapacity>0</CarryingCapacity>
<MeatAmount>450</MeatAmount>
<LeatherAmount>600</LeatherAmount>
<!-- 疼痛休克,女皇很难因为疼痛而倒下,虽并不是像机器人一样不会休克 -->
<PainShockThreshold>1</PainShockThreshold>
<!-- 女皇非常擅长灵能,以维持蜂群的蜂巢意识链接 -->
<PsychicSensitivity>5</PsychicSensitivity>
<!-- 女皇的崩溃概率 -->
<MentalBreakThreshold>0</MentalBreakThreshold>
<!-- 女皇的高耸身躯和强健循环系统使得很难被毒倒下 -->
<ToxicResistance>0.95</ToxicResistance>
<ToxicEnvironmentResistance MayRequire="Ludeon.RimWorld.Biotech">0.95</ToxicEnvironmentResistance>
<!-- 女皇的甲壳可以抵御火焰侵袭,难以燃烧-->
<Flammability>0.1</Flammability>
<!-- 女皇的庞大申请很难闪开近战 -->
<MeleeDodgeChance>0.25</MeleeDodgeChance>
<!-- <MeleeHitChance>1</MeleeHitChance> -->
<!-- <NegotiationAbility>1</NegotiationAbility> -->
<!-- <SellPriceFactor>1</SellPriceFactor> -->
<!-- <SocialImpact>1</SocialImpact> -->
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
<!-- 自带的甲壳可以防御外部攻击 -->
<ArmorRating_Blunt>0.6</ArmorRating_Blunt>
<ArmorRating_Sharp>0.8</ArmorRating_Sharp>
<ArmorRating_Heat>0.5</ArmorRating_Heat>
<!-- 虫群拥有惊人的愈合速度 -->
<InjuryHealingFactor>5</InjuryHealingFactor>
<!-- 在野外采集的营养 -->
<ForagedNutritionPerDay>0</ForagedNutritionPerDay>
</statBases>
<race>
<!-- 身体类型 -->
<body>ArachnaeQueen_Body</body>
<fleshType>Normal</fleshType>
<!-- AI行为勿改 -->
<thinkTreeMain>ARA_Humanlike</thinkTreeMain>
<!-- 智力水平 -->
<intelligence>Humanlike</intelligence>
<!-- 肉和皮革的定义 -->
<leatherDef>Leather_Light</leatherDef>
<specificMeatDef>Meat_Megaspider</specificMeatDef>
<nameCategory>HumanStandard</nameCategory>
<bloodDef>Filth_BloodInsect</bloodDef>
<bloodSmearDef>Filth_BloodSmear</bloodSmearDef>
<!-- 身形大小 -->
<baseBodySize>10</baseBodySize>
<!-- 基础血量,很高 -->
<baseHealthScale>10</baseHealthScale>
<!-- 解剖产物 -->
<leatherDef>Steel</leatherDef>
<specificMeatDef>Steel</specificMeatDef>
<soundMeleeHitPawn>Pawn_Melee_BigBash_HitPawn</soundMeleeHitPawn>
<soundMeleeHitBuilding>Pawn_Melee_BigBash_HitBuilding</soundMeleeHitBuilding>
<soundMeleeMiss>Pawn_Melee_BigBash_Miss</soundMeleeMiss>
<soundMeleeDodge>Pawn_MeleeDodge</soundMeleeDodge>
<!-- 年龄阶段 -->
<!-- <lifeExpectancy>5000</lifeExpectancy> -->
<lifeStageWorkSettings MayRequire="Ludeon.RimWorld.Biotech">
<Firefighter>0</Firefighter>
<Patient>0</Patient>
<Doctor>0</Doctor>
<PatientBedRest>0</PatientBedRest>
<Childcare MayRequire="Ludeon.RimWorld.Biotech">0</Childcare>
<BasicWorker>0</BasicWorker>
<Warden>0</Warden>
<Handling>0</Handling>
<Cooking>0</Cooking>
<Hunting>0</Hunting>
<Construction>0</Construction>
<Growing>0</Growing>
<Mining>0</Mining>
<PlantCutting>0</PlantCutting>
<Smithing>0</Smithing>
<Tailoring>0</Tailoring>
<Art>0</Art>
<Crafting>0</Crafting>
<Hauling>0</Hauling>
<Cleaning>0</Cleaning>
<Research>0</Research>
<DarkStudy MayRequire="Ludeon.RimWorld.Anomaly">0</DarkStudy>
</lifeStageWorkSettings>
<lifeStageAges Inherit="False">
<li>
<def>ARA_Queen_Adult</def>
<minAge>0</minAge>
<soundWounded>Pawn_HiveQueen_Wounded</soundWounded>
<soundDeath>Pawn_HiveQueen_Death</soundDeath>
<soundCall>Pawn_HiveQueen_Call</soundCall>
<soundAngry>Pawn_HiveQueen_Angry</soundAngry>
</li>
</lifeStageAges>
<canFlyInVacuum>false</canFlyInVacuum>
</race>
<!-- 工具设置(攻击方式) -->
<tools>
<li>
<label>头顶</label>
<capacities>
<li>Poke</li>
</capacities>
<power>16</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
<ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
<chanceFactor>0.01</chanceFactor>
</li>
<li>
<label>踩踏</label>
<capacities>
<li>Blunt</li>
<li>Poke</li>
</capacities>
<power>35</power>
<cooldownTime>2.5</cooldownTime>
<linkedBodyPartsGroup>Legs</linkedBodyPartsGroup>
</li>
<li>
<label>腿部穿刺</label>
<capacities>
<li>Stab</li>
</capacities>
<power>50</power>
<cooldownTime>3</cooldownTime>
<linkedBodyPartsGroup>Legs</linkedBodyPartsGroup>
</li>
<li>
<label>钳击</label>
<capacities>
<li>Cut</li>
</capacities>
<power>30</power>
<cooldownTime>2</cooldownTime>
<linkedBodyPartsGroup>Hands</linkedBodyPartsGroup>
</li>
</tools>
<recipes Inherit="False">
</recipes>
<comps>
<!-- <li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.DrawFaceGraphicsComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.HeadControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.EyeballControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.LidControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.BrowControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.MouthControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.SkinControllerComp</compClass>
</li>
<li MayRequire="Nals.FacialAnimation">
<compClass>FacialAnimation.FacialAnimationControllerComp</compClass>
</li> -->
<!--<li>
<compClass>FacialAnimation.EmotionControllerComp</compClass>
</li>-->
<!-- <li Class="CompProperties_DrugAddict"/> -->
</comps>
</AlienRace.ThingDef_AlienRace>
</Defs>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<ThingDef ParentName="OrganicProductBase">
<defName>ARA_InsectJelly</defName>
<label>阿拉克涅虫蜜</label>
<description>由阿拉克涅虫族储存和用作食物的果冻。它顺滑、浓郁、永不腐烂,能满足食用者的娱乐需求。由于其独特的生物特性,非阿拉克涅虫族也可以食用这种食物,并且不会引起食物中毒。</description>
<possessionCount>20</possessionCount>
<graphicData>
<texPath>Things/Item/Resource/AnimalProductRaw/InsectJelly</texPath>
<graphicClass>Graphic_StackCount</graphicClass>
</graphicData>
<socialPropernessMatters>true</socialPropernessMatters>
<statBases>
<MarketValue>5.0</MarketValue>
<Mass>0.025</Mass>
<Nutrition>0.1</Nutrition>
<FoodPoisonChanceFixedHuman>0</FoodPoisonChanceFixedHuman>
</statBases>
<ingestible>
<foodType>AnimalProduct</foodType>
<preferability>MealFine</preferability>
<joy>0.04</joy>
<joyKind>Gluttonous</joyKind>
<ingestEffect>EatVegetarian</ingestEffect>
<ingestSound>Meal_Eat</ingestSound>
<lowPriorityCaravanFood>true</lowPriorityCaravanFood>
<babiesCanIngest>true</babiesCanIngest>
</ingestible>
<thingCategories>
<li>AnimalProductRaw</li>
</thingCategories>
<allowedArchonexusCount>150</allowedArchonexusCount>
</ThingDef>
</Defs>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<TerrainDef ParentName="FloorBase">
<defName>ARA_InsectSludge</defName>
<label>阿拉克涅菌毯</label>
<description>由阿拉克涅虫族所铺设的由真菌和分泌物混合得到的地面,清洁速度很快,但是对其他种族来说不太好看。</description>
<designationCategory>Floors</designationCategory>
<texturePath>Terrain/Surfaces/InsectSludge</texturePath>
<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>0</pathCost>
<generatedFilth>Filth_Slime</generatedFilth>
<filthAcceptanceMask>
<li>Unnatural</li>
</filthAcceptanceMask>
<natural>true</natural>
<fertility>0</fertility>
<takeFootprints>True</takeFootprints>
<avoidWander>false</avoidWander>
<statBases>
<Beauty>-6</Beauty>
<CleaningTimeFactor>0.25</CleaningTimeFactor>
<Cleanliness>0</Cleanliness>
<Flammability>0.2</Flammability>
</statBases>
<!-- <tags>
<li>Insect</li>
</tags> -->
</TerrainDef>
<ThingDef ParentName="Wall">
<defName>ARA_InsectWall</defName>
<label>堆积山岩</label>
<description>阿拉克涅工蜂将硬质岩石堆起来形成的墙壁,非常坚硬并且不会花费材料,就是看起来不太美观。</description>
<uiOrder>1800</uiOrder>
<uiIconPath>Wula/Building/Linked/WULA_Fortress_Wall_MenuIcon</uiIconPath>
<graphicData>
<texPath>ArachnaeSwarm/Building/ARA_InsectWall</texPath>
<graphicClass>Graphic_Single</graphicClass>
<shaderType>CutoutComplex</shaderType>
</graphicData>
<designationCategory>Structure</designationCategory>
<mineable>true</mineable>
<blockLight>true</blockLight>
<statBases>
<MarketValue>0</MarketValue>
<Beauty>-6</Beauty>
<MaxHitPoints>1000</MaxHitPoints>
<WorkToBuild>1500</WorkToBuild>
<Flammability>0</Flammability>
<Cleanliness>0</Cleanliness>
</statBases>
<building>
<isAirtight>true</isAirtight>
<isNaturalRock>true</isNaturalRock>
</building>
<terrainAffordanceNeeded>Heavy</terrainAffordanceNeeded>
<costStuffCount>0</costStuffCount>
<stuffCategories Inherit="False"/>
<!-- <placeWorkers>
<li>PlaceWorker_OnSubstructure</li>
</placeWorkers> -->
<damageMultipliers Inherit="False">
<li>
<damageDef>Bomb</damageDef>
<multiplier>0.1</multiplier>
</li>
<li>
<damageDef>Thump</damageDef>
<multiplier>0.1</multiplier>
</li>
</damageMultipliers>
<comps>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectSludge</terrainToSpawn>
<spawnRadius>1.35</spawnRadius>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="BuildingNaturalBase">
<defName>ARA_EggSac</defName>
<label>虫卵囊</label>
<description>一个黏滑的囊状物,内含昆虫幼虫。幼虫的孕育过程会产生微弱的生物荧光。</description>
<thingClass>Building</thingClass>
<category>Building</category>
<graphicData>
<texPath>Things/Building/EggSac</texPath>
<graphicClass>Graphic_Random</graphicClass>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<fillPercent>0.3</fillPercent>
<rotatable>false</rotatable>
<terrainAffordanceNeeded>Light</terrainAffordanceNeeded>
<statBases>
<MaxHitPoints>20</MaxHitPoints>
<Flammability>0.4</Flammability>
<Beauty>-6</Beauty>
</statBases>
<building>
<isInert>true</isInert>
<claimable>false</claimable>
<deconstructible>false</deconstructible>
<repairable>false</repairable>
<quickTargetable>true</quickTargetable>
<isTargetable>true</isTargetable>
<expandHomeArea>false</expandHomeArea>
</building>
<comps>
<li Class="CompProperties_Glower">
<glowRadius>6</glowRadius>
<glowColor>(113,141,117,0)</glowColor>
</li>
<li Class="CompProperties_SpawnPawnOnDestroyed">
<compClass>CompSpawnLarva</compClass>
<pawnKind>Larva</pawnKind>
<lordJob>LordJob_WanderNest</lordJob>
</li>
<li Class="CompProperties_SpawnEffecterOnDestroy">
<effect>CocoonDestroyed</effect>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -1,17 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="BuildingNaturalBase">
<defName>ARA_InteractiveEggSac</defName>
<label>可交互的虫卵囊</label>
<description>一个黏滑的囊状物,可以通过交互来孵化特定的昆虫</description>
<label>阿拉克涅虫卵囊-休眠中</label>
<description>一个脆弱、易燃、黏滑的囊状物,是阿拉克涅女皇种所诞之卵,内含哺育一只新督虫所需的营养和遗传物质,可以通过阿拉克涅女皇种的交互完成激活进程——参阅虫卵的具体信息,了解各个督虫的特点</description>
<thingClass>Building</thingClass>
<descriptionHyperlinks>
<ThingDef>ArachnaeNode_Race_Myrmecocystus</ThingDef>
</descriptionHyperlinks>
<category>Building</category>
<size>(1,1)</size>
<minifiedDef>MinifiedThing</minifiedDef>
<thingCategories>
<li>BuildingsMisc</li>
</thingCategories>
<graphicData>
<texPath>Things/Building/EggSac</texPath>
<graphicClass>Graphic_Random</graphicClass>
<drawSize>(1.5,1.5)</drawSize>
<texPath>ArachnaeSwarm/Building/ARA_EggSac</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>(1.5,1.5)</drawSize>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
@@ -20,40 +26,75 @@
<tickerType>Normal</tickerType>
<terrainAffordanceNeeded>Light</terrainAffordanceNeeded>
<statBases>
<MaxHitPoints>200</MaxHitPoints>
<Flammability>0.4</Flammability>
<Beauty>-6</Beauty>
<Mass>10</Mass>
<MaxHitPoints>20</MaxHitPoints>
<Flammability>1</Flammability>
<Beauty>-6</Beauty>
</statBases>
<building>
<isInert>true</isInert>
<claimable>false</claimable>
<deconstructible>false</deconstructible>
<repairable>false</repairable>
<quickTargetable>true</quickTargetable>
<isTargetable>true</isTargetable>
<expandHomeArea>false</expandHomeArea>
<isInert>true</isInert>
<!-- <claimable>false</claimable> -->
<deconstructible>false</deconstructible>
<repairable>false</repairable>
<quickTargetable>true</quickTargetable>
<isTargetable>true</isTargetable>
<expandHomeArea>false</expandHomeArea>
</building>
<comps>
<li Class="CompProperties_Glower">
<glowRadius>6</glowRadius>
<glowColor>(113,141,117,0)</glowColor>
</li>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<pawnKinds>
<li>Megascarab</li>
<li>Spelopede</li>
<li>Megaspider</li>
</pawnKinds>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<delay>300</delay> <!-- 5 seconds -->
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="CompProperties_SpawnEffecterOnDestroy">
<effect>CocoonDestroyed</effect>
</li>
<li Class="CompProperties_Glower">
<glowRadius>6</glowRadius>
<glowColor>(113,141,117,0)</glowColor>
</li>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<pawnKinds>
<li>Megascarab</li>
<li>Spelopede</li>
<li>Megaspider</li>
<li>ArachnaeNode_Race_Myrmecocystus</li>
</pawnKinds>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<pawnKindDelays>
<li>
<pawnKind>Megascarab</pawnKind>
<delay>3000</delay>
</li>
<li>
<pawnKind>Spelopede</pawnKind>
<delay>3000</delay>
</li>
<li>
<pawnKind>Megaspider</pawnKind>
<delay>3000</delay>
</li>
<li>
<pawnKind>ArachnaeNode_Race_Myrmecocystus</pawnKind>
<delay>300</delay>
</li>
</pawnKindDelays>
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="CompProperties_Maintainable">
<ticksHealthy>60000</ticksHealthy>
<ticksNeedsMaintenance>60000</ticksNeedsMaintenance>
<damagePerTickRare>10</damagePerTickRare>
</li>
<li Class="CompProperties_SpawnEffecterOnDestroy">
<effect>CocoonDestroyed</effect>
</li>
<li Class="CompProperties_SpawnerFilth">
<filthDef>Filth_Slime</filthDef>
<spawnCountOnSpawn>10</spawnCountOnSpawn>
<spawnMtbHours>4</spawnMtbHours>
<spawnRadius>5</spawnRadius>
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectSludge</terrainToSpawn>
<spawnRadius>4.6</spawnRadius>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -0,0 +1,444 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThinkTreeDef>
<defName>ARA_InsectWorker</defName>
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<!-- Keep lying down if we have to -->
<li Class="ThinkNode_ConditionalMustKeepLyingDown">
<subNodes>
<!-- Do a queued job if possible -->
<li Class="ThinkNode_QueuedJob">
<inBedOnly>true</inBedOnly>
</li>
<!-- Keep lying down -->
<li Class="JobGiver_KeepLyingDown"/>
</subNodes>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>Downed</treeDef>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>BurningResponse</treeDef>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>MentalStateCritical</treeDef>
</li>
<!-- React to close melee threat -->
<li Class="JobGiver_ReactToCloseMeleeThreat"/>
<!-- Do a queued job -->
<li Class="ThinkNode_QueuedJob"/>
<!-- Wild insects dig out if no path to map edge and starving -->
<li Class="ThinkNode_ConditionalHasFaction">
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_ConditionalStarving">
<subNodes>
<li Class="ThinkNode_ConditionalBodySize">
<min>0.7</min>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>DigOutIfCannotReachMapEdge</treeDef>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Leave if timed out -->
<li Class="ThinkNode_ConditionalExitTimedOut">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapRandom">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Mental state non critical -->
<li Class="ThinkNode_Subtree">
<treeDef>MentalStateNonCritical</treeDef>
</li>
<!-- Forced goto -->
<li Class="ThinkNode_ConditionalForcedGoto">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ForcedGoto"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Behavior when roped -->
<li Class="ThinkNode_Subtree">
<treeDef>RopedPawn</treeDef>
</li>
<!-- Lord directives -->
<li Class="ThinkNode_Subtree">
<treeDef>LordDuty</treeDef>
</li>
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Animal_PreMain</insertTag>
</li>
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Insect_PreMain</insertTag>
</li>
<li Class="ThinkNode_ConditionalHasFaction">
<invert>true</invert>
<subNodes>
<!-- Wild insects with no lord will fight nearby enemies -->
<li Class="JobGiver_AIFightEnemies">
<targetAcquireRadius>30</targetAcquireRadius> <!-- Same as DefendAndExpandHive -->
<targetKeepRadius>35</targetKeepRadius>
</li>
<!-- Wild insects leave map in some conditions -->
<li Class="ThinkNode_Subtree">
<treeDef>LeaveIfWrongSeason</treeDef>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>LeaveIfStarving</treeDef>
</li>
<!-- Wild insects randomly leave map -->
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbDays>60</mtbDays>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapRandom">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Insects of a faction that's not the players without a lord leave randomly -->
<li Class="ThinkNode_ConditionalOfPlayerFaction">
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_ConditionalHasFaction">
<subNodes>
<li Class="ThinkNode_ConditionalNoLord">
<subNodes>
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbDays>60</mtbDays>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapRandom">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Tame insects -->
<li Class="ThinkNode_ConditionalOfPlayerFaction">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>TrainedAnimalBehavior</tagToGive>
<subNodes>
<!-- Trained behavior: obedience: Follow and defend master -->
<li Class="ThinkNode_ConditionalTrainableCompleted">
<trainable>Obedience</trainable>
<subNodes>
<li Class="ThinkNode_ConditionalShouldFollowMaster">
<subNodes>
<li Class="JobGiver_AIDefendMaster">
<attackMeleeThreatEvenIfNotHostile>true</attackMeleeThreatEvenIfNotHostile>
</li>
<li Class="JobGiver_AIFollowMaster"/>
<li Class="JobGiver_WanderNearMaster"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Trained behavior: Rescue-->
<li Class="ThinkNode_ConditionalTrainableCompleted">
<trainable>Rescue</trainable>
<subNodes>
<li Class="JobGiver_RescueNearby">
<radius>75</radius>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Take care of critical needs (below rescue - so heroic!)-->
<li Class="ThinkNode_Tagger">
<tagToGive>RestingForMedicalReasons</tagToGive>
<subNodes>
<li Class="JobGiver_PatientGoToBed"/>
</subNodes>
</li>
<li Class="JobGiver_SeekAllowedArea"/>
<li Class="JobGiver_SeekSafeTemperature"/>
</subNodes>
</li>
<!-- Eat random things out of curiosity -->
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbDays>60</mtbDays>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="JobGiver_EatRandom"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Satisfy basic needs -->
<li Class="ThinkNode_Subtree">
<treeDef>SatisfyBasicNeeds</treeDef>
</li>
<!-- Tame insect: do useful things for the colony-->
<li Class="ThinkNode_ConditionalHasFaction">
<subNodes>
<!-- Do a queued job -->
<li Class="ThinkNode_QueuedJob" />
<li Class="JobGiver_SeekAllowedArea" />
<li Class="JobGiver_Work">
<emergency>true</emergency>
</li>
<li Class="JobGiver_Work" />
<!-- Try to mate -->
<li Class="ThinkNode_ChancePerHour_Mate">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="JobGiver_Mate"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Nuzzle randoms -->
<li Class="ThinkNode_ChancePerHour_Nuzzle">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_Nuzzle"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Roamers gonna roam -->
<li Class="ThinkNode_ChancePerDay_Roam">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_StartRoaming"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Trained behavior: Haul-->
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbHours>1.5</mtbHours>
<subNodes>
<li Class="ThinkNode_ConditionalRequireCapacities">
<requiredCapacities>
<li>Manipulation</li>
</requiredCapacities>
<subNodes>
<li Class="ThinkNode_ConditionalTrainableCompleted">
<trainable>Haul</trainable>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>TrainedAnimalBehavior</tagToGive>
<subNodes>
<li Class="JobGiver_Haul"/>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Trained behavior: Forage -->
<li Class="ThinkNode_ConditionalTrainableCompleted" MayRequire="Ludeon.RimWorld.Odyssey">
<trainable>Forage</trainable>
<subNodes>
<li Class="ThinkNode_ChancePerHour_Forage">
<subNodes>
<li Class="ThinkNode_ConditionalAnimalShouldForage">
<subNodes>
<li Class="JobGiver_Forage" />
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Trained behavior: Mine -->
<li Class="ThinkNode_ConditionalTrainableCompleted" MayRequire="Ludeon.RimWorld.Odyssey">
<trainable>Dig</trainable>
<subNodes>
<li Class="ThinkNode_ConditionalAnimalShouldDig">
<subNodes>
<li Class="JobGiver_Mine" />
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Animal_PreWander</insertTag>
</li>
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Insect_PreWander</insertTag>
</li>
<!-- Tame insect: wander near colony if possible -->
<li Class="ThinkNode_ConditionalOfPlayerFaction">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<!-- Wander near your current position if in hostile map -->
<li Class="ThinkNode_ConditionalAnyEnemyInHostileMap">
<subNodes>
<li Class="JobGiver_WanderAnywhere">
<maxDanger>None</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
<li Class="ThinkNode_ConditionalRoamer">
<subNodes>
<li Class="JobGiver_WanderInRoofedCellsInPen">
<maxDanger>None</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
<expiryInterval>500</expiryInterval>
</li>
<!-- tame roamers should not wander too far, and if unenclosed wander near a suitable pen marker 10% of the time -->
<li Class="ThinkNode_ConditionalRandom">
<chance>0.1</chance>
<subNodes>
<li Class="JobGiver_WanderInPen">
<maxDanger>None</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
<expiryInterval>500</expiryInterval>
</li>
</subNodes>
</li>
<li Class="JobGiver_WanderAnywhere">
<maxDanger>None</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
<!-- Wander near colony -->
<li Class="JobGiver_WanderColony">
<maxDanger>None</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Of neutral faction: rest and then exit the map -->
<li Class="ThinkNode_ConditionalNonPlayerNonHostileFaction">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>RestingForMedicalReasons</tagToGive>
<subNodes>
<li Class="JobGiver_PatientGoToBed"/>
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapBest">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Wander -->
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<li Class="ThinkNode_ConditionalHerdAnimal">
<subNodes>
<li Class="JobGiver_WanderHerd">
<maxDanger>Deadly</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
<li Class="JobGiver_WanderAnywhere">
<maxDanger>Deadly</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
<li Class="JobGiver_IdleError"/>
</subNodes>
</thinkRoot>
</ThinkTreeDef>
</Defs>

View File

@@ -0,0 +1,501 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<ThinkTreeDef>
<defName>ARA_Humanlike</defName> <!-- 更改defName以避免与原版Humanlike冲突 -->
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<!-- Do lovin' -->
<li Class="ThinkNode_ConditionalLyingDown">
<subNodes>
<li Class="ThinkNode_ChancePerHour_Lovin">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="JobGiver_DoLovin" />
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- If we HAVE to keep lying down... -->
<li Class="ThinkNode_ConditionalMustKeepLyingDown">
<subNodes>
<!-- Do a queued job if possible (e.g. watch tv in bed) -->
<li Class="ThinkNode_QueuedJob">
<inBedOnly>true</inBedOnly>
</li>
<!-- Get joy -->
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="ThinkNode_PrioritySorter">
<subNodes>
<li Class="ThinkNode_Priority_GetJoy">
<subNodes>
<li Class="JobGiver_GetJoyInBed" />
</subNodes>
</li>
<li Class="JobGiver_MeditateInBed"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- Keep lying down -->
<li Class="JobGiver_KeepLyingDown" />
</subNodes>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>Downed</treeDef>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>BurningResponse</treeDef>
</li>
<li Class="ThinkNode_Subtree">
<treeDef>MentalStateCritical</treeDef>
</li>
<!-- Escaping threats -->
<li Class="ThinkNode_Subtree" MayRequire="Ludeon.RimWorld.Biotech">
<treeDef>Abilities_Escape</treeDef>
</li>
<!-- React to close melee threat -->
<li Class="JobGiver_ReactToCloseMeleeThreat" />
<!-- Mental state non critical -->
<li Class="ThinkNode_Subtree">
<treeDef>MentalStateNonCritical</treeDef>
</li>
<!-- Behavior when roped -->
<li Class="ThinkNode_Subtree">
<treeDef>RopedPawn</treeDef>
</li>
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Humanlike_PostMentalState</insertTag>
</li>
<!-- Do a queued job -->
<li Class="ThinkNode_QueuedJob" />
<!-- Wait if drafted -->
<li Class="ThinkNode_ConditionalColonist">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>DraftedOrder</tagToGive>
<subNodes>
<li Class="JobGiver_MoveToStandable" />
<li Class="JobGiver_Orders" />
</subNodes>
</li>
</subNodes>
</li>
<!-- Self-tend if you're an NPC -->
<li Class="ThinkNode_ConditionalNPCCanSelfTendNow">
<subNodes>
<li Class="JobGiver_SelfTend" />
</subNodes>
</li>
<!-- Lord directives (high priority) -->
<li Class="ThinkNode_JoinVoluntarilyJoinableLord">
<dutyHook>HighPriority</dutyHook>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>LordDuty</treeDef>
</li>
</subNodes>
</li>
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Humanlike_PostDuty</insertTag>
</li>
<!-- JobGiver_MaintainBuildings start -->
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbHours>2.5</mtbHours>
<subNodes>
<li Class="ArachnaeSwarm.JobGiver_MaintainBuildings">
<maintainableThingDefs>
<li>ARA_InteractiveEggSac</li> <!-- 默认维护Hive -->
</maintainableThingDefs>
</li>
</subNodes>
</li>
<li Class="ArachnaeSwarm.JobGiver_MaintainBuildings">
<maintainableThingDefs>
<li>ARA_InteractiveEggSac</li> <!-- 默认维护Hive -->
</maintainableThingDefs>
<onlyIfDamagingState>true</onlyIfDamagingState>
</li>
<!-- JobGiver_MaintainBuildings end -->
<!-- Prisoner -->
<li Class="ThinkNode_ConditionalPrisoner">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
<subNodes>
<!-- If it's the player home map... -->
<li Class="ThinkNode_ConditionalInNonPlayerHomeMap">
<invert>true</invert>
<subNodes>
<!-- Wait instead of escaping if should -->
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<li Class="JobGiver_PrisonerWaitInsteadOfEscaping">
<maxDanger>Deadly</maxDanger>
</li>
</subNodes>
</li>
<!-- Escape -->
<li Class="ThinkNode_Tagger">
<tagToGive>Escaping</tagToGive>
<subNodes>
<li Class="JobGiver_PrisonerEscape" />
</subNodes>
</li>
</subNodes>
</li>
<!-- Exit map if released -->
<li Class="ThinkNode_ConditionalReleased">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapBest">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>RestingForMedicalReasons</tagToGive>
<subNodes>
<li Class="JobGiver_PatientGoToBed" />
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>ChangingApparel</tagToGive>
<subNodes>
<li Class="JobGiver_PrisonerGetDressed" />
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="ThinkNode_PrioritySorter">
<subNodes>
<li Class="JobGiver_Autofeed" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="JobGiver_GetFood"/>
<li Class="JobGiver_GetRest"/>
<li Class="JobGiver_SatisfyChemicalNeed"/>
<li Class="JobGiver_SatifyChemicalDependency" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="JobGiver_GetHemogen" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="JobGiver_GetDeathrest" MayRequire="Ludeon.RimWorld.Biotech" />
<li Class="ThinkNode_Priority_GetJoy">
<subNodes>
<li Class="JobGiver_GetJoy"/>
<li Class="JobGiver_GetJoyInBed"/>
</subNodes>
</li>
<li Class="JobGiver_Meditate"/>
</subNodes>
</li>
</subNodes>
</li>
<!-- If in non-PlayerHomeMap -->
<li Class="ThinkNode_ConditionalInNonPlayerHomeMap">
<subNodes>
<!-- No colonist spawned in the map -->
<li Class="ThinkNode_ConditionalAnyUndownedColonistSpawnedNearby">
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Escaping</tagToGive>
<subNodes>
<li Class="JobGiver_PrisonerEscape" />
</subNodes>
</li>
</subNodes>
</li>
<!-- Wander -->
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<li Class="JobGiver_WanderColony">
<maxDanger>Deadly</maxDanger>
</li>
</subNodes>
</li>
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<li Class="JobGiver_WanderCurrentRoom">
<maxDanger>Deadly</maxDanger>
</li>
</subNodes>
</li>
<li Class="JobGiver_IdleError" />
</subNodes>
</li>
<!-- If on colonist team, do forced and emergency work -->
<li Class="ThinkNode_ConditionalColonist">
<subNodes>
<!-- Seek allowed area -->
<li Class="JobGiver_SeekAllowedArea" />
<!-- Seek safe temperatures -->
<li Class="JobGiver_BringBabyToSafety" />
<li Class="JobGiver_SeekSafeTemperature" />
<!-- Drop unnused inventory -->
<li Class="JobGiver_DropUnusedInventory" />
<!-- Emergency work -->
<li Class="JobGiver_Work">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
<emergency>true</emergency>
</li>
<!-- Get food (only if starving) -->
<li Class="ThinkNode_ConditionalStarving">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="JobGiver_GetFood">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Breastfeed -->
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_Autofeed" MayRequire="Ludeon.RimWorld.Biotech" />
</subNodes>
</li>
<!-- Lord directives (medium priority) -->
<li Class="ThinkNode_JoinVoluntarilyJoinableLord">
<dutyHook>MediumPriority</dutyHook>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>LordDuty</treeDef>
</li>
</subNodes>
</li>
<!-- Pick up a weapon dropped while previously downed -->
<li Class="JobGiver_PickupDroppedWeapon">
<ignoreForbidden>true</ignoreForbidden>
</li>
<!-- Optimize apparel -->
<li Class="ThinkNode_Tagger">
<tagToGive>ChangingApparel</tagToGive>
<subNodes>
<li Class="JobGiver_OptimizeApparel">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
<!-- Look change -->
<li MayRequire="Ludeon.RimWorld.Ideology" Class="ThinkNode_ConditionalWantsLookChange">
<subNodes>
<li Class="JobGiver_UseStylingStationAutomatic" />
</subNodes>
</li>
<!-- Dye hair -->
<li MayRequire="Ludeon.RimWorld.Ideology" Class="JobGiver_DyeHair" />
<!-- Take for inventory stock -->
<li Class="ThinkNode_Tagger">
<tagToGive>TakeForInventoryStock</tagToGive>
<subNodes>
<li Class="JobGiver_TakeForInventoryStock">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
<!-- Unload your inventory -->
<li Class="ThinkNode_Tagger">
<tagToGive>UnloadingOwnInventory</tagToGive>
<subNodes>
<li Class="JobGiver_UnloadYourInventory" />
</subNodes>
</li>
<!-- Pack food if not hungry-->
<li Class="ThinkNode_ConditionalNeedPercentageAbove">
<need>Food</need>
<threshold>0.6</threshold>
<subNodes>
<li Class="JobGiver_PackFood">
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Behavior from traits -->
<li Class="ThinkNode_TraitBehaviors" />
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Humanlike_PreMain</insertTag>
</li>
<!-- Main colonist behavior core -->
<li Class="ThinkNode_ConditionalColonist">
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>MainColonistBehaviorCore</treeDef>
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
<!-- Main wild man behavior core -->
<li Class="ThinkNode_ConditionalPawnKind">
<pawnKind>WildMan</pawnKind>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>MainWildManBehaviorCore</treeDef>
<leaveJoinableLordIfIssuesJob>true</leaveJoinableLordIfIssuesJob>
</li>
</subNodes>
</li>
<!-- Insertion hook for modders -->
<li Class="ThinkNode_SubtreesByTag">
<insertTag>Humanlike_PostMain</insertTag>
</li>
<!-- Idle colonist -->
<li Class="ThinkNode_ConditionalColonist">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<!-- Do random joy activity -->
<li Class="ThinkNode_ConditionalNeedPercentageAbove">
<need>Joy</need>
<threshold>0.9</threshold>
<invert>true</invert>
<subNodes>
<li Class="JobGiver_IdleJoy" />
</subNodes>
</li>
<!-- Wander -->
<li Class="JobGiver_WanderColony">
<maxDanger>None</maxDanger>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Idle wild man -->
<li Class="ThinkNode_ConditionalPawnKind">
<pawnKind>WildMan</pawnKind>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<!-- Wander -->
<li Class="JobGiver_WanderAnywhere">
<maxDanger>Deadly</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- If you're a neutral guest, if you're not hurt exit the map, otherwise use a medical bed -->
<li Class="ThinkNode_ConditionalGuest">
<subNodes>
<li Class="ThinkNode_ConditionalNonPlayerNonHostileFactionOrFactionless">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>RestingForMedicalReasons</tagToGive>
<subNodes>
<li Class="JobGiver_PatientGoToBed" />
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapBest">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- Final backup: If you're just here for no apparent reason, and not a colonist, leave the map
e.g. This happens for pawns who are downed during combat, then later self-heal -->
<li Class="ThinkNode_ConditionalColonist">
<invert>true</invert>
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="JobGiver_ExitMapBest">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
</subNodes>
</li>
<!-- If you can't leave, just wander -->
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
<subNodes>
<li Class="JobGiver_WanderAnywhere">
<maxDanger>Deadly</maxDanger>
</li>
</subNodes>
</li>
<li Class="JobGiver_IdleError" />
</subNodes>
</thinkRoot>
</ThinkTreeDef>
</Defs>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<LanguageData>
<ARA_AlertUnlinkedDroneLabel>未连接的虫群工蜂</ARA_AlertUnlinkedDroneLabel>
<ARA_AlertUnlinkedDroneExplanation>地图上存在未连接到阿拉克涅女皇种的虫群工蜂。这些工蜂将在一段时间后死亡。请尽快将它们与阿拉克涅女皇种连接。</ARA_AlertUnlinkedDroneExplanation>
</LanguageData>

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View File

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View File

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 KiB

View File

@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public static class AnimalWorkSystemPatcher
{
static AnimalWorkSystemPatcher()
{
var harmony = new Harmony("com.yourname.animalworksystem");
harmony.PatchAll();
}
}
[HarmonyPatch(typeof(Pawn_WorkSettings), "EnableAndInitialize")]
public static class Patch_Pawn_WorkSettings_EnableAndInitialize
{
public static void Postfix(Pawn_WorkSettings __instance, Pawn ___pawn)
{
// 检查是否是我们想要启用工作系统的动物,并且它不是机械体
// 因为原版的 EnableAndInitialize 已经处理了机械体的工作设置
if (___pawn.Faction != null && ___pawn.Faction.IsPlayer &&
!___pawn.RaceProps.IsMechanoid &&
ShouldEnableWorkSystem(___pawn))
{
// 获取 CompProperties_WorkForNonMechs
CompProperties_WorkForNonMechs compProps = null;
if (___pawn.def.comps != null)
{
foreach (var comp in ___pawn.def.comps)
{
if (comp is CompProperties_WorkForNonMechs props)
{
compProps = props;
break;
}
}
}
if (compProps != null && compProps.workTypes != null)
{
// 设置 CompProperties_WorkForNonMechs 中定义的工作类型优先级
foreach (var workType in compProps.workTypes)
{
if (!__instance.WorkIsActive(workType) && !___pawn.WorkTypeIsDisabled(workType))
{
__instance.SetPriority(workType, 3); // 默认优先级
}
}
}
}
}
private static bool ShouldEnableWorkSystem(Pawn pawn)
{
// 检查 ThingDef 中是否有 CompProperties_WorkForNonMechs 配置
if (pawn.def.comps != null)
{
foreach (var compProperties in pawn.def.comps)
{
if (compProperties is CompProperties_WorkForNonMechs)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -73,9 +73,33 @@
<Compile Include="JobDriver_Incubate.cs" />
<Compile Include="CompProperties_AbilitySprayLiquidMulti.cs" />
<Compile Include="CompAbilityEffect_SprayLiquidMulti.cs" />
<Compile Include="Building_Incubator.cs" />
<Compile Include="Hediffs\Hediff_CurseFlame.cs" />
<Compile Include="CompAbilityEffect_NeedCost.cs" />
<Compile Include="CompAbilityEffect_BodyPartCheck.cs" />
<Compile Include="Hediff_HiveMindMaster.cs" />
<Compile Include="Hediff_HiveMindDrone.cs" />
<Compile Include="HediffCompProperties_HiveMindDrone.cs" />
<Compile Include="HediffComp_HiveMindDrone.cs" />
<Compile Include="CompAbilityEffect_BindDrone.cs" />
<Compile Include="CompProperties_AbilityBindDrone.cs" />
<Compile Include="JobGiver_MaintainBuildings.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="CompWorkForNonMechs.cs" />
<Compile Include="AnimalWorkSystemPatcher.cs" />
<Compile Include="Patch_WorkGivers_Growing.cs" />
<Compile Include="Patch_QualityUtility.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="CompProperties_DelayedTerrainSpawn.cs" />
<Compile Include="CompDelayedTerrainSpawn.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="WULA_AutoMechCarrier\CompAutoMechCarrier.cs" />
<Compile Include="WULA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />
<Compile Include="WULA_AutoMechCarrier\PawnProductionEntry.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 自定义清理任务删除obj文件夹中的临时文件 -->
<Target Name="CleanDebugFiles" AfterTargets="Build">

View File

@@ -0,0 +1,22 @@
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class Building_Incubator : Building
{
public CompSpawnPawnFromList SpawnComp => GetComp<CompSpawnPawnFromList>();
public override Graphic Graphic
{
get
{
if (SpawnComp != null && SpawnComp.IsHatching && SpawnComp.Props.hatchingGraphicData != null)
{
return SpawnComp.Props.hatchingGraphicData.Graphic;
}
return base.Graphic;
}
}
}
}

View File

@@ -0,0 +1,108 @@
using RimWorld;
using Verse;
using System.Linq; // For LINQ operations
namespace ArachnaeSwarm
{
public class CompAbilityEffect_BindDrone : CompAbilityEffect
{
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn dronePawn = target.Pawn;
Pawn masterPawn = parent.pawn; // The pawn casting the ability
if (masterPawn != null && dronePawn != null)
{
Hediff_HiveMindMaster masterHediff = masterPawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster;
if (masterHediff != null)
{
if (masterHediff.TryBindDrone(dronePawn))
{
Messages.Message($"Successfully bound {dronePawn.LabelShort} to {masterPawn.LabelShort}'s hive mind.", MessageTypeDefOf.PositiveEvent, historical: false);
}
else
{
Messages.Message($"Failed to bind {dronePawn.LabelShort} to {masterPawn.LabelShort}'s hive mind. Check logs for details.", MessageTypeDefOf.NegativeEvent, historical: false);
}
}
else
{
Log.Error($"[ArachnaeSwarm] Master {masterPawn.LabelShort} tried to bind a drone but does not have Hediff_HiveMindMaster.");
}
}
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
if (!base.Valid(target, throwMessages))
{
return false;
}
Pawn dronePawn = target.Pawn;
Pawn masterPawn = parent.pawn;
// Target must be a pawn
if (dronePawn == null)
{
if (throwMessages)
{
Messages.Message("MustTargetPawn".Translate(parent.def.label), MessageTypeDefOf.RejectInput, historical: false);
}
return false;
}
// Target must be on the same map as the caster
if (dronePawn.Map != masterPawn.Map)
{
if (throwMessages)
{
Messages.Message("CannotTargetDifferentMap".Translate(), MessageTypeDefOf.RejectInput, historical: false);
}
return false;
}
// Target must have ARA_HiveMindDrone hediff
Hediff_HiveMindDrone droneHediff = dronePawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindDrone")) as Hediff_HiveMindDrone;
if (droneHediff == null)
{
if (throwMessages)
{
Messages.Message($"Target {dronePawn.LabelShort} does not have the 'ARA_HiveMindDrone' hediff.", MessageTypeDefOf.RejectInput, historical: false);
}
return false;
}
// Target must not be already bound to another master
if (droneHediff.target != null && droneHediff.target != masterPawn)
{
if (throwMessages)
{
Messages.Message($"Target {dronePawn.LabelShort} is already bound to {droneHediff.target.LabelShort}.", MessageTypeDefOf.RejectInput, historical: false);
}
return false;
}
// Caster must have ARA_HiveMindMaster hediff
Hediff_HiveMindMaster masterHediff = masterPawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster;
if (masterHediff == null)
{
if (throwMessages)
{
Messages.Message($"Caster {masterPawn.LabelShort} does not have the 'ARA_HiveMindMaster' hediff.", MessageTypeDefOf.RejectInput, historical: false);
}
return false;
}
// All checks passed
return true;
}
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
{
return Valid(target);
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Linq;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityBodyPartCheck : CompProperties_AbilityEffect
{
public BodyPartDef requiredPart;
public float minimumHealth = 0.8f;
public string failMessage = "Missing or damaged body part.";
public CompProperties_AbilityBodyPartCheck()
{
compClass = typeof(CompAbilityEffect_BodyPartCheck);
}
}
public class CompAbilityEffect_BodyPartCheck : CompAbilityEffect
{
public new CompProperties_AbilityBodyPartCheck Props => (CompProperties_AbilityBodyPartCheck)props;
public override bool GizmoDisabled(out string reason)
{
Pawn caster = parent.pawn;
if (caster != null && caster.health != null && caster.health.hediffSet != null)
{
var part = caster.health.hediffSet.GetNotMissingParts()
.FirstOrDefault(p => p.def == Props.requiredPart);
if (part == null)
{
reason = Props.failMessage;
return true;
}
float partHealth = caster.health.hediffSet.GetPartHealth(part) / part.def.GetMaxHealth(caster);
if (partHealth < Props.minimumHealth)
{
reason = Props.failMessage;
return true;
}
}
reason = null;
return false;
}
}
}

View File

@@ -0,0 +1,54 @@
using RimWorld;
using RimWorld.Planet;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityNeedCost : CompProperties_AbilityEffect
{
public NeedDef needDef;
public float needCost;
public string failMessage;
public CompProperties_AbilityNeedCost()
{
compClass = typeof(CompAbilityEffect_NeedCost);
}
}
public class CompAbilityEffect_NeedCost : CompAbilityEffect
{
public new CompProperties_AbilityNeedCost Props => (CompProperties_AbilityNeedCost)props;
public override bool GizmoDisabled(out string reason)
{
Pawn caster = parent.pawn;
if (caster != null && caster.needs != null)
{
if (caster.needs.TryGetNeed(Props.needDef, out Need need))
{
if (need.CurLevel < Props.needCost)
{
reason = Props.failMessage;
return true;
}
}
}
reason = null;
return false;
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn caster = parent.pawn;
if (caster != null && caster.needs != null)
{
if (caster.needs.TryGetNeed(Props.needDef, out Need need))
{
need.CurLevel -= Props.needCost;
}
}
}
}
}

View File

@@ -0,0 +1,57 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompDelayedTerrainSpawn : ThingComp
{
private CompProperties_DelayedTerrainSpawn Props => (CompProperties_DelayedTerrainSpawn)props;
private int ticksToSpawn;
private bool started;
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
StartDelayedSpawn();
}
public override void CompTick()
{
base.CompTick();
if (started)
{
ticksToSpawn--;
if (ticksToSpawn <= 0)
{
DoTerrainSpawn();
}
}
}
private void StartDelayedSpawn()
{
started = true;
ticksToSpawn = Props.delayTicks;
}
private void DoTerrainSpawn()
{
if (parent.Destroyed)
{
return;
}
if (Props.terrainToSpawn != null)
{
foreach (IntVec3 current in GenRadial.RadialCellsAround(parent.Position, Props.spawnRadius, true))
{
if (current.InBounds(parent.Map) && current.Walkable(parent.Map))
{
parent.Map.terrainGrid.SetTerrain(current, Props.terrainToSpawn);
}
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
public class CompProperties_AbilityBindDrone : CompProperties_AbilityEffect
{
public CompProperties_AbilityBindDrone()
{
this.compClass = typeof(CompAbilityEffect_BindDrone);
}
}
}

View File

@@ -0,0 +1,16 @@
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_DelayedTerrainSpawn : CompProperties
{
public int delayTicks = 0;
public TerrainDef terrainToSpawn;
public float spawnRadius = 0f;
public CompProperties_DelayedTerrainSpawn()
{
compClass = typeof(CompDelayedTerrainSpawn);
}
}
}

View File

@@ -9,10 +9,11 @@ namespace ArachnaeSwarm
{
public List<PawnKindDef> pawnKinds;
public List<PawnKindDef> whitelist;
public int delay = 0;
public List<PawnKindDelay> pawnKindDelays;
public bool destroyOnSpawn = false;
public IntRange spawnCount = new IntRange(1, 1);
public Type lordJob;
public GraphicData hatchingGraphicData;
public CompProperties_SpawnPawnFromList()
{
@@ -31,4 +32,10 @@ namespace ArachnaeSwarm
}
}
}
}
public class PawnKindDelay
{
public PawnKindDef pawnKind;
public int delay;
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Verse;
using RimWorld;
using Verse.AI;
@@ -13,6 +14,7 @@ namespace ArachnaeSwarm
private int spawnUntilTick = -1;
private PawnKindDef spawningPawnKind;
private PawnKindDef selectedPawnKind;
public bool IsHatching => spawnUntilTick > 0;
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
{
@@ -40,10 +42,12 @@ namespace ArachnaeSwarm
}
}
public void StartIncubation()
{
spawningPawnKind = selectedPawnKind;
spawnUntilTick = Find.TickManager.TicksGame + Props.delay;
int delay = Props.pawnKindDelays?.FirstOrDefault(pkd => pkd.pawnKind == selectedPawnKind)?.delay ?? 0;
spawnUntilTick = Find.TickManager.TicksGame + delay;
}
public override void CompTick()
@@ -55,6 +59,8 @@ namespace ArachnaeSwarm
}
}
private void SpawnPawn(PawnKindDef pawnKind)
{
try
@@ -71,34 +77,38 @@ namespace ArachnaeSwarm
return;
}
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
if (pawn == null)
int count = Props.spawnCount.RandomInRange;
for (int i = 0; i < count; i++)
{
Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}.");
return;
}
if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null)
{
Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}.");
if (!pawn.Destroyed)
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
if (pawn == null)
{
pawn.Destroy();
Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}.");
continue;
}
return;
}
if (Props.lordJob != null)
{
try
if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null)
{
LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob);
Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map);
lord.AddPawn(pawn);
Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}.");
if (!pawn.Destroyed)
{
pawn.Destroy();
}
continue;
}
catch (System.Exception e)
if (Props.lordJob != null)
{
Log.Error($"CompSpawnPawnFromList: Error creating LordJob {Props.lordJob?.Name ?? "null"} or assigning pawn {pawn}. Exception: {e}");
try
{
LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob);
Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map);
lord.AddPawn(pawn);
}
catch (System.Exception e)
{
Log.Error($"CompSpawnPawnFromList: Error creating LordJob {Props.lordJob?.Name ?? "null"} or assigning pawn {pawn}. Exception: {e}");
}
}
}
@@ -114,6 +124,7 @@ namespace ArachnaeSwarm
}
}
public override string CompInspectStringExtra()
{
if (spawnUntilTick > 0)
@@ -136,6 +147,7 @@ namespace ArachnaeSwarm
base.PostExposeData();
Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind");
Scribe_Defs.Look(ref selectedPawnKind, "selectedPawnKind");
}
}
}

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_WorkForNonMechs : CompProperties
{
public List<WorkTypeDef> workTypes;
public CompProperties_WorkForNonMechs()
{
compClass = typeof(CompWorkForNonMechs);
}
}
public class CompWorkForNonMechs : ThingComp
{
public CompProperties_WorkForNonMechs Props => (CompProperties_WorkForNonMechs)props;
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
var pawn = parent as Pawn;
if (pawn == null || pawn.Faction == null || !pawn.Faction.IsPlayer) return;
// 确保 workSettings 实例存在
if (pawn.workSettings == null)
{
pawn.workSettings = new Pawn_WorkSettings(pawn);
}
pawn.workSettings.EnableAndInitialize();
}
}
}

View File

@@ -0,0 +1,14 @@
using Verse;
namespace ArachnaeSwarm
{
public class HediffCompProperties_HiveMindDrone : HediffCompProperties
{
public int unlinkedDieDelayTicks = 1800; // Default to 30 seconds
public HediffCompProperties_HiveMindDrone()
{
this.compClass = typeof(HediffComp_HiveMindDrone); // Reference the Comp class
}
}
}

View File

@@ -0,0 +1,57 @@
using Verse;
using RimWorld;
namespace ArachnaeSwarm
{
public class HediffComp_HiveMindDrone : HediffComp
{
public HediffCompProperties_HiveMindDrone Props => (HediffCompProperties_HiveMindDrone)this.props;
public int TicksUnlinked => ticksUnlinked; // Expose as public property
private int ticksUnlinked = 0;
public override void CompExposeData()
{
base.CompExposeData();
Scribe_Values.Look(ref ticksUnlinked, "ticksUnlinked", 0);
}
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
// Only check if pawn is spawned and on a map
if (parent.pawn.Spawned && parent.pawn.Map != null)
{
// We use parent.pawn.IsHashIntervalTick(60) for performance
if (!parent.pawn.IsHashIntervalTick(60))
return;
Hediff_HiveMindDrone droneHediff = parent as Hediff_HiveMindDrone;
if (droneHediff == null) return; // Should not happen
Pawn masterPawn = droneHediff.target as Pawn;
if (masterPawn == null || masterPawn.Destroyed || masterPawn.Dead || !masterPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_HiveMindMaster")))
{
// Master is invalid or unlinked, start/continue unlinked timer
ticksUnlinked += 60; // Increment by 60 because we check every 60 ticks
if (ticksUnlinked >= Props.unlinkedDieDelayTicks)
{
Log.Message($"[ArachnaeSwarm] Drone {parent.pawn.LabelShort} was unlinked from master for too long and will die. Forcing death.");
// Ensure the pawn is killed only once and prevent further ticks
if (!parent.pawn.Dead && !parent.pawn.Destroyed)
{
parent.pawn.Kill(null, parent);
}
}
}
else
{
// Master is valid, reset unlinked timer
ticksUnlinked = 0;
}
}
}
}
}

View File

@@ -0,0 +1,73 @@
using System.Linq;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class Hediff_HiveMindDrone : HediffWithTarget
{
public override string LabelBase
{
get
{
string baseLabel = base.LabelBase + " (" + (target != null ? target.LabelShortCap : "未连接") + ")";
// Get the HediffComp_HiveMindDrone to access ticksUnlinked
HediffComp_HiveMindDrone comp = this.TryGetComp<HediffComp_HiveMindDrone>();
if (comp != null)
{
// Safely cast target to Pawn for Dead and health checks
Pawn masterPawn = target as Pawn;
if (masterPawn == null || masterPawn.Destroyed || masterPawn.Dead || !masterPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_HiveMindMaster")))
{
float timeLeftSecs = (comp.Props.unlinkedDieDelayTicks - comp.TicksUnlinked) / 60f;
if (timeLeftSecs > 0)
{
return baseLabel + " (死亡倒计时: " + timeLeftSecs.ToString("F1") + "s)";
}
}
}
return baseLabel;
}
}
public override void PostAdd(DamageInfo? dinfo)
{
base.PostAdd(dinfo);
// No direct linking in PostAdd, master will link manually
}
public override bool ShouldRemove
{
get
{
// Only remove if base ShouldRemove is true, OR if pawn is dead
// We do NOT want to remove it just because target is invalid, as the Comp will handle delayed death
if (base.ShouldRemove && pawn.Dead)
{
return true;
}
// Also remove if pawn is no longer spawned or on a map
if (!pawn.Spawned || pawn.Map == null)
{
return true;
}
return false; // Let the Comp handle the unlinked death
}
}
public override void PostRemoved()
{
base.PostRemoved();
// Deregister from the master when this hediff is removed
// Ensure target is a Pawn and not dead before attempting to deregister
if (this.target is Pawn master && master != null && !master.Destroyed && !master.Dead)
{
var masterHediff = master.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindMaster")) as Hediff_HiveMindMaster;
masterHediff?.DeregisterDrone(this.pawn);
}
}
// PostTick logic moved to HediffComp_HiveMindDrone
}
}

View File

@@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class Hediff_HiveMindMaster : Hediff
{
private List<Pawn> drones = new List<Pawn>();
public override string LabelInBrackets => drones.Count.ToString();
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref drones, "drones", LookMode.Reference);
if (drones == null)
{
drones = new List<Pawn>();
}
}
public bool TryBindDrone(Pawn drone)
{
if (drone == null || drone.Dead || !drone.Spawned || drone.Map != this.pawn.Map)
{
Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone?.LabelShort ?? "null"}: Invalid pawn state.");
return false;
}
Hediff_HiveMindDrone droneHediff = drone.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ARA_HiveMindDrone")) as Hediff_HiveMindDrone;
if (droneHediff == null)
{
Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone.LabelShort}: Does not have ARA_HiveMindDrone hediff.");
return false;
}
if (droneHediff.target != null && droneHediff.target != this.pawn)
{
Log.Message($"[ArachnaeSwarm] Cannot bind drone {drone.LabelShort}: Already bound to another master ({droneHediff.target.LabelShort}).");
return false;
}
if (drones.Contains(drone))
{
Log.Message($"[ArachnaeSwarm] Drone {drone.LabelShort} is already bound to this master.");
return false;
}
droneHediff.target = this.pawn; // Set the drone's target to this master
drones.Add(drone);
UpdateSeverity();
Log.Message($"[ArachnaeSwarm] Master {this.pawn.LabelShort} successfully bound drone {drone.LabelShort}.");
return true;
}
public void DeregisterDrone(Pawn drone)
{
if (drones.Contains(drone))
{
drones.Remove(drone);
UpdateSeverity();
}
}
private void UpdateSeverity()
{
this.Severity = drones.Count;
}
public override void PostRemoved()
{
base.PostRemoved();
// Kill all drones when the master hediff is removed (e.g., master dies)
foreach (var drone in drones.ToList()) // ToList() to avoid collection modification issues
{
if (drone != null && !drone.Dead)
{
Log.Message($"[ArachnaeSwarm] Master {pawn.LabelShort} died, killing drone {drone.LabelShort}.");
drone.Kill(null, this);
}
}
}
}
}

View File

@@ -0,0 +1,56 @@
using System.Collections.Generic;
using Verse;
using RimWorld;
using Verse.AI;
using Verse.AI.Group;
namespace ArachnaeSwarm
{
public class JobGiver_MaintainBuildings : JobGiver_AIFightEnemies
{
private bool onlyIfDamagingState;
// 新增属性用于存储可维护的ThingDef列表
public List<ThingDef> maintainableThingDefs;
private static readonly float CellsInScanRadius = GenRadial.NumCellsInRadius(7.9f);
public override ThinkNode DeepCopy(bool resolve = true)
{
JobGiver_MaintainBuildings obj = (JobGiver_MaintainBuildings)base.DeepCopy(resolve);
obj.onlyIfDamagingState = onlyIfDamagingState;
obj.maintainableThingDefs = maintainableThingDefs; // 复制列表
return obj;
}
protected override Job TryGiveJob(Pawn pawn)
{
Room room = pawn.GetRoom();
for (int i = 0; (float)i < CellsInScanRadius; i++)
{
IntVec3 intVec = pawn.Position + GenRadial.RadialPattern[i];
if (!intVec.InBounds(pawn.Map) || intVec.GetRoom(pawn.Map) != room)
{
continue;
}
// 遍历可维护的ThingDef列表
foreach (ThingDef thingDef in maintainableThingDefs)
{
// 查找指定ThingDef的建筑
Thing targetThing = (Thing)pawn.Map.thingGrid.ThingAt(intVec, thingDef);
if (targetThing != null && pawn.CanReserve(targetThing))
{
CompMaintainable compMaintainable = targetThing.TryGetComp<CompMaintainable>();
if (compMaintainable != null && compMaintainable.CurStage != 0 && (!onlyIfDamagingState || compMaintainable.CurStage == MaintainableStage.Damaging))
{
return JobMaker.MakeJob(JobDefOf.Maintain, targetThing);
}
}
}
}
return null;
}
}
}

View File

@@ -0,0 +1,62 @@
using HarmonyLib;
using RimWorld;
using Verse;
using System.Reflection; // For MethodInfo
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public static class QualityUtilityPatch
{
static QualityUtilityPatch()
{
var harmony = new Harmony("com.yourname.qualityutilitypatch");
harmony.Patch(
original: AccessTools.Method(typeof(QualityUtility), nameof(QualityUtility.GenerateQualityCreatedByPawn), new[] { typeof(Pawn), typeof(SkillDef), typeof(bool) }),
prefix: new HarmonyMethod(typeof(QualityUtilityPatch), nameof(GenerateQualityCreatedByPawn_Prefix))
);
}
public static bool GenerateQualityCreatedByPawn_Prefix(Pawn pawn, SkillDef relevantSkill, bool consumeInspiration, ref QualityCategory __result)
{
// 检查当前 Pawn 是否是我们的自定义动物(通过检查其 ThingDef 是否拥有 CompProperties_WorkForNonMechs
if (pawn != null && pawn.def.comps != null && ShouldEnableWorkSystem(pawn))
{
// 如果是,强制使用 mechFixedSkillLevel
int relevantSkillLevel = pawn.RaceProps.mechFixedSkillLevel;
bool inspired = consumeInspiration && pawn.InspirationDef == InspirationDefOf.Inspired_Creativity;
// 调用 QualityUtility.GenerateQualityCreatedByPawn 的 int 重载
__result = QualityUtility.GenerateQualityCreatedByPawn(relevantSkillLevel, inspired);
// 消耗灵感(如果适用)
if (inspired)
{
pawn.mindState.inspirationHandler.EndInspiration(InspirationDefOf.Inspired_Creativity);
}
// 返回 false跳过原版方法执行
return false;
}
// 返回 true执行原版方法
return true;
}
private static bool ShouldEnableWorkSystem(Pawn pawn)
{
// 检查 ThingDef 中是否有 CompProperties_WorkForNonMechs 配置
if (pawn.def.comps != null)
{
foreach (var compProperties in pawn.def.comps)
{
if (compProperties is CompProperties_WorkForNonMechs)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -0,0 +1,96 @@
using HarmonyLib;
using RimWorld;
using Verse;
using Verse.AI;
using System.Reflection;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public static class Patch_WorkGivers_Growing
{
static Patch_WorkGivers_Growing()
{
var harmony = new Harmony("com.yourname.workgiversgrowingpatch");
// Patch WorkGiver_GrowerSow.JobOnCell
harmony.Patch(
original: AccessTools.Method(typeof(WorkGiver_GrowerSow), nameof(WorkGiver_GrowerSow.JobOnCell)),
prefix: new HarmonyMethod(typeof(Patch_WorkGivers_Growing), nameof(JobOnCell_GrowerSow_Prefix))
);
// Patch JobDriver_Deconstruct.TickActionInterval
harmony.Patch(
original: AccessTools.Method(typeof(JobDriver_Deconstruct), "TickActionInterval"),
prefix: new HarmonyMethod(typeof(Patch_WorkGivers_Growing), nameof(TickActionInterval_Deconstruct_Prefix))
);
}
public static bool JobOnCell_GrowerSow_Prefix(Pawn pawn, IntVec3 c, ref Job __result, WorkGiver_GrowerSow __instance)
{
// 检查是否是我们的自定义动物,并且它不是真正的机械体 (因为真正的机械体原版会处理)
if (ShouldEnableWorkSystem(pawn) && !pawn.RaceProps.IsMechanoid)
{
// 使用反射获取 WorkGiver_GrowerSow 实例的 wantedPlantDef 字段
ThingDef wantedPlantDef = (ThingDef)AccessTools.Field(typeof(WorkGiver_Grower), "wantedPlantDef").GetValue(__instance);
if (wantedPlantDef == null)
{
__result = null;
return false; // 跳过原版方法
}
// 强制使用 mechFixedSkillLevel 作为相关技能等级
int relevantSkillLevel = pawn.RaceProps.mechFixedSkillLevel;
// 然后进行原始的 sowMinSkill 检查
if (wantedPlantDef.plant.sowMinSkill > relevantSkillLevel)
{
__result = null; // 技能不足,不生成 Job
return false; // 跳过原版方法
}
// 如果技能足够,让原版方法继续执行,处理其他复杂的检查
// 注意:这里我们只处理了技能检查部分,其他逻辑仍然依赖原版方法。
// 如果原版方法在其他地方再次访问 pawn.skills仍然可能出错。
// 但这是最直接的修复方法,避免了完全复制整个原始方法。
}
return true; // 执行原版方法
}
public static bool TickActionInterval_Deconstruct_Prefix(JobDriver_Deconstruct __instance, Pawn ___pawn, int delta)
{
// 检查是否是我们的自定义动物,并且它不是真正的机械体
if (ShouldEnableWorkSystem(___pawn) && !___pawn.RaceProps.IsMechanoid)
{
// 模拟技能学习,避免访问 pawn.skills 导致 NullReferenceException
// 这里我们不实际增加经验值,只是模拟原版方法的行为
// 避免了对 pawn.skills 的访问
if (__instance.Building.def.CostListAdjusted(__instance.Building.Stuff).Count > 0)
{
// 可以选择在这里添加一些日志,以便调试
// Log.Message($"Animal {___pawn.LabelShort} is deconstructing, simulating skill gain.");
}
return false; // 跳过原版方法
}
return true; // 执行原版方法
}
private static bool ShouldEnableWorkSystem(Pawn pawn)
{
// 检查 ThingDef 中是否有 CompProperties_WorkForNonMechs 配置
if (pawn.def.comps != null)
{
foreach (var compProperties in pawn.def.comps)
{
if (compProperties is CompProperties_WorkForNonMechs)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -0,0 +1,195 @@
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Verse;
using Verse.AI.Group;
namespace ArachnaeSwarm
{
public class CompAutoMechCarrier : CompMechCarrier
{
#region Reflected Fields
private static FieldInfo spawnedPawnsField;
private static FieldInfo cooldownTicksRemainingField;
private static FieldInfo innerContainerField;
private List<Pawn> SpawnedPawns
{
get
{
if (spawnedPawnsField == null)
spawnedPawnsField = typeof(CompMechCarrier).GetField("spawnedPawns", BindingFlags.NonPublic | BindingFlags.Instance);
return (List<Pawn>)spawnedPawnsField.GetValue(this);
}
}
private int CooldownTicksRemaining
{
get
{
if (cooldownTicksRemainingField == null)
cooldownTicksRemainingField = typeof(CompMechCarrier).GetField("cooldownTicksRemaining", BindingFlags.NonPublic | BindingFlags.Instance);
return (int)cooldownTicksRemainingField.GetValue(this);
}
set
{
if (cooldownTicksRemainingField == null)
cooldownTicksRemainingField = typeof(CompMechCarrier).GetField("cooldownTicksRemaining", BindingFlags.NonPublic | BindingFlags.Instance);
cooldownTicksRemainingField.SetValue(this, value);
}
}
private ThingOwner InnerContainer
{
get
{
if (innerContainerField == null)
innerContainerField = typeof(CompMechCarrier).GetField("innerContainer", BindingFlags.NonPublic | BindingFlags.Instance);
return (ThingOwner)innerContainerField.GetValue(this);
}
}
#endregion
public CompProperties_AutoMechCarrier AutoProps => (CompProperties_AutoMechCarrier)props;
private int TotalPawnCapacity => AutoProps.productionQueue.Sum(e => e.count);
private int LiveSpawnedPawnsCount(PawnKindDef kind)
{
SpawnedPawns.RemoveAll(p => p == null || p.Destroyed);
return SpawnedPawns.Count(p => p.kindDef == kind);
}
private AcceptanceReport CanSpawnNow(PawnKindDef kind)
{
if (parent is Pawn pawn && (pawn.IsSelfShutdown() || !pawn.Awake() || pawn.Downed || pawn.Dead || !pawn.Spawned))
return false;
if (CooldownTicksRemaining > 0)
return "CooldownTime".Translate() + " " + CooldownTicksRemaining.ToStringSecondsFromTicks();
PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
int cost = entry.cost ?? Props.costPerPawn;
if (!AutoProps.freeProduction && InnerContainer.TotalStackCountOfDef(Props.fixedIngredient) < cost)
return "MechCarrierNotEnoughResources".Translate();
return true;
}
private void TrySpawnPawn(PawnKindDef kind)
{
PawnGenerationRequest request = new PawnGenerationRequest(kind, parent.Faction, PawnGenerationContext.NonPlayer, -1, forceGenerateNewPawn: true);
Pawn pawn = PawnGenerator.GeneratePawn(request);
GenSpawn.Spawn(pawn, parent.Position, parent.Map);
SpawnedPawns.Add(pawn);
if (parent is Pawn p && p.GetLord() != null)
p.GetLord().AddPawn(pawn);
if (!AutoProps.freeProduction)
{
PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
int costLeft = entry.cost ?? Props.costPerPawn;
List<Thing> things = new List<Thing>(InnerContainer);
for (int j = 0; j < things.Count; j++)
{
Thing thing = InnerContainer.Take(things[j], Mathf.Min(things[j].stackCount, costLeft));
costLeft -= thing.stackCount;
thing.Destroy();
if (costLeft <= 0) break;
}
}
PawnProductionEntry spawnEntry = AutoProps.productionQueue.First(e => e.pawnKind == kind);
CooldownTicksRemaining = spawnEntry.cooldownTicks ?? Props.cooldownTicks;
if (Props.spawnedMechEffecter != null)
EffecterTrigger(Props.spawnedMechEffecter, Props.attachSpawnedMechEffecter, pawn);
if (Props.spawnEffecter != null)
EffecterTrigger(Props.spawnEffecter, Props.attachSpawnedEffecter, parent);
}
private void EffecterTrigger(EffecterDef effecterDef, bool attach, Thing target)
{
Effecter effecter = new Effecter(effecterDef);
effecter.Trigger(attach ? ((TargetInfo)target) : new TargetInfo(target.Position, target.Map), TargetInfo.Invalid);
effecter.Cleanup();
}
public override void CompTick()
{
base.CompTick();
if (parent.IsHashIntervalTick(60)) // 每秒检查一次
{
// 检查是否有抑制生产的Hediff
if (AutoProps.disableHediff != null && (parent as Pawn)?.health.hediffSet.HasHediff(AutoProps.disableHediff) == true)
{
return; // 有Hediff停止生产
}
// 1. 先检查是否满员
bool isFull = true;
foreach (var entry in AutoProps.productionQueue)
{
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{
isFull = false;
break;
}
}
if (isFull)
{
return; // 如果已满员,则不进行任何操作,包括冷却计时
}
// 2. 如果未满员,才检查冷却时间
if (CooldownTicksRemaining > 0) return;
// 3. 寻找空位并生产
foreach (var entry in AutoProps.productionQueue)
{
if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count)
{
if (CanSpawnNow(entry.pawnKind).Accepted)
{
TrySpawnPawn(entry.pawnKind);
break; // 每次只生产一个
}
}
}
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
// 移除所有Gizmo逻辑
return Enumerable.Empty<Gizmo>();
}
public override string CompInspectStringExtra()
{
SpawnedPawns.RemoveAll(p => p == null || p.Destroyed);
string text = "Pawns: " + SpawnedPawns.Count + " / " + TotalPawnCapacity;
foreach (var entry in AutoProps.productionQueue)
{
text += $"\n- {entry.pawnKind.LabelCap}: {LiveSpawnedPawnsCount(entry.pawnKind)} / {entry.count}";
}
if (CooldownTicksRemaining > 0)
{
text += "\n" + "CooldownTime".Translate() + ": " + CooldownTicksRemaining.ToStringSecondsFromTicks();
}
if (!AutoProps.freeProduction)
{
text += "\n" + base.CompInspectStringExtra();
}
return text;
}
}
}

View File

@@ -0,0 +1,54 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
namespace ArachnaeSwarm
{
public class CompProperties_AutoMechCarrier : CompProperties_MechCarrier
{
// XML中定义生产是否消耗资源
public bool freeProduction = false;
// 如果单位拥有这个Hediff则停止生产
public HediffDef disableHediff;
// 定义生产队列
public List<PawnProductionEntry> productionQueue = new List<PawnProductionEntry>();
public CompProperties_AutoMechCarrier()
{
// 确保这个属性类指向我们新的功能实现类
compClass = typeof(CompAutoMechCarrier);
}
public override IEnumerable<string> ConfigErrors(ThingDef parentDef)
{
foreach (string error in base.ConfigErrors(parentDef))
{
yield return error;
}
if (productionQueue.NullOrEmpty())
{
yield return "CompProperties_AutoMechCarrier must have at least one entry in productionQueue.";
}
}
public override void ResolveReferences(ThingDef parentDef)
{
base.ResolveReferences(parentDef);
// Prevent division by zero if costPerPawn is not set, which the base game AI might try to access.
if (costPerPawn <= 0)
{
costPerPawn = 1;
}
// 如果spawnPawnKind为空因为我们用了新的队列系统
// 就从队列里取第一个作为“假”值以防止基类方法在生成Gizmo标签时出错。
if (spawnPawnKind == null && !productionQueue.NullOrEmpty())
{
spawnPawnKind = productionQueue[0].pawnKind;
}
}
}
}

View File

@@ -0,0 +1,23 @@
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// A data class to hold information about a pawn to be produced in a queue.
/// Used in XML definitions.
/// </summary>
public class PawnProductionEntry
{
// The PawnKindDef of the unit to spawn.
public PawnKindDef pawnKind;
// The maximum number of this kind of unit to maintain.
public int count = 1;
// Optional: specific cooldown for this entry. If not set, the parent comp's cooldown is used.
public int? cooldownTicks;
// Optional: specific cost for this entry. If not set, the parent comp's costPerPawn is used.
public int? cost;
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]

View File

@@ -0,0 +1 @@
70a1ccfa141c7c82eb05a9fac71c32df86f6b34332995c92bb7aac69bc46394b

View File

@@ -0,0 +1,2 @@
C:\Steam\steamapps\common\RimWorld\Mods\ArachnaeSwarm\Source\ArachnaeSwarm\obj\Debug\ArachnaeSwarm.csproj.AssemblyReference.cache
C:\Steam\steamapps\common\RimWorld\Mods\ArachnaeSwarm\Source\ArachnaeSwarm\obj\Debug\ArachnaeSwarm.csproj.CoreCompileInputs.cache

View File

@@ -0,0 +1,514 @@
# 动物工作模式解决方案文档(最终实现版)
## 1. 项目概述
本项目旨在实现一个功能,使动物(特别是昆虫)能够像机械体一样持续工作,而不需要通过机械师控制 WorkMode。通过为动物启用工作系统并创建自定义行为树动物将始终处于工作状态持续执行允许的工作类型。
## 2. 原版代码分析
### 2.1 昆虫 ThinkTreeDef 结构
原版昆虫的 ThinkTree (`Insect.xml`) 包含以下主要逻辑:
1. **紧急情况处理**:倒地、燃烧、精神状态等
2. **基本需求满足**:睡觉、吃饭等
3. **驯服动物行为**:跟随主人、救援等
4. **闲置行为**:漫游、待命等
### 2.2 机械体 ThinkTreeDef 结构
原版机械体的 ThinkTree (`Mechanoid.xml`) 包含 WorkMode 系统,这是动物不具备的。
## 3. 为什么机械体有 workSettings 而动物没有
### 3.1 核心原因分析
机械体和动物虽然都是 Pawn但它们的 workSettings 初始化逻辑不同:
1. **`Pawn_WorkSettings` 的存在性**
- `Pawn` 类内部持有一个 `Pawn_WorkSettings` 类型的引用 `priorities`,默认为 `null`
- `public bool EverWork => priorities != null;` 属性表明只有当 `priorities` 不为 `null`Pawn 才有工作能力
2. **初始化条件**
- `EnableAndInitializeIfNotAlreadyInitialized()` 方法检查 `priorities` 是否为 `null`,如果为 `null` 则调用 `EnableAndInitialize()`
- `EnableAndInitialize()` 方法是真正执行初始化的地方,创建 `priorities` 对象并根据条件设置初始优先级
3. **Mechanoid 有 WorkSettings 的证据**
- `EnableAndInitialize()` 方法明确包含对机械体的特殊处理:
```csharp
if (ModsConfig.BiotechActive && pawn.RaceProps.IsMechanoid && !pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty())
{
for (int i = 0; i < pawn.RaceProps.mechWorkTypePriorities.Count; i++)
{
MechWorkTypePriority mechWorkTypePriority = pawn.RaceProps.mechWorkTypePriorities[i];
SetPriority(mechWorkTypePriority.def, mechWorkTypePriority.priority);
}
}
```
- 这表明机械体的设计意图就是拥有并使用 `Pawn_WorkSettings`
4. **Animal 没有 WorkSettings 的证据**
- **直接初始化逻辑**`EnableAndInitialize()` 方法在为 Pawn 分配默认"活跃"工作类型时,会过滤掉 `pawn.WorkTypeIsDisabled(w)` 的工作类型。对于大多数动物来说,它们的 `RaceProps` 会禁用几乎所有需要手动分配的 `WorkTypeDef`
- **工作类型的定义**:绝大多数工作类型都包含限制,使得动物 Pawn 默认无法执行这些工作
- **特定工作提供者的处理**:针对动物的操作是通过独立的 `WorkGiver` 系统直接处理的,不依赖于通用的 `workSettings` 优先级系统
### 3.2 结论
机械体被设计为拥有 `Pawn_WorkSettings`,因为它们的工作优先级可以通过其 `RaceProps.mechWorkTypePriorities` 进行预设,并且游戏逻辑会在需要时初始化它。
动物通常没有有效的 `Pawn_WorkSettings`,因为:
1. 它们被设计为不能执行绝大多数需要手动分配的工作
2. 它们与玩家互动的特定工作是通过独立的 `WorkGiver` 系统直接处理的
3. 因此,除非有特定的游戏逻辑或 Mod 显式地为动物调用 `EnableAndInitialize()`,否则它们的 `priorities` 对象很可能保持 `null` 状态
## 4. 为什么 `RaceProps.mechWorkTypePriorities` 只对机械体有效
### 4.1 核心解释
`mechWorkTypePriorities` 是 `RaceProperties` 类中的一个字段专门用于定义机械体Mechanoid在生成时其工作类型Work Types的默认优先级。它的设计和使用都与机械体的独特机制紧密相关而这些机制在动物或其他生物上并不存在或不以相同方式运作。
### 4.2 详细证据和解释
1. **字段定义与命名**
- `mechWorkTypePriorities` 被明确定义为:
```csharp
public List<MechWorkTypePriority> mechWorkTypePriorities;
```
- 其名称 `mechWorkTypePriorities` 包含了 "Mech" 前缀,明确指示其用途是针对机械体的。
2. **`MechWorkTypePriority` 类型**
- 该字段存储的是 `MechWorkTypePriority` 对象的列表。虽然代码片段中没有直接给出 `MechWorkTypePriority` 的定义,但其名称和用途(存储工作类型及其优先级)强烈暗示它是专门为机械体设计的数据结构。
3. **使用场景 - 初始化工作设置**
- 关键证据出现在 `Pawn_WorkSettings.EnableAndInitialize()` 方法中:
```csharp
// ... (其他初始化代码) ...
if (ModsConfig.BiotechActive && pawn.RaceProps.IsMechanoid && !pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty())
{
for (int i = 0; i < pawn.RaceProps.mechWorkTypePriorities.Count; i++)
{
MechWorkTypePriority mechWorkTypePriority = pawn.RaceProps.mechWorkTypePriorities[i];
SetPriority(mechWorkTypePriority.def, mechWorkTypePriority.priority);
}
}
// ... (其他初始化代码,如处理禁用的工作类型) ...
```
- 这段代码明确地检查了三个条件:
* `ModsConfig.BiotechActive`生物技术Biotech模组是否激活。这表明该功能是与 Biotech 模组引入的机械体相关的。
* `pawn.RaceProps.IsMechanoid`:当前 Pawn单位的种族属性是否为机械体。
* `!pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty()`:该机械体的 `mechWorkTypePriorities` 列表是否存在且非空。
- **只有当这三个条件都满足时,才会遍历 `mechWorkTypePriorities` 列表,并根据其中定义的 `WorkTypeDef` 和优先级来设置该机械体 Pawn 的工作优先级。**
- 对于动物或其他非机械体生物,`pawn.RaceProps.IsMechanoid` 条件为假,因此即使在它们的 `ThingDef` 中定义了 `mechWorkTypePriorities`,这段代码也不会执行,这些优先级设置就会被忽略。
4. **机制差异 - 动物 vs 机械体**
- **动物**:动物的工作能力(如驯服、训练、特定任务)通常是通过 `trainability`(可训练性)、`trainableTags`(可训练标签)等属性来定义的。它们的工作行为(如觅食、繁殖、战斗)主要由其 `intelligence`(智力)、`thinkTreeMain`(主思考树)和 `dutyBoss`(职责)等属性驱动。它们的初始工作优先级(如果有的话)通常是固定的或基于简单规则随机分配,而不是通过一个专门的优先级列表来精确控制。
- **机械体**:机械体是 Biotech 模组引入的复杂单位,它们拥有类似殖民者的工作系统。它们可以被指派执行各种殖民者能做的工作(如建造、种植、烹饪等),其能力范围和初始工作优先级需要更精细的控制。`mechWorkTypePriorities` 就是为了满足这种需求而设计的,允许设计者为每种机械体明确指定哪些工作类型应该默认开启以及它们的优先级。
5. **辅助证据 - MechWorkUtility**
- 在 `MechWorkUtility` 类中,多个方法(如 `SpecialDisplayStats`, `AnyWorkMechCouldDo`)在处理与机械体工作相关逻辑时,都会首先检查 `parentDef.race.IsMechanoid`。这进一步证明了与机械体工作类型相关的逻辑是严格限定于机械体的。
### 4.3 结论
`RaceProperties.mechWorkTypePriorities` 虽然是 `RaceProperties` 类的一个通用属性,但它被设计并实现为**仅对机械体Mechanoid生效**。这是因为:
1. 它的命名和数据类型 (`MechWorkTypePriority`) 明确指向机械体。
2. 核心的使用代码 (`Pawn_WorkSettings.EnableAndInitialize`) 通过 `pawn.RaceProps.IsMechanoid` 条件严格限制了其应用范围。
3. 机械体和动物在工作系统上的根本差异决定了需要不同的机制来管理其初始工作能力,`mechWorkTypePriorities` 是为满足机械体特有需求而生的。
因此,即使在动物的 `ThingDef` 文件中添加了 `mechWorkTypePriorities` 部分,游戏代码也不会读取或应用这些设置,因为动物不是机械体,相关的初始化逻辑不会被执行。
## 5. 通过 Harmony 补丁拦截 `pawn.RaceProps.IsMechanoid` 的分析
### 5.1 用户提供的实现思路
用户提供了一种更精确和安全的实现思路:通过 Harmony 补丁拦截 `Pawn_WorkSettings.EnableAndInitialize` 方法,在特定条件下局部伪装成机械体来为动物启用工作系统。
### 5.2 实现方法
1. **引入 Harmony**:确保你的 Mod 项目中引用了 Harmony 库。
2. **定义补丁类**:创建一个静态类来存放你的 Harmony 补丁。
3. **编写前缀补丁**
```csharp
[HarmonyPatch(typeof(Pawn_WorkSettings), nameof(Pawn_WorkSettings.EnableAndInitialize))]
public static class Patch_Pawn_WorkSettings_EnableAndInitialize
{
public static bool Prefix(Pawn_WorkSettings __instance, Pawn ___pawn)
{
// 检查是否是我们想要启用工作系统的动物
if (___pawn.Faction != null && ___pawn.Faction.IsPlayer &&
!___pawn.RaceProps.IsMechanoid && // 真实身份不是机械体
ShouldEnableWorkSystem(___pawn)) // 但我们需要为它启用工作系统
{
// 局部伪装成机械体来执行初始化逻辑
// 执行机械体工作优先级初始化逻辑
if (ModsConfig.BiotechActive && !___pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty())
{
for (int i = 0; i < ___pawn.RaceProps.mechWorkTypePriorities.Count; i++)
{
var priority = ___pawn.RaceProps.mechWorkTypePriorities[i];
__instance.SetPriority(priority.def, priority.priority);
}
}
// 同时也可以初始化 mechEnabledWorkTypes 中的工作类型
if (!___pawn.RaceProps.mechEnabledWorkTypes.NullOrEmpty())
{
foreach (var workType in ___pawn.RaceProps.mechEnabledWorkTypes)
{
if (!__instance.WorkIsActive(workType) && !___pawn.WorkTypeIsDisabled(workType))
{
__instance.SetPriority(workType, 3); // 默认优先级
}
}
}
// 阻止原方法继续执行
return false;
}
return true; // 其他情况正常执行原逻辑
}
private static bool ShouldEnableWorkSystem(Pawn pawn)
{
// 检查是否有特定的 Comp
if (pawn.TryGetComp<CompWorkForNonMechs>() != null)
return true;
// 检查是否有 mechWorkTypePriorities 或 mechEnabledWorkTypes 配置
if (!pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty() ||
!pawn.RaceProps.mechEnabledWorkTypes.NullOrEmpty())
return true;
return false;
}
}
```
4. **应用补丁**
```csharp
[StaticConstructorOnStartup]
public static class AnimalWorkSystemPatcher
{
static AnimalWorkSystemPatcher()
{
var harmony = new Harmony("com.yourname.animalworksystem");
harmony.PatchAll();
}
}
```
### 5.3 潜在问题和风险
1. **副作用**
- 这种方法比直接补丁 `IsMechanoid` 属性更加精确,因为它只在 `Pawn_WorkSettings.EnableAndInitialize` 方法中进行伪装,不影响其他系统。
- 但仍需注意确保伪装逻辑只在特定条件下触发,避免意外影响其他 Pawn。
2. **补丁冲突**
- 其他 Mod 也可能使用 Harmony 来修改 `Pawn_WorkSettings` 或相关逻辑。
- 需要确保补丁逻辑具有良好的兼容性。
3. **性能影响**
- Harmony 补丁会增加方法调用的开销,但在这个场景下影响很小。
4. **维护困难**
- 如果游戏更新修改了相关逻辑,你的补丁可能失效或产生新的问题,需要随之更新。
### 5.4 结论和建议
用户提供的实现思路是一种更加精确和安全的方法,通过局部伪装成机械体来为动物启用工作系统。这种方法的优点包括:
1. **精确性**:只在特定条件下(动物是玩家阵营且需要启用工作系统)才进行伪装。
2. **安全性**:只在 `Pawn_WorkSettings.EnableAndInitialize` 方法中进行伪装,不影响其他系统。
3. **兼容性**:通过检查特定的 Comp 或配置来决定是否启用工作系统,具有良好的可扩展性。
## 6. 完整实现方案
### 6.1 核心思路
1. 为动物添加 `CompWorkForNonMechs` 以启用工作系统
2. 创建 `ThinkNode_AnimalWorker` 替代默认行为,强制工作
3. 使用 Harmony 补丁局部伪装成机械体来为动物启用工作系统
4. 使用自定义 ThinkTree 替代默认动物行为树
5. 定义允许的工作类型,并确保其与 WorkGiver 兼容
### 6.2 设计要点
1. **为动物启用 WorkSettings 系统**:通过 Harmony 补丁局部伪装成机械体来为动物启用工作系统
2. **使用自定义 ThinkNode 强制工作行为**:创建 ThinkNode跳过所有动物默认行为直接进入工作逻辑
3. **修改动物定义**:添加 ThinkTree 和 Comp
4. **为动物添加工作类型支持**:定义允许的工作类型
## 7. 实现细节
### 7.1 CompWorkForNonMechs.cs
```csharp
using System.Collections.Generic;
using RimWorld;
using Verse;
namespace YourModName
{
public class CompWorkForNonMechs : ThingComp
{
public class CompProperties_WorkForNonMechs : CompProperties
{
public List<WorkTypeDef> workTypes;
public CompProperties_WorkForNonMechs()
{
compClass = typeof(CompWorkForNonMechs);
}
}
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
var pawn = parent as Pawn;
if (pawn == null || pawn.Faction == null || !pawn.Faction.IsPlayer) return;
// 启用工作设置
if (pawn.workSettings == null)
{
pawn.workSettings = new Pawn_WorkSettings(pawn);
}
pawn.workSettings.EnableAndInitialize();
// 启用指定的工作类型
var props = (CompProperties_WorkForNonMechs)props;
if (props.workTypes != null)
{
foreach (var workType in props.workTypes)
{
if (!pawn.WorkTypeIsDisabled(workType))
{
pawn.workSettings.SetPriority(workType, 3); // 默认优先级
}
}
}
}
}
}
```
### 7.2 ThinkNode_AnimalWorker.cs
```csharp
using RimWorld;
using Verse;
namespace YourModName
{
public class ThinkNode_AnimalWorker : ThinkNode_Priority
{
public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
{
if (pawn.workSettings == null || !pawn.Faction.IsPlayer)
{
return ThinkResult.NoJob;
}
// 优先执行紧急工作
var job = WorkGiverUtility.GetPriorityWork(pawn, emergency: true);
if (job != null) return new ThinkResult(job, this);
// 然后执行普通工作
job = WorkGiverUtility.GetPriorityWork(pawn, emergency: false);
if (job != null) return new ThinkResult(job, this);
return ThinkResult.NoJob;
}
}
}
```
### 7.3 AnimalWorkSystemPatcher.cs
```csharp
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using RimWorld;
using Verse;
namespace YourModName
{
[StaticConstructorOnStartup]
public static class AnimalWorkSystemPatcher
{
static AnimalWorkSystemPatcher()
{
var harmony = new Harmony("com.yourname.animalworksystem");
harmony.PatchAll();
}
}
[HarmonyPatch(typeof(Pawn_WorkSettings), nameof(Pawn_WorkSettings.EnableAndInitialize))]
public static class Patch_Pawn_WorkSettings_EnableAndInitialize
{
// 缓存原始的 IsMechanoid 属性 Getter
private static PropertyInfo isMechanoidProperty =
typeof(RaceProperties).GetProperty("IsMechanoid", BindingFlags.Public | BindingFlags.Instance);
public static bool Prefix(Pawn_WorkSettings __instance, Pawn ___pawn)
{
// 检查是否是我们想要启用工作系统的动物
if (___pawn.Faction != null && ___pawn.Faction.IsPlayer &&
!___pawn.RaceProps.IsMechanoid && // 真实身份不是机械体
ShouldEnableWorkSystem(___pawn)) // 但我们需要为它启用工作系统
{
// 局部伪装成机械体来执行初始化逻辑
// 执行机械体工作优先级初始化逻辑(来自 Pawn_WorkSettings.EnableAndInitialize
if (ModsConfig.BiotechActive && !___pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty())
{
for (int i = 0; i < ___pawn.RaceProps.mechWorkTypePriorities.Count; i++)
{
var priority = ___pawn.RaceProps.mechWorkTypePriorities[i];
__instance.SetPriority(priority.def, priority.priority);
}
}
// 同时也可以初始化 mechEnabledWorkTypes 中的工作类型(如果你需要)
if (!___pawn.RaceProps.mechEnabledWorkTypes.NullOrEmpty())
{
foreach (var workType in ___pawn.RaceProps.mechEnabledWorkTypes)
{
if (!__instance.WorkIsActive(workType) && !___pawn.WorkTypeIsDisabled(workType))
{
__instance.SetPriority(workType, 3); // 默认优先级
}
}
}
// 阻止原方法继续执行(因为我们已经手动处理了初始化)
return false;
}
return true; // 其他情况正常执行原逻辑
}
private static bool ShouldEnableWorkSystem(Pawn pawn)
{
// 你可以通过多种方式判断:
// 1. 检查是否有特定的 Comp
if (pawn.TryGetComp<CompWorkForNonMechs>() != null)
return true;
// 2. 检查是否有 mechWorkTypePriorities 或 mechEnabledWorkTypes 配置
if (!pawn.RaceProps.mechWorkTypePriorities.NullOrEmpty() ||
!pawn.RaceProps.mechEnabledWorkTypes.NullOrEmpty())
return true;
// 3. 检查特定的标签或 defName
// return pawn.def.defName.Contains("Worker");
return false;
}
}
}
```
### 7.4 修改动物定义
```xml
<ThingDef ParentName="BaseInsect">
<defName>Megascarab_Worker</defName>
<label>worker megascarab</label>
<description>A genetically modified megascarab, capable of performing simple mechanical tasks.</description>
<statBases>
<MoveSpeed>3.0</MoveSpeed>
<MarketValue>300</MarketValue>
</statBases>
<race>
<thinkTreeMain>InsectWorker</thinkTreeMain>
<thinkTreeConstant>AnimalConstant</thinkTreeConstant>
<mechWorkTypePriorities>
<li>
<def>Hauling</def>
<priority>3</priority>
</li>
<li>
<def>Cleaning</def>
<priority>2</priority>
</li>
</mechWorkTypePriorities>
</race>
<comps>
<li Class="YourModName.CompWorkForNonMechs+CompProperties_WorkForNonMechs">
<workTypes>
<li>Hauling</li>
<li>Cleaning</li>
<li>BasicWorker</li>
</workTypes>
</li>
</comps>
</ThingDef>
```
### 7.5 自定义 ThinkTreeDef
```xml
<ThinkTreeDef>
<defName>InsectWorker</defName>
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<!-- 紧急情况处理 -->
<li Class="ThinkNode_Subtree"><treeDef>Downed</treeDef></li>
<li Class="ThinkNode_Subtree"><treeDef>BurningResponse</treeDef></li>
<li Class="ThinkNode_Subtree"><treeDef>MentalStateCritical</treeDef></li>
<!-- 强制工作模式 -->
<li Class="YourModName.ThinkNode_AnimalWorker" />
<!-- 闲置行为 -->
<li Class="JobGiver_IdleError"/>
</subNodes>
</thinkRoot>
</ThinkTreeDef>
```
## 8. 原始方案的反驳分析
### 8.1 项目概述:不成立
**反驳证据:**
- RimWorld 原版设计中,动物的行为树是完全独立于机械体的,没有 WorkMode 系统。
- 动物不能直接复用机械体的工作逻辑。
### 8.2 ThinkNode_AnimalAlwaysWork 类:不成立
**反驳证据:**
- `ThinkNode_Priority` 是一个标准的 ThinkNode它会按顺序尝试子节点直到某一个返回 `ThinkResult`。
- 该类不会实现"始终工作"的功能,因为它没有改变行为树的执行逻辑。
### 8.3 InsectWorker ThinkTreeDef不成立
**反驳证据:**
- RimWorld 中,动物的 ThinkTree 并不会调用 `JobGiver_Work`,因为该类是为机械体设计的。
- 即使强制插入 `JobGiver_Work`,它也会因为动物的 `WorkSettings` 未初始化而失败。
### 8.4 Harmony 补丁拦截 IsMechanoid不成立
**反驳证据:**
- `RaceProperties.IsMechanoid` 是一个只读属性,由 `<race><isMechanoid>true</isMechanoid></race>` 控制。
- Patch 该属性会导致所有依赖该属性的逻辑被干扰,风险极高。
## 9. 使用说明
1. **编译代码**:将所有 C# 文件编译到您的 Mod 中
2. **添加 XML 文件**:将新的 ThinkTreeDef 和动物定义添加到您的 Mod 中
3. **配置工作类型**:在动物定义中配置 `mechWorkTypePriorities` 和 `CompWorkForNonMechs` 组件
4. **测试**:在游戏中生成修改后的动物,观察其工作行为
## 10. 注意事项
1. **兼容性**:此方案绕过了 WorkMode 系统,动物将始终处于工作状态
2. **性能**:频繁的工作查找可能会有轻微性能影响
3. **调试**:如果遇到问题,请检查日志文件中的错误信息
4. **避免 patch IsMechanoid**:不干扰原版逻辑
5. **副作用风险**:直接 patch `IsMechanoid` 会导致严重的副作用,强烈不推荐使用
6. **精确补丁**:用户提供的实现通过局部伪装成机械体来为动物启用工作系统,是一种更加精确和安全的方法

View File

@@ -0,0 +1,147 @@
# 蜂巢意识Hive Mind系统设计文档 - v2
## 1. 需求概述
本设计旨在为 `ArachnaeSwarm` Mod 实现一个“蜂巢意识”系统。该系统包含两种角色:
- **主节点 (Master)**:蜂巢的中心。
- **子节点 (Drone)**:蜂巢的工蜂,可以有多个。
它们之间通过 `Hediff`(健康状态)进行链接,实现以下核心功能:
1. **自动绑定**:子节点在生成时,会自动在地图上寻找携带 `ARA_HiveMindMaster` Hediff 的Pawn作为主节点。如果找到多个则选择第一个进行绑定。如果找不到主节点子节点会立即死亡。
2. **主从死亡联动**:当主节点死亡时,所有与之链接的子节点也会立即死亡。
3. **链接增益**:主节点的力量会随着链接的子节点数量增加而增强。具体表现为主节点的 `Hediff` 严重性Severity会随着子节点数量的增加而提升为后续添加属性加成提供基础。
## 2. 技术方案
为了实现上述功能,我们将创建以下组件:
### 2.1. XML 定义 (使用 ARA_ 前缀)
我们将定义两个新的 `HediffDef`:
- `HediffDef: ARA_HiveMindMaster`
- **hediffClass**: `ArachnaeSwarm.Hediff_HiveMindMaster`
- **描述**: 应用于主节点,用于管理子节点链接并根据数量调整严重性。
- `HediffDef: ARA_HiveMindDrone`
- **hediffClass**: `ArachnaeSwarm.Hediff_HiveMindDrone`
- **描述**: 应用于子节点,继承自 `HediffWithTarget`,其 `target` 字段将指向主节点。
### 2.2. C# 类定义 (命名空间: ArachnaeSwarm)
我们将实现两个新的C#类
- `Hediff_HiveMindMaster`
- 继承自 `Hediff`
- 包含一个 `List<Pawn>` 类型的字段 `drones`,用于存储所有已链接的子节点。
- 提供 `RegisterDrone(Pawn drone)``DeregisterDrone(Pawn drone)` 方法,用于添加和移除子节点。
- 在每次注册/反注册后,更新自身的 `Severity` 属性,其值等于 `drones.Count`
- 重写 `PostRemoved()` 方法在主节点死亡或Hediff被移除时杀死所有已注册的子节点。
- `Hediff_HiveMindDrone`
- 继承自 `HediffWithTarget`
- 重写 `PostAdd(DamageInfo? dinfo)` 方法。在此方法中:
1. 在当前地图上扫描所有Pawn查找携带 `ARA_HiveMindMaster` Hediff 的单位。
2. 如果找到至少一个,则选择第一个作为 `target`,并调用其 `RegisterDrone` 方法将自己注册进去。
3. 如果找不到任何主节点,立即杀死自己 (`pawn.Kill(null, null)`)。
- 重写 `PostRemoved()` 方法,在自身被移除时,如果 `target` 仍然有效,则调用其 `DeregisterDrone` 方法将自己从中移除。
-`PostTick()` 或类似方法中周期性检查 `target`(主节点)是否已死亡或 Hediff 已被移除。如果是,则立即杀死自己。
## 3. 开发步骤 (TODO List)
- [ ] **步骤 1: 创建 XML 定义**
-`ArachnaeSwarm/1.6/Defs/HediffDefs/` 目录下创建 `ARA_Hediffs_HiveMind.xml` 文件。
- [ ] **步骤 2: 实现 C# 类 `Hediff_HiveMindMaster`**
-`ArachnaeSwarm/Source/ArachnaeSwarm/` 目录下创建 `Hediff_HiveMindMaster.cs` 文件并编写代码。
- [ ] **步骤 3: 实现 C# 类 `Hediff_HiveMindDrone`**
-`ArachnaeSwarm/Source/ArachnaeSwarm/` 目录下创建 `Hediff_HiveMindDrone.cs` 文件并编写代码。
- [ ] **步骤 4: 更新项目文件**
- 将新创建的 `.cs` 文件添加到 `ArachnaeSwarm.csproj` 项目文件中。
- [ ] **步骤 5: 编译和测试**
- 运行 `dotnet build` 编译项目,修复所有编译错误。
- 进入游戏进行功能测试。
## 4. 参考代码
### `HediffWithTarget.cs`
```csharp
using Verse;
namespace RimWorld
{
public class HediffWithTarget : HediffWithComps
{
public Thing target;
public override bool ShouldRemove
{
get
{
if (target != null && !(target is Pawn { Dead: not false }))
{
return base.ShouldRemove;
}
return true;
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_References.Look(ref target, "target");
}
}
}
```
### `Hediff_PsychicBond.cs`
```csharp
using Verse;
namespace RimWorld
{
public class Hediff_PsychicBond : HediffWithTarget
{
private const int HediffCheckInterval = 65;
public override string LabelBase => base.LabelBase + " (" + target?.LabelShortCap + ")";
public override bool ShouldRemove
{
get
{
if (!base.ShouldRemove)
{
return pawn.Dead;
}
return true;
}
}
public override void PostRemoved()
{
base.PostRemoved();
Gene_PsychicBonding gene_PsychicBonding = base.pawn.genes?.GetFirstGeneOfType<Gene_PsychicBonding>();
if (gene_PsychicBonding != null)
{
gene_PsychicBonding.RemoveBond();
}
else if (target != null && target is Pawn pawn)
{
pawn.genes?.GetFirstGeneOfType<Gene_PsychicBonding>()?.RemoveBond();
}
}
public override void PostTickInterval(int delta)
{
base.PostTickInterval(delta);
if (pawn.IsHashIntervalTick(65, delta))
{
Severity = (ThoughtWorker_PsychicBondProximity.NearPsychicBondedPerson(pawn, this) ? 0.5f : 1.5f);
}
}
}
}

View File

@@ -0,0 +1,227 @@
# 技术文档RimWorld 中 `specialTrainables` 的工作机制解析 (V6 - 终极证据版)
## 1. 目标
本文档旨在深入剖析 RimWorld 中 `<specialTrainables>` 标签的底层工作机制,并最终得出一套可复用的“配方”,用于让动物学会在无需训练、无衰减的情况下,执行任何原版已存在的工作。本文档包含所有必要的、完整的原版代码引用作为证据,以确保其自包含性、正确性和健壮性,可供任何人在无上下文的情况下阅读并执行。
## 2. 核心机制深度解析
`specialTrainables` 的功能是一套精巧的、深度集成在 AI 思维逻辑中的 **条件行为分支**
### 2.1. 玩家授权机制
**关键发现**: 游戏通过一个统一的 UI 列 (`PawnColumnWorker_Trainable_Special`) 来管理所有被标记为 `specialTrainable` 的技能。当玩家点击该列的复选框时,会调用 `pawn.training.SetWantedRecursive()` 来设置 `Pawn_TrainingTracker``wantedTrainables` 字段的值。
* **证据**: 以下是 `PawnColumnWorker_Trainable_Special.txt` 的完整内容,它清晰地展示了 `SetWantedRecursive` 是如何被调用的。
```csharp
using System.Text;
using UnityEngine;
using Verse;
namespace RimWorld
{
public class PawnColumnWorker_Trainable_Special : PawnColumnWorker
{
public override void DoHeader(Rect rect, PawnTable table)
{
base.DoHeader(rect, table);
MouseoverSounds.DoRegion(rect);
}
public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
{
if (pawn.training != null && !pawn.RaceProps.specialTrainables.NullOrEmpty())
{
int num = (int)((rect.width - 24f) / 2f);
int num2 = Mathf.Max(3, 0);
Rect rect2 = new Rect(rect.x + (float)num, rect.y + (float)num2, 24f, 24f);
DoSpecialTrainableCheckbox(rect2, pawn, doTooltip: true);
}
}
private void DoSpecialTrainableCheckbox(Rect rect, Pawn pawn, bool doTooltip)
{
GetStatus(pawn, out var learned, out var checkOn, out var canTrain, out var _);
bool flag = checkOn;
Texture2D texChecked = (learned ? TrainingCardUtility.LearnedTrainingTex : null);
Texture2D texUnchecked = (learned ? TrainingCardUtility.LearnedNotTrainingTex : null);
Widgets.Checkbox(rect.position, ref checkOn, rect.width, !canTrain, paintable: true, texChecked, texUnchecked);
if (checkOn != flag)
{
PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.AnimalTraining, KnowledgeAmount.Total);
foreach (TrainableDef specialTrainable in pawn.RaceProps.specialTrainables)
{
pawn.training.SetWantedRecursive(specialTrainable, checkOn);
}
}
if (doTooltip)
{
DoSpecialTrainableTooltip(rect, pawn);
}
}
private void DoSpecialTrainableTooltip(Rect rect, Pawn pawn)
{
if (!Mouse.IsOver(rect))
{
return;
}
TooltipHandler.TipRegion(rect, delegate
{
StringBuilder stringBuilder = new StringBuilder();
foreach (TrainableDef specialTrainable in pawn.RaceProps.specialTrainables)
{
bool visible;
AcceptanceReport acceptanceReport = pawn.training.CanAssignToTrain(specialTrainable, out visible);
stringBuilder.AppendLineIfNotEmpty();
stringBuilder.AppendLine(specialTrainable.LabelCap + "\n\n" + specialTrainable.description);
if (!acceptanceReport.Accepted)
{
stringBuilder.AppendLine().AppendLine(acceptanceReport.Reason);
}
else if (!specialTrainable.prerequisites.NullOrEmpty())
{
stringBuilder.AppendLine();
foreach (TrainableDef prerequisite in specialTrainable.prerequisites)
{
if (!pawn.training.HasLearned(prerequisite))
{
stringBuilder.AppendLine("TrainingNeedsPrerequisite".Translate(prerequisite.LabelCap));
}
}
}
}
return stringBuilder.ToString();
}, (int)(rect.y * 511f + rect.x));
}
public override int GetMinWidth(PawnTable table)
{
return Mathf.Max(base.GetMinWidth(table), 24);
}
public override int GetMaxWidth(PawnTable table)
{
return Mathf.Min(base.GetMaxWidth(table), GetMinWidth(table));
}
public override int GetMinCellHeight(Pawn pawn)
{
return Mathf.Max(base.GetMinCellHeight(pawn), 24);
}
public override int Compare(Pawn a, Pawn b)
{
return GetValueToCompare(a).CompareTo(GetValueToCompare(b));
}
private int GetValueToCompare(Pawn pawn)
{
if (pawn.training == null || pawn.RaceProps.specialTrainables.NullOrEmpty())
{
return int.MinValue;
}
GetStatus(pawn, out var learned, out var checkOn, out var canTrain, out var visible);
if (learned)
{
return 4;
}
if (!visible)
{
return 0;
}
if (!canTrain)
{
return 1;
}
if (!checkOn)
{
return 2;
}
return 3;
}
private static void GetStatus(Pawn pawn, out bool learned, out bool checkOn, out bool canTrain, out bool visible)
{
learned = true;
checkOn = true;
canTrain = true;
visible = false;
foreach (TrainableDef specialTrainable in pawn.RaceProps.specialTrainables)
{
if (!pawn.training.HasLearned(specialTrainable))
{
learned = false;
}
if (!pawn.training.GetWanted(specialTrainable))
{
checkOn = false;
}
if (!pawn.training.CanAssignToTrain(specialTrainable, out var visible2))
{
canTrain = false;
}
if (visible2)
{
visible = true;
}
}
}
}
}
```
### 2.2. AI 决策机制
* **关键发现**: 我们可以为每个技能创建一个继承自 `ThinkNode_Conditional` 的决策节点,在 `Satisfied` 方法中通过检查 `pawn.training.GetWanted(def)` 来判断玩家是否授权。
## 3. 最终实施蓝图
### 阶段一:核心机制实现 (通用)
* **1.1: 实现瞬间训练 (`CompInstantTrain.cs`)**: 创建一个 `ThingComp`,在 `PostSpawnSetup` 中调用 `pawn.training.Train(def, null, true)`。
* **1.2: 引入 Harmony**: 在项目中添加 `0Harmony.dll` 引用并创建 `MainHarmony.cs` 初始化补丁。
* **1.3: 阻止训练衰减 (`Patch_TrainingTracker_TickRare.cs`)**: 创建一个对 `Pawn_TrainingTracker.TrainingTrackerTickRare` 的前缀补丁,对特殊动物返回 `false`。
### 阶段二:实现“种植” (`Growing`) 功能
* **2.1: (XML) 创建 `TrainableDef`**: 创建 `Defs/TrainableDefs/ARA_Sowing.xml`,定义 `ARA_Sowing`,并设 `<specialTrainable>true</specialTrainable>`。
* **2.2: (C#) 创建 AI 决策节点**: 创建 `Source/ArachnaeSwarm/ThinkNode_ConditionalAnimalShouldSow.cs`,并使用静态缓存 Def。
```csharp
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
[DefOf]
public static class ARA_TrainableDefOf
{
public static TrainableDef ARA_Sowing;
public static TrainableDef ARA_PlantCutting;
static ARA_TrainableDefOf() { DefOfHelper.EnsureInitializedInCtor(typeof(ARA_TrainableDefOf)); }
}
public class ThinkNode_ConditionalAnimalShouldSow : ThinkNode_Conditional
{
protected override bool Satisfied(Pawn pawn)
{
if (pawn.training == null) return false;
return pawn.training.HasLearned(ARA_TrainableDefOf.ARA_Sowing) &&
pawn.training.GetWanted(ARA_TrainableDefOf.ARA_Sowing);
}
}
}
```
* **2.3: (XML) 关联组件**:
* **PawnKindDef**: 在 `comps` 列表中添加 `CompProperties_InstantTrain` 并配置 `trainables`。
* **ThingDef**: 在 `specialTrainables` 列表中添加 `<li>ARA_Sowing</li>`。
* **ThinkTreeDef**: 添加 `<li Class="ArachnaeSwarm.ThinkNode_ConditionalAnimalShouldSow">` 节点,其子节点为 `<li Class="RimWorld.JobGiver_Work"><workType>Growing</workType></li>`。
### 阶段三:实现“植物割除” (`PlantCutting`) 功能
此阶段完全重复阶段二的模式,仅替换相应的名称 (`ARA_PlantCutting`, `ThinkNode_ConditionalAnimalShouldPlantCut`, `workType: PlantCutting`)。
### 阶段四:最终审查与打包
* **4.1**: 审查所有代码和 XML。
* **4.2**: 编译并进行游戏内测试。

View File

@@ -0,0 +1,38 @@
# 项目:可交互的虫卵囊
## 1. 核心目标
创建一个可交互的虫卵囊,它允许一个特定的 Pawn阿拉克涅女皇种通过右键菜单与它交互从一个可配置的列表中选择一个 Pawn并在经过一段可配置的延迟后生成这个 Pawn。
## 2. 已完成的功能
* **创建了新的 VS 项目**: [`ArachnaeSwarm.csproj`](Source/ArachnaeSwarm/ArachnaeSwarm.csproj)
* **实现了核心的生成逻辑**:
* `CompProperties_SpawnPawnFromList.cs`: 定义了 XML 中可配置的属性,包括:
* `pawnKinds`: 可生成的 Pawn 列表。
* `whitelist`: 可以与虫卵囊交互的 Pawn 列表。
* `delay`: 孵化延迟。
* `spawnCount`: 生成数量。
* `destroyOnSpawn`: 生成后是否摧毁自身。
* `lordJob`: 生成的 Pawn 要执行的集体任务。
* `CompSpawnPawnFromList.cs`: 实现了核心的生成逻辑,包括:
* 生成右键菜单。
* 处理孵化倒计时。
* 生成指定数量的 Pawn。
* 在检查面板上显示孵化状态和提示信息。
* **实现了交互的 Job**:
* `ARA_Jobs.xml`: 定义了 `ARA_IncubateJob`
* `JobDriver_Incubate.cs`: 实现了让 Pawn 走到虫卵囊旁边并启动孵化过程的逻辑。
* **实现了动态的图形切换**:
* `Building_Incubator.cs`: 创建了一个新的建筑基类,它会根据虫卵囊是否正在孵化来动态地改变自身的图形。
* **创建了测试用的 Defs**:
* `ARA_InteractiveEggSac.xml`: 定义了一个可交互的虫卵囊,用于在游戏中测试新功能。
* `ArachnaeSwarm_Keys.xml`: 定义了相关的本地化 `key`
## 3. 当前状态
目前,项目已经基本完成了所有的核心功能,并且能够成功编译。但是,在最后一次构建时,我们遇到了一个编译错误,导致我们无法进行最终的测试。
## 4. 下一步计划
解决当前的编译错误,并成功构建项目,以便在游戏中进行最终的测试。

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B