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

@@ -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
}
}