1
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user