This commit is contained in:
2025-12-18 11:45:19 +08:00
parent 539e171e1b
commit b57d1dfdd2
10 changed files with 871 additions and 338 deletions

Binary file not shown.

View File

@@ -189,6 +189,66 @@
</children>
<positionRadius>0.1</positionRadius>
</EffecterDef>
<EffecterDef>
<defName>ARA_Double_Melee_Attack_Hit</defName>
<children>
<li>
<subEffecterClass>SubEffecter_Random</subEffecterClass>
<children>
<li>
<subEffecterClass>SubEffecter_SprayerTriggered</subEffecterClass>
<fleckDef>ARA_Mote_Melee_Attack_Main</fleckDef>
<burstCount>1</burstCount>
<color>(170,74,68)</color>
<scale>3.5~4.5</scale>
<speed>0.5</speed>
<angle>-35~35</angle>
<spawnLocType>OnSource</spawnLocType>
<fleckUsesAngleForVelocity>true</fleckUsesAngleForVelocity>
</li>
<li>
<subEffecterClass>SubEffecter_SprayerTriggered</subEffecterClass>
<fleckDef>ARA_Mote_Melee_Attack_Main</fleckDef>
<burstCount>1</burstCount>
<color>(147,50,28)</color>
<scale>2.5~3.5</scale>
<speed>0.5</speed>
<angle>-15~15</angle>
<spawnLocType>OnSource</spawnLocType>
<fleckUsesAngleForVelocity>true</fleckUsesAngleForVelocity>
</li>
</children>
</li>
<li>
<subEffecterClass>SubEffecter_Random</subEffecterClass>
<children>
<li>
<subEffecterClass>SubEffecter_SprayerTriggered</subEffecterClass>
<fleckDef>ARA_Mote_Melee_Attack_Main</fleckDef>
<burstCount>1</burstCount>
<color>(170,74,68)</color>
<scale>3.5~4.5</scale>
<speed>0.5</speed>
<angle>180~196</angle>
<spawnLocType>OnSource</spawnLocType>
<fleckUsesAngleForVelocity>true</fleckUsesAngleForVelocity>
</li>
<li>
<subEffecterClass>SubEffecter_SprayerTriggered</subEffecterClass>
<fleckDef>ARA_Mote_Melee_Attack_Main</fleckDef>
<burstCount>1</burstCount>
<color>(147,50,28)</color>
<scale>2.5~3.5</scale>
<speed>0.5</speed>
<angle>195~215</angle>
<spawnLocType>OnSource</spawnLocType>
<fleckUsesAngleForVelocity>true</fleckUsesAngleForVelocity>
</li>
</children>
</li>
</children>
<positionRadius>0.1</positionRadius>
</EffecterDef>
<FleckDef ParentName="FleckBase">
<defName>ARA_Fleck_Icez_Cloud</defName>

View File

@@ -91,10 +91,6 @@
<race>
<thinkTreeMain>ARA_Larva_Thinktree</thinkTreeMain>
</race>
<comps>
<li Class="ArachnaeSwarm.CompProperties_DraftableAnimal">
</li>
</comps>
</ThingDef>
<ThingDef ParentName="ArachnaeBase_Race">
<defName>ArachnaeBase_Race_Scavenger</defName>
@@ -102,6 +98,7 @@
<description>阿拉克涅辅虫之一,智力低下,可以执行种植、收割、搬运、清洁和挖掘工作,注定在度过短暂的时光后死亡。</description>
<race>
<specialTrainables>
<li MayRequire="Ludeon.RimWorld.Odyssey">AttackTarget</li>
<li>ARA_Sowing</li>
<li>Dig</li>
<li>ARA_Cleaning</li>
@@ -110,6 +107,31 @@
<comps>
<li Class="ArachnaeSwarm.CompProperties_AdvancedTraining">
<trainables>
<li>
<trainable>Obedience</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Release</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Rescue</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Tameness</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>AttackTarget</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Dig</trainable>
<trainInstantly>true</trainInstantly>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="ArachnaeBase_Race">
<defName>ArachnaeBeast_Race_Slayer</defName>
<label>阿拉克涅幼虫种</label>
<description>阿拉克涅辅虫之一,是虫族的根基。</description>
<race>
<thinkTreeMain>ARA_Insect_Beast</thinkTreeMain>
<specialTrainables>
<li MayRequire="Ludeon.RimWorld.Odyssey">AttackTarget</li>
</specialTrainables>
</race>
<tools Inherit="False">
<li>
<label>挥击</label>
<capacities>
<li>ARA_MW_Scything_Talons_Cut</li>
</capacities>
<power>65</power>
<armorPenetration>2</armorPenetration>
<cooldownTime>2</cooldownTime>
</li>
</tools>
<comps>
<li Class="ArachnaeSwarm.CompProperties_Cleave">
<cleaveAngle>120</cleaveAngle>
<cleaveRange>4</cleaveRange>
<cleaveDamageFactor>0.75</cleaveDamageFactor>
<damageDowned>false</damageDowned>
<explosionDamageDef>Cut</explosionDamageDef>
<attackEffecter>ARA_Double_Melee_Attack_Hit</attackEffecter>
<cleaveEffecter>ARA_Double_Melee_Attack_Hit</cleaveEffecter>
</li>
<li Class="ArachnaeSwarm.CompProperties_AdvancedTraining">
<trainables>
<li>
<trainable>Obedience</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Release</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Rescue</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>Tameness</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
<li>
<trainable>AttackTarget</trainable>
<trainInstantly>true</trainInstantly>
<setWanted>true</setWanted>
</li>
</trainables>
<disableAllSkillDecay>true</disableAllSkillDecay> <!-- 阻止这个动物的所有技能衰减 -->
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -31,7 +31,7 @@
<li Class="ThinkNode_QueuedJob"/>
<!-- Wait if drafted -->
<li Class="ThinkNode_ConditionalColonist">
<li Class="ThinkNode_ConditionalOfPlayerFaction">
<subNodes>
<li Class="ThinkNode_Tagger">
<tagToGive>DraftedOrder</tagToGive>
@@ -139,7 +139,7 @@
</ThinkTreeDef>
<ThinkTreeDef>
<defName>ARA_Insect_WithPlanting</defName>
<defName>ARA_Insect_Beast</defName>
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<!-- Keep lying down if we have to -->
@@ -171,17 +171,67 @@
<!-- Do a queued job -->
<li Class="ThinkNode_QueuedJob"/>
<!-- Wild insects dig out if no path to map edge and starving -->
<!-- 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>
<li Class="ThinkNode_ConditionalStarving">
<!-- 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_ConditionalBodySize">
<min>0.7</min>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
<li Class="ThinkNode_Subtree">
<treeDef>DigOutIfCannotReachMapEdge</treeDef>
<li Class="JobGiver_ExitMapRandom">
<defaultLocomotion>Walk</defaultLocomotion>
</li>
</subNodes>
</li>
@@ -190,19 +240,278 @@
</subNodes>
</li>
<!-- Leave if timed out -->
<li Class="ThinkNode_ConditionalExitTimedOut">
<!-- 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_AIFightEnemies">
<targetAcquireRadius>30</targetAcquireRadius>
<targetKeepRadius>35</targetKeepRadius>
</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>500</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>
<!-- 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>
</subNodes>
</li>
<!-- Tame animal: 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_ExitMapRandom">
<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>
<ThinkTreeDef>
<defName>ARA_Insect_WithPlanting</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"/>
<!-- Mental state non critical -->
<li Class="ThinkNode_Subtree">
@@ -454,13 +763,6 @@
<li Class="JobGiver_Mine" />
</subNodes>
</li>
<!-- Trained behavior: Mine
<li Class="ThinkNode_ConditionalTrainableCompleted" MayRequire="Ludeon.RimWorld.Odyssey">
<trainable>Dig</trainable>
<subNodes>
</subNodes>
</li>-->
<!-- OUR CUSTOM LOGIC INJECTION FOR PLANT HARVESTING -->
<li Class="ArachnaeSwarm.ThinkNode_ConditionalAnimalShouldDoGrowingWork">
@@ -479,15 +781,7 @@
</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 -->
<!-- Tame animal: wander near colony if possible -->
<li Class="ThinkNode_ConditionalOfPlayerFaction">
<subNodes>
<li Class="ThinkNode_Tagger">
@@ -539,17 +833,17 @@
</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"/>
<li Class="JobGiver_PatientGoToBed" />
</subNodes>
</li>
<li Class="ThinkNode_Tagger">
<tagToGive>Misc</tagToGive>
<subNodes>
@@ -560,7 +854,7 @@
</li>
</subNodes>
</li>
<!-- Wander -->
<li Class="ThinkNode_Tagger">
<tagToGive>Idle</tagToGive>
@@ -573,10 +867,10 @@
</li>
</subNodes>
</li>
<li Class="JobGiver_WanderAnywhere">
<maxDanger>Deadly</maxDanger>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
<ticksBetweenWandersRange>120~240</ticksBetweenWandersRange>
</li>
</subNodes>
</li>

View File

@@ -19,5 +19,74 @@
<!-- 在UI中的排序 -->
<listPriority>100</listPriority>
</TrainableDef>
<TrainableDef>
<defName>ARA_Sowing</defName>
<label>种植</label>
<description>允许该生物执行种植任务。</description>
<!-- 标记为特殊训练,这样它就会被 PawnColumnWorker_Trainable_Special 统一管理 -->
<specialTrainable>true</specialTrainable>
<!-- 训练难度和所需智力 -->
<difficulty>5</difficulty>
<requiredTrainability>Advanced</requiredTrainability>
<!-- 训练所需步骤 -->
<steps>3</steps>
<!-- 在UI中的排序 -->
<listPriority>100</listPriority>
</TrainableDef>
<TrainableDef>
<defName>ARA_Slayer_Ability1_Train</defName>
<label>暴屠冲撞</label>
<description></description>
<listPriority>0</listPriority>
<difficulty>200</difficulty>
<steps>1</steps>
<specialTrainable>true</specialTrainable>
<enablesAbility>ARA_Ability_SlayerCharge</enablesAbility>
</TrainableDef>
<AbilityDef>
<defName>ARA_Ability_SlayerCharge</defName>
<label>暴屠冲撞</label>
<description>以庞大的身躯冲撞目标,对路径上的一切造成伤害。在冲击中途经的距离越远,伤害越高。</description>
<iconPath>ArachnaeSwarm/UI/Abilities/ARA_Ability_TrackingCharge</iconPath> <!-- Placeholder Icon -->
<cooldownTicksRange>6000</cooldownTicksRange>
<verbProperties>
<verbClass>ArachnaeSwarm.Verb_CastAbilityTrackingCharge</verbClass>
<label>追踪冲撞</label>
<targetParams>
<canTargetPawns>true</canTargetPawns>
<canTargetBuildings>true</canTargetBuildings>
<canTargetAnimals>true</canTargetAnimals>
<canTargetMechs>true</canTargetMechs>
<canTargetSelf>false</canTargetSelf>
</targetParams>
<range>18</range>
<warmupTime>1.5</warmupTime>
</verbProperties>
<comps>
<li Class="CompProperties_AbilityRequiresTrainable">
<trainableDef>ARA_Slayer_Ability1_Train</trainableDef>
<aiCanCastWithoutTrainable>true</aiCanCastWithoutTrainable>
</li>
<li Class="ArachnaeSwarm.CompProperties_TrackingCharge">
<homingSpeed>1.5</homingSpeed>
<initialDamage>50</initialDamage>
<damagePerTile>3</damagePerTile>
<inertiaDistance>6</inertiaDistance>
<collisionDamageDef>Blunt</collisionDamageDef>
<flyerDef>ARA_Flyer_TrackingCharge</flyerDef>
<collisionRadius>2.5</collisionRadius> <!-- Larger collision radius -->
<impactSound>Pawn_Melee_BigBash_HitPawn</impactSound>
<damageHostileOnly>true</damageHostileOnly> <!-- Set to false to damage everyone in the path -->
</li>
<li Class="CompProperties_AbilityEffecterOnCaster">
<effecterDef>WarTrumpet</effecterDef>
<maintainTicks>20</maintainTicks> <!-- Long enough for the "2nd wave" to spawn -->
</li>
</comps>
</AbilityDef>
</Defs>