This commit is contained in:
2026-02-25 12:00:37 +08:00
parent 5195d05045
commit 2fd290da9e
17 changed files with 1005 additions and 171 deletions

View File

@@ -0,0 +1,407 @@
// HediffCompProperties_SwitchableHediff.cs
using RimWorld;
using Verse;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
namespace WulaFallenEmpire
{
public class HediffCompProperties_SwitchableHediff : HediffCompProperties
{
// 可切换的hediff列表
public List<HediffDef> availableHediffs = new List<HediffDef>();
// 默认选择的hediff索引
public int defaultHediffIndex = 0;
// Gizmo图标路径
public string gizmoIconPath = "UI/Commands/Default";
// 是否显示当前状态的提示
public bool showStatusInGizmo = true;
// 可自定义的标签和描述
public string switchLabel = "WULA_SwitchableHediff_SwitchLabel"; // 默认翻译键
public string switchDesc = "WULA_SwitchableHediff_SwitchDesc"; // 默认翻译键
public string statusLabel = "WULA_SwitchableHediff_StatusLabel"; // 默认翻译键
public string statusDesc = "WULA_SwitchableHediff_StatusDesc"; // 默认翻译键
public HediffCompProperties_SwitchableHediff()
{
compClass = typeof(HediffComp_SwitchableHediff);
}
}
public class HediffComp_SwitchableHediff : HediffComp
{
public HediffCompProperties_SwitchableHediff Props => (HediffCompProperties_SwitchableHediff)props;
// 当前选择的hediff索引
private int currentHediffIndex = -1;
// 当前激活的hediff引用
private Hediff activeHediff;
// 用于保存和恢复的hediff ID
private int activeHediffId = -1;
public override void CompPostMake()
{
base.CompPostMake();
// 初始化当前选择
if (currentHediffIndex == -1 && Props.availableHediffs.Count > 0)
{
currentHediffIndex = Props.defaultHediffIndex;
if (currentHediffIndex >= Props.availableHediffs.Count)
currentHediffIndex = 0;
// 应用初始hediff
ApplySelectedHediff();
}
}
// 应用当前选择的hediff
private void ApplySelectedHediff()
{
// 移除之前激活的hediff
if (activeHediff != null && Pawn.health.hediffSet.hediffs.Contains(activeHediff))
{
Pawn.health.RemoveHediff(activeHediff);
}
activeHediff = null;
activeHediffId = -1;
// 应用新的hediff
if (currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[currentHediffIndex];
if (hediffDef != null)
{
activeHediff = HediffMaker.MakeHediff(hediffDef, Pawn);
activeHediff.Severity = 1f; // 默认严重性为1
Pawn.health.AddHediff(activeHediff);
// 记录hediff的ID用于保存/恢复
activeHediffId = GetHediffId(activeHediff);
}
}
}
// 获取hediff的唯一标识符
private int GetHediffId(Hediff hediff)
{
// 使用哈希码作为临时ID实际游戏中可能需要更稳定的标识方法
return hediff.GetHashCode();
}
// 尝试恢复已保存的hediff引用
private bool TryRestoreActiveHediff()
{
if (activeHediffId == -1) return false;
// 在pawn的所有hediff中查找匹配的
foreach (var hediff in Pawn.health.hediffSet.hediffs)
{
if (GetHediffId(hediff) == activeHediffId)
{
activeHediff = hediff;
return true;
}
}
// 如果找不到尝试根据currentHediffIndex查找对应的hediff
if (currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var expectedDef = Props.availableHediffs[currentHediffIndex];
foreach (var hediff in Pawn.health.hediffSet.hediffs)
{
if (hediff.def == expectedDef)
{
activeHediff = hediff;
activeHediffId = GetHediffId(hediff);
return true;
}
}
}
return false;
}
// 切换到特定索引的hediff
private void SwitchToHediff(int index)
{
if (index >= 0 && index < Props.availableHediffs.Count)
{
currentHediffIndex = index;
ApplySelectedHediff();
// 发送切换消息
var hediffDef = Props.availableHediffs[index];
if (hediffDef != null)
{
Messages.Message("WULA_SwitchableHediff_SwitchedTo".Translate(hediffDef.label),
Pawn, MessageTypeDefOf.SilentInput);
}
}
}
// 获取当前hediff名称
private string GetCurrentHediffName()
{
if (currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[currentHediffIndex];
return hediffDef?.label ?? "WULA_Unknown".Translate();
}
return "WULA_None".Translate();
}
// 获取当前hediff描述
private string GetCurrentHediffDesc()
{
if (currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[currentHediffIndex];
return hediffDef?.description ?? "WULA_NoDescription".Translate();
}
return string.Empty;
}
// 获取特定hediff的描述
private string GetHediffDescription(int index)
{
if (index >= 0 && index < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[index];
return hediffDef?.description ?? "WULA_NoDescription".Translate();
}
return string.Empty;
}
// 获取特定hediff的详细工具提示包含效果信息
private string GetHediffDetailedTooltip(int index)
{
if (index >= 0 && index < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[index];
if (hediffDef == null) return string.Empty;
StringBuilder sb = new StringBuilder();
// 添加描述
if (!hediffDef.description.NullOrEmpty())
{
sb.AppendLine(hediffDef.description);
}
return sb.ToString().TrimEndNewlines();
}
return string.Empty;
}
public override IEnumerable<Gizmo> CompGetGizmos()
{
// 只有玩家派系的pawn才显示Gizmo
if (Pawn.Faction == Faction.OfPlayer && Props.availableHediffs.Count > 1)
{
// 主切换按钮 - 显示当前状态
Command_Action mainButton = new Command_Action
{
// 使用可自定义的标签,如果没有自定义则使用翻译键
defaultLabel = Props.switchLabel.Translate(),
defaultDesc = "WULA_SwitchableHediff_CurrentMode".Translate(GetCurrentHediffName()) + "\n" +
Props.switchDesc.Translate(),
icon = ContentFinder<Texture2D>.Get(Props.gizmoIconPath, false) ?? BaseContent.BadTex,
action = () => {
// 显示选择菜单
ShowHediffSelectionMenu();
},
hotKey = KeyBindingDefOf.Misc2
};
yield return mainButton;
// 如果启用了状态显示添加一个信息Gizmo
if (Props.showStatusInGizmo)
{
Command_Action statusButton = new Command_Action
{
defaultLabel = Props.statusLabel.Translate(GetCurrentHediffName()),
defaultDesc = Props.statusDesc.Translate() + "\n\n" +
"WULA_SwitchableHediff_CurrentDesc".Translate(GetCurrentHediffDesc()),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Info", false) ?? BaseContent.BadTex,
action = () => {
// 显示当前hediff的详细信息
ShowCurrentHediffInfo();
}
};
yield return statusButton;
}
}
}
// 显示hediff选择菜单
private void ShowHediffSelectionMenu()
{
List<FloatMenuOption> options = new List<FloatMenuOption>();
for (int i = 0; i < Props.availableHediffs.Count; i++)
{
int index = i; // 捕获当前索引
var hediffDef = Props.availableHediffs[i];
string label = hediffDef?.label ?? "WULA_Unknown".Translate();
string description = GetHediffDetailedTooltip(i); // 获取详细工具提示
// 标记当前选择的项目
string prefix = (i == currentHediffIndex) ? "✓ " : " ";
// 创建选项
var option = new FloatMenuOption(
prefix + label,
() => {
SwitchToHediff(index);
}
);
// 设置工具提示 - 使用详细的描述信息
option.tooltip = description;
options.Add(option);
}
// 显示浮动菜单
if (options.Count > 0)
{
Find.WindowStack.Add(new FloatMenu(options, "WULA_SwitchableHediff_SelectMode".Translate()));
}
}
// 显示当前hediff的详细信息
private void ShowCurrentHediffInfo()
{
if (currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var hediffDef = Props.availableHediffs[currentHediffIndex];
string description = GetHediffDetailedTooltip(currentHediffIndex); // 使用详细工具提示
Messages.Message(
"WULA_SwitchableHediff_CurrentModeInfo".Translate(hediffDef?.label, description),
MessageTypeDefOf.SilentInput
);
}
}
public override string CompTipStringExtra
{
get
{
string baseTip = base.CompTipStringExtra ?? "";
string currentEffect = "WULA_SwitchableHediff_CurrentEffect".Translate(GetCurrentHediffName());
if (!string.IsNullOrEmpty(baseTip))
return baseTip + "\n" + currentEffect;
else
return currentEffect;
}
}
public override string CompLabelInBracketsExtra
{
get
{
return GetCurrentHediffName();
}
}
public override void CompExposeData()
{
base.CompExposeData();
Scribe_Values.Look(ref currentHediffIndex, "currentHediffIndex", -1);
Scribe_Values.Look(ref activeHediffId, "activeHediffId", -1);
// 加载后恢复状态
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
if (currentHediffIndex == -1 && Props.availableHediffs.Count > 0)
{
// 如果没有保存的索引,使用默认值
currentHediffIndex = Props.defaultHediffIndex;
if (currentHediffIndex >= Props.availableHediffs.Count)
currentHediffIndex = 0;
}
// 尝试恢复已保存的hediff引用
if (!TryRestoreActiveHediff())
{
ApplySelectedHediff();
}
// 验证状态一致性
ValidateStateConsistency();
}
}
// 验证状态一致性
private void ValidateStateConsistency()
{
bool hasConsistency = true;
// 检查currentHediffIndex是否有效
if (currentHediffIndex < 0 || currentHediffIndex >= Props.availableHediffs.Count)
{
hasConsistency = false;
}
// 检查activeHediff是否与currentHediffIndex一致
if (activeHediff != null && currentHediffIndex >= 0 && currentHediffIndex < Props.availableHediffs.Count)
{
var expectedDef = Props.availableHediffs[currentHediffIndex];
if (activeHediff.def != expectedDef)
{
hasConsistency = false;
}
}
if (!hasConsistency)
{
RepairState();
}
}
// 修复状态不一致
private void RepairState()
{
// 如果activeHediff存在但与currentHediffIndex不匹配尝试根据activeHediff找到正确的索引
if (activeHediff != null)
{
for (int i = 0; i < Props.availableHediffs.Count; i++)
{
if (Props.availableHediffs[i] == activeHediff.def)
{
currentHediffIndex = i;
return;
}
}
}
ApplySelectedHediff();
}
// 当父hediff被移除时也要移除激活的hediff
public override void CompPostPostRemoved()
{
base.CompPostPostRemoved();
if (activeHediff != null && Pawn.health.hediffSet.hediffs.Contains(activeHediff))
{
Pawn.health.RemoveHediff(activeHediff);
}
activeHediff = null;
activeHediffId = -1;
}
}
}