11
This commit is contained in:
Binary file not shown.
@@ -4,14 +4,15 @@
|
||||
<defName>ARA_HiveMindMaster</defName>
|
||||
<label>阿拉克涅女皇种</label>
|
||||
<description>阿拉克涅女皇种是虫群意识的中心节点, 作为主脑统御整个阿拉克涅虫群。其体内拥有大量未分化的修复细胞,可以以常人无法想象的速度自行治愈所有的创伤。</description>
|
||||
<hediffClass>ArachnaeSwarm.Hediff_HiveMindMaster</hediffClass>
|
||||
<!-- <hediffClass>ArachnaeSwarm.Hediff_HiveMindMaster</hediffClass> -->
|
||||
<hediffClass>HediffWithComps</hediffClass>
|
||||
<defaultLabelColor>(0.8, 0.3, 0.8)</defaultLabelColor>
|
||||
<isBad>false</isBad>
|
||||
<scenarioCanAdd>false</scenarioCanAdd>
|
||||
<maxSeverity>100</maxSeverity>
|
||||
<stages>
|
||||
<li>
|
||||
<label>连接至 {0} 个虫群工蜂</label>
|
||||
<!-- <label>连接至 {0} 个虫群工蜂</label> -->
|
||||
<minSeverity>0</minSeverity>
|
||||
<foodPoisoningChanceFactor>0</foodPoisoningChanceFactor>
|
||||
<!-- Stat offsets will be added here later -->
|
||||
@@ -28,16 +29,20 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_HiveMindMaster">
|
||||
<scanIntervalTicks>3200</scanIntervalTicks>
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_GestaltNode">
|
||||
<nodeType>OverlordNode</nodeType>
|
||||
</li>
|
||||
<!-- <li Class="ArachnaeSwarm.HediffCompProperties_HiveMindMaster">
|
||||
<scanIntervalTicks>3200</scanIntervalTicks>
|
||||
</li> -->
|
||||
</comps>
|
||||
</HediffDef>
|
||||
<HediffDef>
|
||||
<defName>ARA_HiveMindDrone</defName>
|
||||
<label>阿拉克涅督虫</label>
|
||||
<description>阿拉克涅督虫通过心灵与阿拉克涅女皇种相链接。如果女皇死亡,督虫也将停止生命活动。</description>
|
||||
<hediffClass>ArachnaeSwarm.Hediff_HiveMindDrone</hediffClass>
|
||||
<!-- <hediffClass>ArachnaeSwarm.Hediff_HiveMindDrone</hediffClass> -->
|
||||
<hediffClass>HediffWithComps</hediffClass>
|
||||
<defaultLabelColor>(0.6, 0.4, 0.8)</defaultLabelColor>
|
||||
<isBad>false</isBad>
|
||||
<scenarioCanAdd>false</scenarioCanAdd>
|
||||
@@ -45,6 +50,13 @@
|
||||
<li>
|
||||
<minSeverity>0</minSeverity>
|
||||
<foodPoisoningChanceFactor>0</foodPoisoningChanceFactor>
|
||||
<enablesNeeds>
|
||||
<li>ARA_ChitinArmor</li>
|
||||
</enablesNeeds>
|
||||
</li>
|
||||
<li>
|
||||
<minSeverity>1</minSeverity>
|
||||
<foodPoisoningChanceFactor>0</foodPoisoningChanceFactor>
|
||||
<disablesNeeds>
|
||||
<li>Mood</li>
|
||||
<li>Joy</li>
|
||||
@@ -61,15 +73,18 @@
|
||||
</li>
|
||||
</stages>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_HiveMindDrone">
|
||||
<unlinkedDieDelayTicks>6400</unlinkedDieDelayTicks> <!-- Default to 30 seconds -->
|
||||
<li Class="ArachnaeSwarm.HediffCompProperties_GestaltNode">
|
||||
<nodeType>HiveNode</nodeType>
|
||||
</li>
|
||||
<li Class="HediffCompProperties_MessageAfterTicks">
|
||||
<!-- <li Class="ArachnaeSwarm.HediffCompProperties_HiveMindDrone">
|
||||
<unlinkedDieDelayTicks>6400</unlinkedDieDelayTicks>
|
||||
</li> -->
|
||||
<!-- <li Class="HediffCompProperties_MessageAfterTicks">
|
||||
<ticks>1</ticks>
|
||||
<letterLabel>{0_labelShort} 诞生</letterLabel>
|
||||
<letterText>一只新的阿拉克涅督虫 {0_labelShort} 已经破茧而出!她正在四处徘徊,等待女皇种的指示——使用阿拉克涅女皇种的信息素标记技能完成链接,或者等待其自行建立链接。</letterText>
|
||||
<letterType>HumanPregnancy</letterType>
|
||||
</li>
|
||||
</li> -->
|
||||
<li Class="HediffCompProperties_RemoveIfOtherHediff">
|
||||
<hediffs>
|
||||
<li>ARA_NonPlayer_HiveMindDroneHediff</li>
|
||||
@@ -77,6 +92,36 @@
|
||||
</li>
|
||||
</comps>
|
||||
</HediffDef>
|
||||
<PawnRelationDef>
|
||||
<defName>ARA_GestaltOverseer</defName>
|
||||
<label>节点监管</label>
|
||||
<workerClass>ArachnaeSwarm.PawnRelationWorker_GestaltOverseer</workerClass>
|
||||
<importance>185</importance>
|
||||
<implied>false</implied>
|
||||
<opinionOffset>100</opinionOffset>
|
||||
<generationChanceFactor>0</generationChanceFactor>
|
||||
<romanceChanceFactor>0</romanceChanceFactor>
|
||||
<incestOpinionOffset>0</incestOpinionOffset>
|
||||
<inbredChanceOnChild>0</inbredChanceOnChild>
|
||||
<familyByBloodRelation>true</familyByBloodRelation>
|
||||
<removeOnDeath>true</removeOnDeath>
|
||||
<removeOnLeftBehind>true</removeOnLeftBehind>
|
||||
<reflexive>true</reflexive>
|
||||
</PawnRelationDef>
|
||||
<ThoughtDef>
|
||||
<defName>ARA_HiveMindDrone_Though</defName>
|
||||
<workerClass>ThoughtWorker_Hediff</workerClass>
|
||||
<hediff>ARA_HiveMindDrone</hediff>
|
||||
<validWhileDespawned>true</validWhileDespawned>
|
||||
<developmentalStageFilter>Baby, Child, Adult</developmentalStageFilter>
|
||||
<stages>
|
||||
<li>
|
||||
<label>失联恐惧</label>
|
||||
<description>我身体中的本能正在呼唤节点监管!</description>
|
||||
<baseMoodEffect>-99999</baseMoodEffect>
|
||||
</li>
|
||||
</stages>
|
||||
</ThoughtDef>
|
||||
<HediffDef>
|
||||
<defName>ARA_NonPlayer_HiveMindDroneHediff</defName>
|
||||
<label>野性虫群</label>
|
||||
|
||||
@@ -536,6 +536,8 @@
|
||||
<ForagedNutritionPerDay>0</ForagedNutritionPerDay>
|
||||
<ComfyTemperatureMin>-3000</ComfyTemperatureMin>
|
||||
<ComfyTemperatureMax>3000</ComfyTemperatureMax>
|
||||
|
||||
<BandwidthCost>1</BandwidthCost>
|
||||
</statBases>
|
||||
|
||||
<race>
|
||||
|
||||
@@ -468,6 +468,7 @@
|
||||
<cannotReceiveThoughts>
|
||||
<li>ColonistLost</li>
|
||||
<li>KnowColonistDied</li>
|
||||
<li>PawnWithGoodOpinionDied</li>
|
||||
<li>PsychicDrone</li>
|
||||
<li>Naked</li>
|
||||
<li>AnyBodyPartButGroinCovered_Disapproved_Female</li>
|
||||
@@ -612,6 +613,9 @@
|
||||
|
||||
<!-- 在野外采集的营养 -->
|
||||
<ForagedNutritionPerDay>0</ForagedNutritionPerDay>
|
||||
|
||||
<MechBandwidth>8</MechBandwidth>
|
||||
<MechControlGroups>1</MechControlGroups>
|
||||
</statBases>
|
||||
|
||||
<race>
|
||||
@@ -779,6 +783,8 @@
|
||||
<toggleDescription>这只阿拉克涅虫族的身躯是如此巨大,以至于靠近它的敌人会被直接一脚踩死</toggleDescription>
|
||||
<toggleIconPath>ArachnaeSwarm/UI/Abilities/ARA_Area_Crush</toggleIconPath>
|
||||
</li>
|
||||
<!-- 添加 Gestalt 组件 -->
|
||||
<li Class="ArachnaeSwarm.CompProperties_Gestalt" />
|
||||
</comps>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
</Defs>
|
||||
@@ -130,4 +130,7 @@
|
||||
|
||||
<ARA_EjectedOrgans>成功将 {0} 的内脏全部翻出</ARA_EjectedOrgans>
|
||||
<ARA_NoEjectableOrgans>目标没有可以翻出的器官</ARA_NoEjectableOrgans>
|
||||
|
||||
<AreaDamageEnabled>区域伤害启动</AreaDamageEnabled>
|
||||
<AreaDamageDisabled>区域伤害关闭</AreaDamageDisabled>
|
||||
</LanguageData>
|
||||
@@ -4,4 +4,10 @@
|
||||
<!-- Guardian Psy-Field Gizmo -->
|
||||
<ARA_GuardianFieldGizmoLabel>守护者力场</ARA_GuardianFieldGizmoLabel>
|
||||
|
||||
<ARA_GestaltGroup>蜂巢网络</ARA_GestaltGroup>
|
||||
<ARA_NoGestaltPawns>无节点生物</ARA_NoGestaltPawns>
|
||||
<ARA_GestaltBandwidth>监管网络负荷</ARA_GestaltBandwidth>
|
||||
|
||||
<ARA_GestaltBandwidthTip>蜂巢网络是阿拉克涅虫群用于建立格式塔思维簇的体系,这使得整个族群可以在女皇种的统一指挥下获得强大的一致性。</ARA_GestaltBandwidthTip>
|
||||
<ARA_GestaltBandwidthExceeded>警告:蜂巢网络正在超载,这将会直接影响女皇种的心情,并有可能导致整个网络的传导性崩溃!</ARA_GestaltBandwidthExceeded>
|
||||
</LanguageData>
|
||||
Binary file not shown.
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\trackingcharge\\pawnflyer_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\trackingcharge\\pawnflyer_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_gestaltnode\\hediffcomp_gestaltnode.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_gestaltnode\\hediffcomp_gestaltnode.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\trackingcharge\\compabilityeffect_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\trackingcharge\\compabilityeffect_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_gestaltnode\\gestaltbandwidthgizmo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_gestaltnode\\gestaltbandwidthgizmo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\trackingcharge\\verb_castabilitytrackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\trackingcharge\\verb_castabilitytrackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_gestaltnode\\gestaltcontrolgroup.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_gestaltnode\\gestaltcontrolgroup.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\trackingcharge\\compproperties_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\trackingcharge\\compproperties_trackingcharge.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_gestaltnode\\gestaltcontrolgroupgizmo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_gestaltnode\\gestaltcontrolgroupgizmo.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
@@ -26,8 +26,21 @@
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 2,
|
||||
"SelectedChildIndex": 0,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "HediffComp_GestaltNode.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_GestaltNode\\HediffComp_GestaltNode.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABQAAAAnAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2026-01-20T08:24:06.173Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
@@ -35,51 +48,41 @@
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "Verb_CastAbilityTrackingCharge.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\Verb_CastAbilityTrackingCharge.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\TrackingCharge\\Verb_CastAbilityTrackingCharge.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\Verb_CastAbilityTrackingCharge.cs",
|
||||
"RelativeToolTip": "Abilities\\TrackingCharge\\Verb_CastAbilityTrackingCharge.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABIAAAANAAAAAAAAAA==",
|
||||
"Title": "GestaltControlGroup.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltControlGroup.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_GestaltNode\\GestaltControlGroup.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltControlGroup.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_GestaltNode\\GestaltControlGroup.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-12-31T03:34:14.205Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "PawnFlyer_TrackingCharge.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\PawnFlyer_TrackingCharge.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\TrackingCharge\\PawnFlyer_TrackingCharge.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\PawnFlyer_TrackingCharge.cs",
|
||||
"RelativeToolTip": "Abilities\\TrackingCharge\\PawnFlyer_TrackingCharge.cs",
|
||||
"ViewState": "AgIAAIwBAAAAAAAAAAAAAKMBAAA3AAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-12-31T03:34:13.727Z",
|
||||
"WhenOpened": "2026-01-20T08:01:28.552Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "CompProperties_TrackingCharge.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\CompProperties_TrackingCharge.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\TrackingCharge\\CompProperties_TrackingCharge.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\CompProperties_TrackingCharge.cs",
|
||||
"RelativeToolTip": "Abilities\\TrackingCharge\\CompProperties_TrackingCharge.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Title": "GestaltControlGroupGizmo.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltControlGroupGizmo.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_GestaltNode\\GestaltControlGroupGizmo.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltControlGroupGizmo.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_GestaltNode\\GestaltControlGroupGizmo.cs",
|
||||
"ViewState": "AgIAAEAAAAAAAAAAAAAUwCwAAABBAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-12-31T03:34:13.26Z"
|
||||
"WhenOpened": "2026-01-20T07:59:09.365Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CompAbilityEffect_TrackingCharge.cs",
|
||||
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\CompAbilityEffect_TrackingCharge.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\TrackingCharge\\CompAbilityEffect_TrackingCharge.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\TrackingCharge\\CompAbilityEffect_TrackingCharge.cs",
|
||||
"RelativeToolTip": "Abilities\\TrackingCharge\\CompAbilityEffect_TrackingCharge.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAABAAAAAAAAAA==",
|
||||
"Title": "GestaltBandwidthGizmo.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltBandwidthGizmo.cs",
|
||||
"RelativeDocumentMoniker": "Hediffs\\ARA_GestaltNode\\GestaltBandwidthGizmo.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_GestaltNode\\GestaltBandwidthGizmo.cs",
|
||||
"RelativeToolTip": "Hediffs\\ARA_GestaltNode\\GestaltBandwidthGizmo.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAuwBMAAAA2AAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-12-31T03:34:12.758Z"
|
||||
"WhenOpened": "2026-01-20T07:59:08.824Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -50,4 +50,16 @@ namespace ArachnaeSwarm
|
||||
DefOfHelper.EnsureInitializedInCtor(typeof(ARA_SoundDefOf));
|
||||
}
|
||||
}
|
||||
|
||||
[DefOf]
|
||||
public static class ARA_PawnRelationDefOf
|
||||
{
|
||||
public static PawnRelationDef ARA_GestaltOverseer;
|
||||
|
||||
static ARA_PawnRelationDefOf()
|
||||
{
|
||||
DefOfHelper.EnsureInitializedInCtor(typeof(ARA_PawnRelationDefOf));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Hediffs\ARA_GestaltNode\CompGestalt.cs" />
|
||||
<Compile Include="Hediffs\ARA_GestaltNode\CompProperties_Gestalt.cs" />
|
||||
<Compile Include="Hediffs\ARA_GestaltNode\GestaltBandwidthGizmo.cs" />
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\..\..\..\..\..\workshop\content\294100\2009463077\1.5\Assemblies\0Harmony.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
@@ -75,7 +78,6 @@
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Compile Include="**\*.cs" Exclude="bin\**;obj\**" />
|
||||
<Folder Include="FacialAnimation\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 自定义清理任务,删除obj文件夹中的临时文件 -->
|
||||
|
||||
86
Source/ArachnaeSwarm/Hediffs/ARA_GestaltNode/CompGestalt.cs
Normal file
86
Source/ArachnaeSwarm/Hediffs/ARA_GestaltNode/CompGestalt.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompGestalt : ThingComp
|
||||
{
|
||||
private Pawn_GestaltTracker tracker;
|
||||
|
||||
public Pawn_GestaltTracker GestaltTracker
|
||||
{
|
||||
get
|
||||
{
|
||||
if (tracker == null)
|
||||
{
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn != null && pawn.IsGestaltNode(GestaltNodeType.OverlordNode))
|
||||
{
|
||||
tracker = new Pawn_GestaltTracker(pawn);
|
||||
}
|
||||
}
|
||||
return tracker;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
|
||||
// 初始化 tracker
|
||||
if (GestaltTracker != null)
|
||||
{
|
||||
// 确保控制组数量正确
|
||||
GestaltTracker.Notify_ControlGroupAmountChanged();
|
||||
|
||||
// 加载时重新连接已控制的 pawn
|
||||
if (respawningAfterLoad)
|
||||
{
|
||||
ReconnectControlledPawns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReconnectControlledPawns()
|
||||
{
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null) return;
|
||||
|
||||
// 查找所有有 GestaltOverseer 关系的 pawn
|
||||
List<DirectPawnRelation> relations = pawn.relations.DirectRelations;
|
||||
foreach (DirectPawnRelation relation in relations)
|
||||
{
|
||||
if (relation.def == ARA_PawnRelationDefOf.ARA_GestaltOverseer)
|
||||
{
|
||||
Pawn hiveNode = relation.otherPawn;
|
||||
if (hiveNode != null && hiveNode.IsGestaltNode(GestaltNodeType.HiveNode))
|
||||
{
|
||||
GestaltTracker?.AssignPawnToControlGroup(hiveNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
Pawn pawn = parent as Pawn;
|
||||
if (pawn == null || !pawn.IsGestaltNode(GestaltNodeType.OverlordNode))
|
||||
yield break;
|
||||
|
||||
if (GestaltTracker == null)
|
||||
yield break;
|
||||
|
||||
foreach (Gizmo gizmo in GestaltTracker.GetGizmos())
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Deep.Look(ref tracker, "gestaltTracker", parent as Pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_Gestalt : CompProperties
|
||||
{
|
||||
public CompProperties_Gestalt()
|
||||
{
|
||||
this.compClass = typeof(CompGestalt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class GestaltBandwidthGizmo : Gizmo
|
||||
{
|
||||
private Pawn_GestaltTracker tracker;
|
||||
|
||||
public GestaltBandwidthGizmo(Pawn_GestaltTracker tracker)
|
||||
{
|
||||
this.tracker = tracker;
|
||||
this.Order = -90f; // 放在最前面
|
||||
}
|
||||
|
||||
public override bool Visible => tracker != null && tracker.Pawn != null && tracker.Pawn.IsGestaltNode(GestaltNodeType.OverlordNode);
|
||||
|
||||
public override float GetWidth(float maxWidth)
|
||||
{
|
||||
return 140f;
|
||||
}
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
|
||||
Rect rect2 = rect.ContractedBy(6f);
|
||||
|
||||
// 背景
|
||||
GUI.color = parms.lowLight ? Command.LowLightBgColor : Color.white;
|
||||
GenUI.DrawTextureWithMaterial(rect, Command.BGTex, null);
|
||||
GUI.color = Color.white;
|
||||
|
||||
// 标题
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.UpperCenter;
|
||||
Widgets.Label(new Rect(rect2.x, rect2.y, rect2.width, 18f), "ARA_GestaltBandwidth".Translate());
|
||||
|
||||
// 带宽条
|
||||
Rect barRect = new Rect(rect2.x, rect2.y + 20f, rect2.width, 20f);
|
||||
float fillPercent = (float)tracker.UsedBandwidth / tracker.TotalBandwidth;
|
||||
Widgets.FillableBar(barRect, fillPercent, SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.6f, 0.8f)));
|
||||
|
||||
// 带宽文本
|
||||
Text.Font = GameFont.Small;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
string bandwidthText = $"{tracker.UsedBandwidth}/{tracker.TotalBandwidth}";
|
||||
Widgets.Label(barRect, bandwidthText);
|
||||
|
||||
// 控制组数量
|
||||
Rect groupRect = new Rect(rect2.x, rect2.y + 45f, rect2.width, 20f);
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
string groupText = "ARA_GestaltGroup".Translate() + $": {tracker.ControlGroups.Count}/{tracker.TotalAvailableControlGroups}";
|
||||
Widgets.Label(groupRect, groupText);
|
||||
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
Text.Font = GameFont.Small;
|
||||
|
||||
// 鼠标悬停提示
|
||||
if (Mouse.IsOver(rect))
|
||||
{
|
||||
TooltipHandler.TipRegion(rect, () =>
|
||||
{
|
||||
string tip = "ARA_GestaltBandwidthTip".Translate(tracker.UsedBandwidth, tracker.TotalBandwidth);
|
||||
tip += $"\n\n{"ARA_GestaltGroup".Translate()}: {tracker.ControlGroups.Count}/{tracker.TotalAvailableControlGroups}";
|
||||
|
||||
if (tracker.UsedBandwidth > tracker.TotalBandwidth)
|
||||
{
|
||||
tip += $"\n\n{"ARA_GestaltBandwidthExceeded".Translate()}".Colorize(Color.red);
|
||||
}
|
||||
|
||||
return tip;
|
||||
}, 7234342);
|
||||
|
||||
Widgets.DrawHighlight(rect);
|
||||
}
|
||||
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class GestaltControlGroup : IExposable
|
||||
{
|
||||
private List<Pawn> assignedPawns = new List<Pawn>();
|
||||
private Pawn_GestaltTracker tracker;
|
||||
|
||||
public List<Pawn> AssignedPawns => assignedPawns;
|
||||
public Pawn_GestaltTracker Tracker => tracker;
|
||||
public int Index => Tracker.ControlGroups.IndexOf(this) + 1;
|
||||
|
||||
public GestaltControlGroup(Pawn_GestaltTracker tracker)
|
||||
{
|
||||
this.tracker = tracker;
|
||||
}
|
||||
|
||||
public bool TryUnassign(Pawn pawn)
|
||||
{
|
||||
return assignedPawns.Remove(pawn);
|
||||
}
|
||||
|
||||
public void Assign(Pawn pawn)
|
||||
{
|
||||
// 先从其他控制组移除
|
||||
foreach (GestaltControlGroup controlGroup in tracker.ControlGroups)
|
||||
{
|
||||
controlGroup.TryUnassign(pawn);
|
||||
}
|
||||
|
||||
assignedPawns.Add(pawn);
|
||||
|
||||
// 唤醒休眠的pawn
|
||||
pawn.TryGetComp<CompCanBeDormant>()?.WakeUp();
|
||||
pawn.jobs?.CheckForJobOverride();
|
||||
}
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_Collections.Look(ref assignedPawns, "assignedPawns", LookMode.Reference);
|
||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
assignedPawns.RemoveAll((Pawn x) => x == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class GestaltControlGroupGizmo : Gizmo
|
||||
{
|
||||
private GestaltControlGroup controlGroup;
|
||||
|
||||
public override bool Visible => controlGroup.AssignedPawns.Count > 0;
|
||||
public override float Order => -89f;
|
||||
|
||||
public GestaltControlGroupGizmo(GestaltControlGroup controlGroup)
|
||||
{
|
||||
this.controlGroup = controlGroup;
|
||||
}
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
|
||||
Rect innerRect = rect.ContractedBy(6f);
|
||||
|
||||
// 背景
|
||||
GUI.color = parms.lowLight ? Command.LowLightBgColor : Color.white;
|
||||
GenUI.DrawTextureWithMaterial(rect, Command.BGTex, null);
|
||||
GUI.color = Color.white;
|
||||
|
||||
// 控制组编号
|
||||
Text.Font = GameFont.Small;
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
string label = "ARA_GestaltGroup".Translate();
|
||||
Widgets.Label(innerRect, label);
|
||||
|
||||
// 显示被控制的pawn
|
||||
Rect pawnRect = new Rect(innerRect.x, innerRect.y + 20f, innerRect.width, innerRect.height - 20f);
|
||||
|
||||
List<Pawn> assignedPawns = controlGroup.AssignedPawns;
|
||||
if (assignedPawns.Count == 0)
|
||||
{
|
||||
GUI.color = ColoredText.SubtleGrayColor;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(pawnRect, "(" + "ARA_NoGestaltPawns".Translate() + ")");
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
GUI.color = Color.white;
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
// 计算pawn图标布局
|
||||
float iconSize = Mathf.Min(pawnRect.width / assignedPawns.Count, pawnRect.height);
|
||||
float spacing = (pawnRect.width - (iconSize * assignedPawns.Count)) / (assignedPawns.Count + 1);
|
||||
|
||||
for (int i = 0; i < assignedPawns.Count; i++)
|
||||
{
|
||||
Rect iconRect = new Rect(
|
||||
pawnRect.x + spacing + (iconSize + spacing) * i,
|
||||
pawnRect.y + (pawnRect.height - iconSize) / 2,
|
||||
iconSize,
|
||||
iconSize
|
||||
);
|
||||
|
||||
Pawn pawn = assignedPawns[i];
|
||||
Widgets.ThingIcon(iconRect, pawn);
|
||||
|
||||
if (Mouse.IsOver(iconRect))
|
||||
{
|
||||
Widgets.DrawHighlight(iconRect);
|
||||
TooltipHandler.TipRegion(iconRect, pawn.LabelCap);
|
||||
|
||||
if (Widgets.ButtonInvisible(iconRect))
|
||||
{
|
||||
CameraJumper.TryJumpAndSelect(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
public override float GetWidth(float maxWidth)
|
||||
{
|
||||
return 130f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using ArachnaeSwarm;
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public static class GestaltUtility
|
||||
{
|
||||
public static Pawn GetOverlord(this Pawn pawn)
|
||||
{
|
||||
List<DirectPawnRelation> relations = pawn.relations.DirectRelations;
|
||||
for (int i = 0; i < relations.Count; i++)
|
||||
{
|
||||
if (relations[i].def == ARA_PawnRelationDefOf.ARA_GestaltOverseer)
|
||||
{
|
||||
return relations[i].otherPawn;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Pawn_GestaltTracker GestaltTracker(this Pawn pawn)
|
||||
{
|
||||
HediffComp_GestaltNode comp = pawn.GetGestaltNodeComp();
|
||||
return comp?.GestaltTracker;
|
||||
}
|
||||
|
||||
public static void GetHiveNodesInAssignedOrder(Pawn overlord, ref List<Pawn> outHiveNodes)
|
||||
{
|
||||
outHiveNodes.Clear();
|
||||
Pawn_GestaltTracker tracker = overlord.GestaltTracker();
|
||||
if (tracker == null)
|
||||
return;
|
||||
|
||||
foreach (GestaltControlGroup group in tracker.ControlGroups)
|
||||
{
|
||||
foreach (Pawn pawn in group.AssignedPawns)
|
||||
{
|
||||
if (!outHiveNodes.Contains(pawn) && pawn.IsGestaltNode(GestaltNodeType.HiveNode))
|
||||
{
|
||||
outHiveNodes.Add(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class HediffCompProperties_GestaltNode : HediffCompProperties
|
||||
{
|
||||
public GestaltNodeType nodeType = GestaltNodeType.HiveNode;
|
||||
|
||||
public HediffCompProperties_GestaltNode()
|
||||
{
|
||||
this.compClass = typeof(HediffComp_GestaltNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using ArachnaeSwarm;
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public enum GestaltNodeType
|
||||
{
|
||||
HiveNode,
|
||||
OverlordNode
|
||||
}
|
||||
|
||||
public class HediffComp_GestaltNode : HediffComp
|
||||
{
|
||||
private GestaltNodeType? cachedNodeType;
|
||||
private Pawn_GestaltTracker tracker;
|
||||
private bool wasConnected = false; // 缓存连接状态,避免每帧都调整严重性
|
||||
|
||||
public GestaltNodeType NodeType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!cachedNodeType.HasValue)
|
||||
{
|
||||
HediffCompProperties_GestaltNode props = this.props as HediffCompProperties_GestaltNode;
|
||||
cachedNodeType = props?.nodeType ?? GestaltNodeType.HiveNode;
|
||||
}
|
||||
return cachedNodeType.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public Pawn_GestaltTracker GestaltTracker
|
||||
{
|
||||
get
|
||||
{
|
||||
CompGestalt comp = Pawn.TryGetComp<CompGestalt>();
|
||||
if (comp != null)
|
||||
{
|
||||
return comp.GestaltTracker;
|
||||
}
|
||||
|
||||
if (tracker == null && NodeType == GestaltNodeType.OverlordNode)
|
||||
{
|
||||
tracker = new Pawn_GestaltTracker(Pawn);
|
||||
}
|
||||
return tracker;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompPostMake()
|
||||
{
|
||||
base.CompPostMake();
|
||||
// 初始化时根据连接状态设置严重性
|
||||
UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
|
||||
public override void CompPostTick(ref float severityAdjustment)
|
||||
{
|
||||
base.CompPostTick(ref severityAdjustment);
|
||||
|
||||
if (NodeType == GestaltNodeType.HiveNode)
|
||||
{
|
||||
// 定期更新严重性
|
||||
if (Find.TickManager.TicksGame % 60 == 0) // 每60tick检查一次
|
||||
{
|
||||
UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
|
||||
// 定期寻找 OverlordNode
|
||||
if (Pawn.IsColonist &&
|
||||
Pawn.Spawned &&
|
||||
!Pawn.Dead &&
|
||||
Find.TickManager.TicksGame % 250 == 0)
|
||||
{
|
||||
TryFindOverlord();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据连接状态更新 Hediff 严重性
|
||||
/// </summary>
|
||||
public void UpdateSeverityBasedOnConnection()
|
||||
{
|
||||
if (NodeType != GestaltNodeType.HiveNode || parent == null)
|
||||
return;
|
||||
|
||||
bool isConnected = IsConnectedToOverlord();
|
||||
|
||||
// 只有连接状态改变时才更新,避免每帧都设置
|
||||
if (isConnected != wasConnected)
|
||||
{
|
||||
float targetSeverity = isConnected ? 1.5f : 0.5f;
|
||||
|
||||
// 平滑过渡到目标严重性
|
||||
if (Mathf.Abs(parent.Severity - targetSeverity) > 0.01f)
|
||||
{
|
||||
parent.Severity = targetSeverity;
|
||||
}
|
||||
|
||||
wasConnected = isConnected;
|
||||
|
||||
// 如果严重性改变,需要重新计算Pawn的能力
|
||||
Pawn.health.Notify_HediffChanged(parent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否连接到 Overlord
|
||||
/// </summary>
|
||||
public bool IsConnectedToOverlord()
|
||||
{
|
||||
return Pawn.GetOverlord() != null;
|
||||
}
|
||||
|
||||
public void TryFindOverlord()
|
||||
{
|
||||
// 如果已经有Overlord,更新连接状态并返回
|
||||
if (IsConnectedToOverlord())
|
||||
{
|
||||
UpdateSeverityBasedOnConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
// 在殖民地寻找可用的OverlordNode
|
||||
Pawn bestOverlord = null;
|
||||
float bestScore = -1f;
|
||||
|
||||
foreach (Pawn pawn in Pawn.Map.mapPawns.FreeColonists)
|
||||
{
|
||||
HediffComp_GestaltNode nodeComp = pawn.GetGestaltNodeComp();
|
||||
if (nodeComp?.NodeType == GestaltNodeType.OverlordNode &&
|
||||
pawn != Pawn &&
|
||||
!pawn.Dead &&
|
||||
!pawn.Downed)
|
||||
{
|
||||
Pawn_GestaltTracker tracker = pawn.GestaltTracker();
|
||||
if (tracker != null && tracker.CanControlPawn(Pawn))
|
||||
{
|
||||
float score = CalculateOverlordScore(pawn, tracker);
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
bestOverlord = pawn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 找到合适的Overlord,建立关系并更新严重性
|
||||
if (bestOverlord != null)
|
||||
{
|
||||
Pawn.relations.AddDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, bestOverlord);
|
||||
UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateOverlordScore(Pawn overlord, Pawn_GestaltTracker tracker)
|
||||
{
|
||||
float score = 0f;
|
||||
|
||||
if (overlord.Spawned && Pawn.Spawned && overlord.Map == Pawn.Map)
|
||||
{
|
||||
float distance = overlord.Position.DistanceTo(Pawn.Position);
|
||||
score += 100f / (distance + 1f);
|
||||
}
|
||||
|
||||
float availableBandwidth = tracker.TotalBandwidth - tracker.UsedBandwidth;
|
||||
score += availableBandwidth * 10f;
|
||||
|
||||
score += (10 - tracker.ControlGroups.Count) * 5f;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
public override void CompPostPostRemoved()
|
||||
{
|
||||
base.CompPostPostRemoved();
|
||||
|
||||
// 当Hediff被移除时,如果连接到Overlord,需要断开连接
|
||||
if (NodeType == GestaltNodeType.HiveNode && IsConnectedToOverlord())
|
||||
{
|
||||
Pawn overlord = Pawn.GetOverlord();
|
||||
if (overlord != null)
|
||||
{
|
||||
Pawn.relations.RemoveDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, overlord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompExposeData()
|
||||
{
|
||||
base.CompExposeData();
|
||||
Scribe_Values.Look(ref wasConnected, "wasConnected", false);
|
||||
}
|
||||
}
|
||||
public static class HediffExtensions
|
||||
{
|
||||
public static HediffComp_GestaltNode GetGestaltNodeComp(this Pawn pawn)
|
||||
{
|
||||
if (pawn?.health?.hediffSet?.hediffs == null)
|
||||
return null;
|
||||
|
||||
foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
|
||||
{
|
||||
HediffComp_GestaltNode comp = hediff.TryGetComp<HediffComp_GestaltNode>();
|
||||
if (comp != null)
|
||||
return comp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsGestaltNode(this Pawn pawn, GestaltNodeType nodeType)
|
||||
{
|
||||
HediffComp_GestaltNode comp = pawn.GetGestaltNodeComp();
|
||||
return comp?.NodeType == nodeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class PawnRelationWorker_GestaltOverseer : PawnRelationWorker
|
||||
{
|
||||
public override void OnRelationCreated(Pawn firstPawn, Pawn secondPawn)
|
||||
{
|
||||
base.OnRelationCreated(firstPawn, secondPawn);
|
||||
|
||||
// 确定谁是Overlord,谁是HiveNode
|
||||
Pawn overlord = firstPawn.IsGestaltNode(GestaltNodeType.OverlordNode) ? firstPawn : secondPawn;
|
||||
Pawn hiveNode = (firstPawn == overlord) ? secondPawn : firstPawn;
|
||||
|
||||
if (overlord.IsGestaltNode(GestaltNodeType.OverlordNode) &&
|
||||
hiveNode.IsGestaltNode(GestaltNodeType.HiveNode))
|
||||
{
|
||||
Pawn_GestaltTracker tracker = overlord.GestaltTracker();
|
||||
if (tracker != null)
|
||||
{
|
||||
tracker.AssignPawnToControlGroup(hiveNode);
|
||||
}
|
||||
|
||||
// 更新HiveNode的严重性
|
||||
HediffComp_GestaltNode hiveNodeComp = hiveNode.GetGestaltNodeComp();
|
||||
if (hiveNodeComp != null)
|
||||
{
|
||||
hiveNodeComp.UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRelationRemoved(Pawn firstPawn, Pawn secondPawn)
|
||||
{
|
||||
base.OnRelationRemoved(firstPawn, secondPawn);
|
||||
|
||||
// 检查是否有Overlord节点
|
||||
Pawn overlord = null;
|
||||
if (firstPawn.IsGestaltNode(GestaltNodeType.OverlordNode))
|
||||
overlord = firstPawn;
|
||||
else if (secondPawn.IsGestaltNode(GestaltNodeType.OverlordNode))
|
||||
overlord = secondPawn;
|
||||
|
||||
Pawn hiveNode = (overlord == firstPawn) ? secondPawn : firstPawn;
|
||||
|
||||
if (overlord != null)
|
||||
{
|
||||
Pawn_GestaltTracker tracker = overlord.GestaltTracker();
|
||||
if (tracker != null)
|
||||
{
|
||||
tracker.UnassignPawnFromAnyControlGroup(hiveNode);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新HiveNode的严重性
|
||||
HediffComp_GestaltNode hiveNodeComp = hiveNode.GetGestaltNodeComp();
|
||||
if (hiveNodeComp != null)
|
||||
{
|
||||
hiveNodeComp.UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Notify_PostRemovedByDeath(Pawn firstPawn, Pawn secondPawn)
|
||||
{
|
||||
base.Notify_PostRemovedByDeath(firstPawn, secondPawn);
|
||||
|
||||
// 处理死亡事件
|
||||
Pawn overlord = (firstPawn.IsGestaltNode(GestaltNodeType.OverlordNode) ? firstPawn : secondPawn);
|
||||
Pawn hiveNode = (firstPawn == overlord) ? secondPawn : firstPawn;
|
||||
|
||||
if (!hiveNode.Dead && hiveNode.IsGestaltNode(GestaltNodeType.HiveNode))
|
||||
{
|
||||
// 断开连接并寻找新的Overlord
|
||||
if (overlord != null && !overlord.Dead)
|
||||
{
|
||||
HediffComp_GestaltNode hiveNodeComp = hiveNode.GetGestaltNodeComp();
|
||||
if (hiveNodeComp != null)
|
||||
{
|
||||
hiveNodeComp.UpdateSeverityBasedOnConnection();
|
||||
}
|
||||
|
||||
// HiveNode会自动尝试寻找新的Overlord
|
||||
hiveNodeComp?.TryFindOverlord();
|
||||
}
|
||||
}
|
||||
|
||||
if (overlord != null && !overlord.Dead)
|
||||
{
|
||||
Messages.Message("MessageGestaltLostControl".Translate(overlord, hiveNode) + ": " + hiveNode.LabelShortCap,
|
||||
new LookTargets(new Thing[] { overlord, hiveNode }), MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
using ArachnaeSwarm;
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm {
|
||||
public class Pawn_GestaltTracker : IExposable
|
||||
{
|
||||
private Pawn pawn;
|
||||
private List<GestaltControlGroup> controlGroups = new List<GestaltControlGroup>();
|
||||
private List<Pawn> controlledPawns = new List<Pawn>();
|
||||
|
||||
public Pawn Pawn => pawn;
|
||||
public List<GestaltControlGroup> ControlGroups => controlGroups;
|
||||
public List<Pawn> ControlledPawns => controlledPawns;
|
||||
|
||||
public int UsedBandwidth => (int)ControlledPawns.Sum(p => p.GetStatValue(StatDefOf.BandwidthCost));
|
||||
public int TotalBandwidth => (int)pawn.GetStatValue(StatDefOf.MechBandwidth);
|
||||
public int TotalAvailableControlGroups => (int)pawn.GetStatValue(StatDefOf.MechControlGroups);
|
||||
|
||||
public AcceptanceReport CanControlPawns
|
||||
{
|
||||
get
|
||||
{
|
||||
if (pawn.Downed)
|
||||
return "GestaltControllerDowned".Translate(pawn.Named("PAWN"));
|
||||
if (pawn.IsPrisoner)
|
||||
return "GestaltControllerImprisoned".Translate(pawn.Named("PAWN"));
|
||||
if (!pawn.Spawned)
|
||||
return false;
|
||||
if (pawn.InMentalState)
|
||||
return "GestaltControllerMentalState".Translate(pawn.Named("PAWN"), pawn.MentalStateDef.Named("MENTALSTATE"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Pawn_GestaltTracker() { }
|
||||
|
||||
public Pawn_GestaltTracker(Pawn pawn)
|
||||
{
|
||||
this.pawn = pawn;
|
||||
Notify_ControlGroupAmountChanged();
|
||||
}
|
||||
|
||||
public bool CanControlPawn(Pawn targetPawn)
|
||||
{
|
||||
if (targetPawn.GetOverlord() != null)
|
||||
return false;
|
||||
|
||||
float bandwidthCost = targetPawn.GetStatValue(StatDefOf.BandwidthCost);
|
||||
return UsedBandwidth + bandwidthCost <= TotalBandwidth;
|
||||
}
|
||||
|
||||
public GestaltControlGroup GetControlGroup(Pawn targetPawn)
|
||||
{
|
||||
foreach (GestaltControlGroup group in controlGroups)
|
||||
{
|
||||
if (group.AssignedPawns.Contains(targetPawn))
|
||||
return group;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void AssignPawnToControlGroup(Pawn targetPawn)
|
||||
{
|
||||
if (controlGroups.Count == 0)
|
||||
{
|
||||
Notify_ControlGroupAmountChanged();
|
||||
if (controlGroups.Count == 0)
|
||||
{
|
||||
Log.Warning("Wants to assign pawn to a control group, but there are none!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 分配到第一个可用的控制组
|
||||
controlGroups[0].Assign(targetPawn);
|
||||
Notify_BandwidthChanged();
|
||||
}
|
||||
|
||||
public void UnassignPawnFromAnyControlGroup(Pawn targetPawn)
|
||||
{
|
||||
foreach (GestaltControlGroup group in controlGroups)
|
||||
{
|
||||
group.TryUnassign(targetPawn);
|
||||
}
|
||||
}
|
||||
|
||||
public void Notify_ControlGroupAmountChanged()
|
||||
{
|
||||
int availableGroups = TotalAvailableControlGroups;
|
||||
|
||||
// 添加缺少的控制组
|
||||
while (controlGroups.Count < availableGroups)
|
||||
{
|
||||
controlGroups.Add(new GestaltControlGroup(this));
|
||||
}
|
||||
|
||||
// 移除多余的控制组
|
||||
while (controlGroups.Count > availableGroups)
|
||||
{
|
||||
GestaltControlGroup groupToRemove = controlGroups[controlGroups.Count - 1];
|
||||
|
||||
if (!groupToRemove.AssignedPawns.NullOrEmpty())
|
||||
{
|
||||
// 将pawn重新分配到其他组
|
||||
foreach (Pawn pawn in groupToRemove.AssignedPawns)
|
||||
{
|
||||
if (controlGroups.Count > 1)
|
||||
{
|
||||
controlGroups[0].Assign(pawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
controlGroups.RemoveAt(controlGroups.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void Notify_BandwidthChanged()
|
||||
{
|
||||
controlledPawns.Clear();
|
||||
|
||||
// 收集所有被控制的pawn
|
||||
foreach (GestaltControlGroup group in controlGroups)
|
||||
{
|
||||
controlledPawns.AddRange(group.AssignedPawns.Where(p => !controlledPawns.Contains(p)));
|
||||
}
|
||||
|
||||
// 检查带宽限制,移除超出带宽的pawn
|
||||
List<Pawn> toRemove = new List<Pawn>();
|
||||
float currentBandwidth = 0f;
|
||||
|
||||
foreach (Pawn controlledPawn in controlledPawns)
|
||||
{
|
||||
float cost = controlledPawn.GetStatValue(StatDefOf.BandwidthCost);
|
||||
if (currentBandwidth + cost <= TotalBandwidth)
|
||||
{
|
||||
currentBandwidth += cost;
|
||||
}
|
||||
else
|
||||
{
|
||||
toRemove.Add(controlledPawn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Pawn pawnToRemove in toRemove)
|
||||
{
|
||||
UnassignPawnFromAnyControlGroup(pawnToRemove);
|
||||
pawnToRemove.relations.RemoveDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, this.pawn);
|
||||
}
|
||||
}
|
||||
|
||||
public void Notify_ApparelChanged()
|
||||
{
|
||||
Notify_BandwidthChanged();
|
||||
Notify_ControlGroupAmountChanged();
|
||||
}
|
||||
|
||||
public void Notify_HediffStateChange(Hediff hediff)
|
||||
{
|
||||
if (hediff != null)
|
||||
{
|
||||
Notify_BandwidthChanged();
|
||||
Notify_ControlGroupAmountChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Gizmo> GetGizmos()
|
||||
{
|
||||
yield return new GestaltBandwidthGizmo(this);
|
||||
|
||||
foreach (GestaltControlGroup group in controlGroups)
|
||||
{
|
||||
yield return new GestaltControlGroupGizmo(group);
|
||||
}
|
||||
}
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_Collections.Look(ref controlGroups, "controlGroups", LookMode.Deep, this);
|
||||
Scribe_Collections.Look(ref controlledPawns, "controlledPawns", LookMode.Reference);
|
||||
|
||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
controlledPawns?.RemoveAll(x => x == null);
|
||||
if (controlGroups == null)
|
||||
controlGroups = new List<GestaltControlGroup>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user