可控机械族(未完成)

This commit is contained in:
2025-10-31 12:02:38 +08:00
parent 8fee1bcfba
commit 4c8821f3ae
7 changed files with 702 additions and 3 deletions

View File

@@ -0,0 +1,271 @@
using System.Collections.Generic;
using RimWorld;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
// 自定义条件节点:检查是否处于自主工作模式
public class ThinkNode_ConditionalAutonomousMech : ThinkNode_Conditional
{
protected override bool Satisfied(Pawn pawn)
{
if (pawn == null || pawn.Dead || pawn.Downed)
return false;
// 检查是否被征召
if (pawn.Drafted)
return false;
// 检查是否有机械师控制
if (pawn.GetOverseer() != null)
return false;
// 检查是否有自主能力
var comp = pawn.GetComp<CompAutonomousMech>();
if (comp == null || !comp.CanWorkAutonomously)
return false;
return true;
}
}
public class CompProperties_AutonomousMech : CompProperties
{
public bool enableAutonomousDrafting = true;
public bool enableAutonomousWork = true;
public bool requirePowerForAutonomy = true;
public bool suppressUncontrolledWarning = true;
public CompProperties_AutonomousMech()
{
compClass = typeof(CompAutonomousMech);
}
}
public class CompAutonomousMech : ThingComp
{
public CompProperties_AutonomousMech Props => (CompProperties_AutonomousMech)props;
public Pawn MechPawn => parent as Pawn;
public bool CanBeAutonomous
{
get
{
if (MechPawn == null || MechPawn.Dead || MechPawn.Downed)
return false;
if (!Props.enableAutonomousDrafting)
return false;
if (MechPawn.GetOverseer() != null)
return false;
if (Props.requirePowerForAutonomy)
{
var energyNeed = MechPawn.needs?.TryGetNeed<Need_MechEnergy>();
if (energyNeed != null && energyNeed.CurLevelPercentage < 0.1f)
return false;
}
return true;
}
}
public bool CanWorkAutonomously
{
get
{
if (!Props.enableAutonomousWork)
return false;
if (!CanBeAutonomous)
return false;
if (MechPawn.Drafted)
return false;
return true;
}
}
public bool ShouldSuppressUncontrolledWarning
{
get
{
if (!Props.suppressUncontrolledWarning)
return false;
return CanBeAutonomous;
}
}
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
if (MechPawn != null && MechPawn.IsColonyMech)
{
EnsureWorkSettings();
}
}
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
if (MechPawn == null || !CanBeAutonomous)
yield break;
// 自主征召按钮
yield return new Command_Toggle
{
defaultLabel = "Autonomous Mode",
defaultDesc = "Enable autonomous operation without mechanitor control",
icon = TexCommand.Draft,
isActive = () => MechPawn.Drafted,
toggleAction = () => ToggleAutonomousDraft(),
hotKey = KeyBindingDefOf.Misc1
};
// 工作模式切换按钮
if (CanWorkAutonomously)
{
yield return new Command_Action
{
defaultLabel = "Work Mode: " + GetCurrentWorkMode(),
defaultDesc = "Switch autonomous work mode",
icon = TexCommand.Attack,
action = () => ShowWorkModeMenu()
};
}
}
private void ToggleAutonomousDraft()
{
if (MechPawn.drafter == null)
return;
if (MechPawn.Drafted)
{
MechPawn.drafter.Drafted = false;
Messages.Message($"{MechPawn.LabelCap} autonomous mode deactivated",
MechPawn, MessageTypeDefOf.NeutralEvent);
}
else
{
if (CanBeAutonomous)
{
MechPawn.drafter.Drafted = true;
Messages.Message($"{MechPawn.LabelCap} is now operating autonomously",
MechPawn, MessageTypeDefOf.PositiveEvent);
}
else
{
Messages.Message($"Cannot activate autonomous mode: {GetBlockReason()}",
MechPawn, MessageTypeDefOf.NegativeEvent);
}
}
}
private string GetCurrentWorkMode()
{
if (MechPawn.workSettings == null)
return "None";
// 检查当前激活的工作模式
foreach (var workType in MechPawn.RaceProps.mechEnabledWorkTypes)
{
if (MechPawn.workSettings.GetPriority(workType) > 0)
{
return workType.defName;
}
}
return "None";
}
private void ShowWorkModeMenu()
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
// 工作模式
list.Add(new FloatMenuOption("Work Mode", () => SetWorkMode("Work")));
// 充电模式
list.Add(new FloatMenuOption("Recharge Mode", () => SetWorkMode("Recharge")));
// 休眠模式
list.Add(new FloatMenuOption("Shutdown Mode", () => SetWorkMode("SelfShutdown")));
Find.WindowStack.Add(new FloatMenu(list));
}
private void SetWorkMode(string mode)
{
if (MechPawn.workSettings == null)
return;
// 重置所有工作模式优先级
foreach (var workType in MechPawn.RaceProps.mechEnabledWorkTypes)
{
MechPawn.workSettings.SetPriority(workType, 0);
}
// 设置选择的工作模式
var targetMode = DefDatabase<WorkTypeDef>.GetNamedSilentFail(mode);
if (targetMode != null)
{
MechPawn.workSettings.SetPriority(targetMode, 3);
Messages.Message($"{MechPawn.LabelCap} switched to {mode} mode",
MechPawn, MessageTypeDefOf.NeutralEvent);
}
}
private string GetBlockReason()
{
if (MechPawn.Dead || MechPawn.Downed)
return "Mech is incapacitated";
if (MechPawn.GetOverseer() != null)
return "Mech is under mechanitor control";
if (Props.requirePowerForAutonomy)
{
var energyNeed = MechPawn.needs?.TryGetNeed<Need_MechEnergy>();
if (energyNeed != null && energyNeed.CurLevelPercentage < 0.1f)
return "Insufficient energy";
}
return "Autonomous mode disabled";
}
private void EnsureWorkSettings()
{
if (MechPawn.workSettings == null)
{
MechPawn.workSettings = new Pawn_WorkSettings(MechPawn);
}
if (MechPawn.RaceProps.mechEnabledWorkTypes != null)
{
// 默认设置为工作模式
var workMode = DefDatabase<WorkTypeDef>.GetNamedSilentFail("Work");
if (workMode != null)
{
MechPawn.workSettings.SetPriority(workMode, 3);
}
}
}
public string GetAutonomousStatusString()
{
if (!CanBeAutonomous)
return null;
if (MechPawn.Drafted)
return "Operating autonomously";
else
return "Autonomous mode available";
}
}
}

View File

@@ -0,0 +1,65 @@
using HarmonyLib;
using RimWorld;
using Verse;
namespace WulaFallenEmpire
{
[HarmonyPatch(typeof(Pawn_DraftController), "get_ShowDraftGizmo")]
public static class Patch_Pawn_DraftController_ShowDraftGizmo
{
public static void Postfix(Pawn_DraftController __instance, ref bool __result)
{
Pawn pawn = __instance.pawn;
if (!__result && pawn != null && pawn.IsColonyMech)
{
var comp = pawn.GetComp<CompAutonomousMech>();
if (comp != null && comp.CanBeAutonomous)
{
__result = true;
}
}
}
}
[HarmonyPatch(typeof(MechanitorUtility), "CanDraftMech")]
public static class Patch_MechanitorUtility_CanDraftMech
{
public static void Postfix(Pawn mech, ref AcceptanceReport __result)
{
if (!__result && mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.CanBeAutonomous)
{
__result = true;
}
}
}
}
[HarmonyPatch(typeof(CompOverseerSubject), "CompInspectStringExtra")]
public static class Patch_CompOverseerSubject_CompInspectStringExtra
{
public static void Postfix(CompOverseerSubject __instance, ref string __result)
{
Pawn mech = __instance.parent as Pawn;
if (mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
string autonomousStatus = comp.GetAutonomousStatusString();
if (!string.IsNullOrEmpty(autonomousStatus))
{
__result = autonomousStatus;
}
else
{
__result = "";
}
}
}
}
}
}

View File

@@ -0,0 +1,175 @@
using HarmonyLib;
using RimWorld;
using Verse;
using System.Reflection;
using UnityEngine;
namespace WulaFallenEmpire
{
// 修复红色名字问题 - 直接修补 PawnNameColorUtility.PawnNameColorOf 方法
[HarmonyPatch(typeof(PawnNameColorUtility), "PawnNameColorOf")]
public static class Patch_PawnNameColorUtility_PawnNameColorOf
{
public static void Postfix(Pawn pawn, ref Color __result)
{
if (pawn != null && pawn.IsColonyMech)
{
var comp = pawn.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 使用正常的白色名字
__result = Color.white;
}
}
}
}
// 修复红光闪烁问题 - 使用 Traverse 访问私有字段
[HarmonyPatch(typeof(Pawn_PlayerSettings), "get_UncontrolledMechDrawPulse")]
public static class Patch_Pawn_PlayerSettings_UncontrolledMechDrawPulse
{
public static bool Prefix(Pawn_PlayerSettings __instance, ref float __result)
{
var traverse = Traverse.Create(__instance);
Pawn pawn = traverse.Field("pawn").GetValue<Pawn>();
if (pawn != null && pawn.IsColonyMech)
{
var comp = pawn.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 返回 0 来禁用红光脉冲
__result = 0f;
return false; // 跳过原始方法
}
}
return true;
}
}
// 修复机械族控制状态检查
[HarmonyPatch(typeof(MechanitorUtility), "IsMechanitorControlled")]
public static class Patch_MechanitorUtility_IsMechanitorControlled
{
public static void Postfix(Pawn mech, ref bool __result)
{
if (!__result && mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 让游戏认为机械族是受控的
__result = true;
}
}
}
}
// 修复机械族控制状态检查的另一个方法
[HarmonyPatch(typeof(CompOverseerSubject), "get_IsControlled")]
public static class Patch_CompOverseerSubject_IsControlled
{
public static void Postfix(CompOverseerSubject __instance, ref bool __result)
{
Pawn mech = __instance.parent as Pawn;
if (!__result && mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 让游戏认为机械族是受控的
__result = true;
}
}
}
}
// 修复机械族控制状态显示的另一个检查
[HarmonyPatch(typeof(Pawn), "GetOverseer")]
public static class Patch_Pawn_GetOverseer
{
public static void Postfix(Pawn __instance, ref Pawn __result)
{
if (__result == null && __instance.IsColonyMech)
{
var comp = __instance.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 返回一个虚拟的监管者来避免红色显示
__result = __instance;
}
}
}
}
// 修复机械族控制组提示
[HarmonyPatch(typeof(CompOverseerSubject), "GetUndraftedControlGroupTip")]
public static class Patch_CompOverseerSubject_GetUndraftedControlGroupTip
{
public static bool Prefix(CompOverseerSubject __instance, ref string __result)
{
Pawn mech = __instance.parent as Pawn;
if (mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 提供自主状态的提示而不是未受控提示
__result = comp.GetAutonomousStatusString() ?? "Autonomous operation";
return false; // 跳过原始方法
}
}
return true;
}
}
// 修复机械族控制状态的其他检查
[HarmonyPatch(typeof(Pawn), "GetInspectString")]
public static class Patch_Pawn_GetInspectString
{
public static void Postfix(Pawn __instance, ref string __result)
{
if (__instance.IsColonyMech)
{
var comp = __instance.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 清理任何未受控相关的文本
if (__result.Contains("MechUncontrolled") || __result.Contains("uncontrolled"))
{
string autonomousStatus = comp.GetAutonomousStatusString();
if (!string.IsNullOrEmpty(autonomousStatus))
{
__result = autonomousStatus;
}
else
{
__result = __result.Replace("MechUncontrolled", "")
.Replace("uncontrolled", "autonomous");
}
}
}
}
}
}
// 修复机械族控制状态的UI显示
[HarmonyPatch(typeof(MechanitorUtility), "GetMechControlGroupDesc")]
public static class Patch_MechanitorUtility_GetMechControlGroupDesc
{
public static bool Prefix(Pawn mech, ref string __result)
{
if (mech != null && mech.IsColonyMech)
{
var comp = mech.GetComp<CompAutonomousMech>();
if (comp != null && comp.ShouldSuppressUncontrolledWarning)
{
// 提供自主状态描述
__result = comp.GetAutonomousStatusString() ?? "Autonomous operation";
return false; // 跳过原始方法
}
}
return true;
}
}
}

View File

@@ -104,6 +104,9 @@
<Compile Include="Pawn\WULA_AutoMechCarrier\CompAutoMechCarrier.cs" />
<Compile Include="Pawn\WULA_AutoMechCarrier\CompProperties_AutoMechCarrier.cs" />
<Compile Include="Pawn\WULA_AutoMechCarrier\PawnProductionEntry.cs" />
<Compile Include="Pawn\WULA_AutonomousMech\CompAutonomousMech.cs" />
<Compile Include="Pawn\WULA_AutonomousMech\Patch_MechanitorUtility_CanDraftMech.cs" />
<Compile Include="Pawn\WULA_AutonomousMech\Patch_UncontrolledMechDrawPulse.cs" />
<Compile Include="Pawn\WULA_BrokenPersonality\MentalBreakWorker_BrokenPersonality.cs" />
<Compile Include="Pawn\WULA_BrokenPersonality\MentalStateDefExtension_BrokenPersonality.cs" />
<Compile Include="Pawn\WULA_BrokenPersonality\MentalState_BrokenPersonality.cs" />