This commit is contained in:
2026-02-03 16:49:49 +08:00
parent 61826f4c25
commit ec37348732
9 changed files with 926 additions and 13 deletions

View File

@@ -2,6 +2,10 @@
"Version": 1,
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawncapacityworker\\pawncapacityworker_psychicstange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawncapacityworker\\pawncapacityworker_psychicstange.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\\pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
@@ -42,7 +46,7 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 2,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Bookmark",
@@ -50,7 +54,20 @@
},
{
"$type": "Document",
"DocumentIndex": 4,
"DocumentIndex": 0,
"Title": "PawnCapacityWorker_PsychicStange.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs",
"RelativeDocumentMoniker": "PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs",
"RelativeToolTip": "PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-03T07:42:21.662Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 5,
"Title": "CompProperties_AbilityPsychicLoadCost.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs",
@@ -62,20 +79,20 @@
},
{
"$type": "Document",
"DocumentIndex": 0,
"DocumentIndex": 1,
"Title": "Gizmo_SwarmSpellStatus.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs",
"RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs",
"ViewState": "AgIAAGcAAAAAAAAAAAAMwHMAAABAAAAAAAAAAA==",
"ViewState": "AgIAAGcAAAAAAAAAAAAMwHwAAAAgAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-01-30T08:20:07.463Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"DocumentIndex": 3,
"Title": "CompAbilityEffect_PsychicLoadCost.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs",
@@ -87,7 +104,7 @@
},
{
"$type": "Document",
"DocumentIndex": 5,
"DocumentIndex": 6,
"Title": "CompAbilityEffect_PsychicBrainburn.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs",
"RelativeDocumentMoniker": "Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs",
@@ -99,7 +116,7 @@
},
{
"$type": "Document",
"DocumentIndex": 1,
"DocumentIndex": 2,
"Title": "ARA_DefOf.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs",
"RelativeDocumentMoniker": "ARA_DefOf.cs",
@@ -111,7 +128,7 @@
},
{
"$type": "Document",
"DocumentIndex": 3,
"DocumentIndex": 4,
"Title": "Comp_SwarmSpellHolder.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs",
@@ -123,7 +140,7 @@
},
{
"$type": "Document",
"DocumentIndex": 6,
"DocumentIndex": 7,
"Title": "SwarmSpellUtility.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs",
@@ -135,7 +152,7 @@
},
{
"$type": "Document",
"DocumentIndex": 7,
"DocumentIndex": 8,
"Title": "CompAutoMechCarrier.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",
"RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs",

View File

@@ -332,6 +332,7 @@
<Compile Include="MentalState\MentalState_HiveMindCascade.cs" />
<Compile Include="Needs\Need_ChitinArmor.cs" />
<Compile Include="Needs\Need_HoneyProduction.cs" />
<Compile Include="PawnCapacityWorker\PawnCapacityWorker_PsychicStange.cs" />
<Compile Include="Pawn_Comps\ARA_AutoMechCarrier\CompAutoMechCarrier.cs" />
<Compile Include="Pawn_Comps\ARA_AutoMechCarrier\CompProducedByMechCarrier.cs" />
<Compile Include="Pawn_Comps\ARA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />

View File

@@ -0,0 +1,354 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// 灵能稳定性Psychic Stange的能力计算器
/// 基于ARA_Psy_Source标签的部件效率和意识水平
/// </summary>
public class PawnCapacityWorker_PsychicStange : PawnCapacityWorker
{
#region
// 定义我们需要的BodyPartTagDef
private static BodyPartTagDef PsySourceTagDef = null;
// 用于缓存的Consciousness容量Def
private static PawnCapacityDef ConsciousnessDef = null;
#endregion
#region
/// <summary>
/// 确保标签Def已初始化
/// </summary>
private void EnsureTagDefsInitialized()
{
if (PsySourceTagDef == null)
{
// 尝试从DefDatabase获取标签定义
PsySourceTagDef = DefDatabase<BodyPartTagDef>.GetNamedSilentFail("ARA_Psy_Source");
if (PsySourceTagDef == null)
{
Log.Warning("[虫群术法] 未找到ARA_Psy_Source的BodyPartTagDef定义");
// 创建一个临时的标签定义以避免空引用
PsySourceTagDef = new BodyPartTagDef
{
defName = "ARA_Psy_Source",
label = "Psychic Source"
};
}
}
if (ConsciousnessDef == null)
{
ConsciousnessDef = DefDatabase<PawnCapacityDef>.GetNamedSilentFail("Consciousness");
if (ConsciousnessDef == null)
{
// 如果找不到Consciousness使用默认的
ConsciousnessDef = PawnCapacityDefOf.Consciousness;
}
}
}
#endregion
#region
/// <summary>
/// 计算灵能稳定性容量水平
/// </summary>
public override float CalculateCapacityLevel(HediffSet diffSet, List<PawnCapacityUtility.CapacityImpactor> impactors = null)
{
// 确保标签Def已初始化
EnsureTagDefsInitialized();
// 如果没有意识能力直接返回0
if (!diffSet.pawn.health.capacities.CapableOf(ConsciousnessDef))
{
// 如果有传入impactors记录影响因子
if (impactors != null)
{
impactors.Add(new PawnCapacityUtility.CapacityImpactorCapacity
{
capacity = ConsciousnessDef
});
}
return 0f;
}
// 获取意识水平
float consciousnessLevel = diffSet.pawn.health.capacities.GetLevel(ConsciousnessDef);
if (consciousnessLevel <= 0f)
{
if (impactors != null)
{
impactors.Add(new PawnCapacityUtility.CapacityImpactorCapacity
{
capacity = ConsciousnessDef
});
}
return 0f;
}
// 计算ARA_Psy_Source标签部件的平均效率
float psySourceEfficiency = CalculatePsySourceEfficiency(diffSet, impactors);
// 最终容量 = 灵能源效率 × 意识水平
float finalCapacity = psySourceEfficiency * consciousnessLevel;
// 如果有传入impactors记录最终影响
if (impactors != null && finalCapacity < 1f)
{
// 如果灵能源效率不是100%,记录它
if (psySourceEfficiency < 1f)
{
// 注意这里我们需要使用自定义的CapacityImpactor来记录灵能源的影响
// 由于PawnCapacityUtility.CalculateTagEfficiency不直接返回影响器列表
// 我们需要自己创建影响器
RecordPsySourceImpactors(diffSet, impactors);
}
// 如果意识水平不是100%,记录它
if (consciousnessLevel < 1f)
{
impactors.Add(new PawnCapacityUtility.CapacityImpactorCapacity
{
capacity = ConsciousnessDef
});
}
}
return finalCapacity;
}
/// <summary>
/// 计算灵能源标签部件的效率
/// </summary>
private float CalculatePsySourceEfficiency(HediffSet diffSet, List<PawnCapacityUtility.CapacityImpactor> impactors = null)
{
if (PsySourceTagDef == null)
return 0f;
// 使用PawnCapacityUtility.CalculateTagEfficiency计算标签部件的平均效率
// 这里我们使用默认的最大值和范围
float efficiency = PawnCapacityUtility.CalculateTagEfficiency(
diffSet,
PsySourceTagDef,
maximum: float.MaxValue,
lerp: default(FloatRange),
impactors: impactors
);
return efficiency;
}
/// <summary>
/// 记录灵能源部件的影响器
/// </summary>
private void RecordPsySourceImpactors(HediffSet diffSet, List<PawnCapacityUtility.CapacityImpactor> impactors)
{
if (diffSet == null || diffSet.pawn == null || diffSet.pawn.RaceProps?.body == null)
return;
// 获取所有带有ARA_Psy_Source标签的部件
var partsWithTag = diffSet.pawn.RaceProps.body.GetPartsWithTag(PsySourceTagDef);
foreach (var part in partsWithTag)
{
// 检查部件是否缺失或受损
if (diffSet.PartIsMissing(part))
{
// 部件缺失
impactors.Add(new PawnCapacityUtility.CapacityImpactorBodyPartHealth
{
bodyPart = part
});
}
else
{
// 检查部件的健康百分比
float partHealth = diffSet.GetPartHealth(part);
float partMaxHealth = part.def.GetMaxHealth(diffSet.pawn);
float healthPercent = partHealth / partMaxHealth;
if (healthPercent < 1f)
{
// 部件受损
impactors.Add(new PawnCapacityUtility.CapacityImpactorBodyPartHealth
{
bodyPart = part
});
}
}
}
}
#endregion
#region
/// <summary>
/// 检查身体定义是否可以拥有此容量
/// 只有当身体拥有ARA_Psy_Source标签的部件时才显示
/// </summary>
public override bool CanHaveCapacity(BodyDef body)
{
// 确保标签Def已初始化
EnsureTagDefsInitialized();
if (PsySourceTagDef == null || body == null)
return false;
// 检查身体是否拥有带有ARA_Psy_Source标签的部件
return body.HasPartWithTag(PsySourceTagDef);
}
#endregion
#region
/// <summary>
/// 获取详细的能力影响描述
/// </summary>
public string GetDetailedCapacityInfo(HediffSet diffSet)
{
EnsureTagDefsInitialized();
if (!CanHaveCapacity(diffSet.pawn.RaceProps.body))
{
return "此单位没有灵能源部件,无法拥有灵能稳定性能力。";
}
float consciousnessLevel = diffSet.pawn.health.capacities.GetLevel(ConsciousnessDef);
float psySourceEfficiency = CalculatePsySourceEfficiency(diffSet, null);
float finalCapacity = psySourceEfficiency * consciousnessLevel;
var partsWithTag = diffSet.pawn.RaceProps.body.GetPartsWithTag(PsySourceTagDef);
int totalParts = 0;
int functionalParts = 0;
int missingParts = 0;
int damagedParts = 0;
foreach (var part in partsWithTag)
{
totalParts++;
if (diffSet.PartIsMissing(part))
{
missingParts++;
}
else
{
float partHealth = diffSet.GetPartHealth(part);
float partMaxHealth = part.def.GetMaxHealth(diffSet.pawn);
if (partHealth < partMaxHealth)
{
damagedParts++;
}
else
{
functionalParts++;
}
}
}
string result = $"灵能稳定性: {finalCapacity:P0}\n";
result += $" 意识水平: {consciousnessLevel:P0}\n";
result += $" 灵能源效率: {psySourceEfficiency:P0}\n";
result += $" 灵能源部件: {totalParts}个 (正常: {functionalParts}, 受损: {damagedParts}, 缺失: {missingParts})";
return result;
}
/// <summary>
/// 检查是否所有灵能源部件都完整
/// </summary>
public bool AreAllPsySourcesIntact(HediffSet diffSet)
{
EnsureTagDefsInitialized();
if (PsySourceTagDef == null || diffSet.pawn.RaceProps?.body == null)
return false;
var partsWithTag = diffSet.pawn.RaceProps.body.GetPartsWithTag(PsySourceTagDef);
foreach (var part in partsWithTag)
{
if (diffSet.PartIsMissing(part))
return false;
float partHealth = diffSet.GetPartHealth(part);
float partMaxHealth = part.def.GetMaxHealth(diffSet.pawn);
if (partHealth < partMaxHealth)
return false;
}
return true;
}
/// <summary>
/// 获取灵能源部件的总健康百分比
/// </summary>
public float GetTotalPsySourceHealthPercent(HediffSet diffSet)
{
EnsureTagDefsInitialized();
if (PsySourceTagDef == null || diffSet.pawn.RaceProps?.body == null)
return 0f;
var partsWithTag = diffSet.pawn.RaceProps.body.GetPartsWithTag(PsySourceTagDef);
if (partsWithTag.Count == 0)
return 0f;
float totalHealth = 0f;
float totalMaxHealth = 0f;
foreach (var part in partsWithTag)
{
float partMaxHealth = part.def.GetMaxHealth(diffSet.pawn);
totalMaxHealth += partMaxHealth;
if (!diffSet.PartIsMissing(part))
{
float partHealth = diffSet.GetPartHealth(part);
totalHealth += partHealth;
}
}
if (totalMaxHealth <= 0f)
return 0f;
return totalHealth / totalMaxHealth;
}
/// <summary>
/// 获取功能正常的灵能源部件数量
/// </summary>
public int GetFunctionalPsySourceCount(HediffSet diffSet)
{
EnsureTagDefsInitialized();
if (PsySourceTagDef == null || diffSet.pawn.RaceProps?.body == null)
return 0;
var partsWithTag = diffSet.pawn.RaceProps.body.GetPartsWithTag(PsySourceTagDef);
int functionalCount = 0;
foreach (var part in partsWithTag)
{
if (!diffSet.PartIsMissing(part))
{
float partHealth = diffSet.GetPartHealth(part);
float partMaxHealth = part.def.GetMaxHealth(diffSet.pawn);
if (partHealth >= partMaxHealth)
{
functionalCount++;
}
}
}
return functionalCount;
}
#endregion
}
}