diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 9a7dfdee..8497704a 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml index 8fe4973c..72811c46 100644 --- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml +++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml @@ -1,6 +1,10 @@  - + + + Human + + A baseline human, mostly unmodified by gene engineering and mostly unchanged by evolutionary pressures on non-Earth planets. 1750 4.6 @@ -221,10 +225,16 @@ - + + + + 0 + + + WulaSpecies - 乌拉星人是一个曾统治银河系的堕落帝国的主要种族,机械乌拉则是仿照她们样貌制作的合成人——随着帝国的衰颓,大量乌拉合成人流散各地。她们拥有近乎无限的寿命,并且拥有一部分机械体的特性。 + 诞生于乌拉帝国的机械生命体 Wula/Things/WulaSpecies/WULA_Species_Icon @@ -1355,6 +1365,7 @@ 0 + WULA_AutonomousMech
  • Hauling
  • @@ -1385,6 +1396,11 @@
    +
  • + true + true + true +
  • +
  • + Despawned +
  • + + +
  • + +
  • + +
  • + + +
  • + Downed +
  • + + +
  • + +
  • + +
  • + + +
  • + BerserkMechanoid + +
  • + +
  • +
  • + Deadly +
  • + + + + + + +
  • + + +
  • + +
  • + DraftedOrder + +
  • +
  • + +
  • + + + + +
  • + LordDuty +
  • + + +
  • + +
  • + + + +
  • + +
  • + +
  • + + +
  • + Work + +
  • +
  • + + +
  • + true +
  • + + +
  • + + +
  • + true + +
  • + 65 + 72 +
  • +
  • + MiscWork + +
  • + Deadly + Patrolling. +
  • + + + + + + + + +
  • + Recharge + +
  • +
  • +
  • + true +
  • + + + + +
  • + SelfShutdown + +
  • +
  • + +
  • + + + + + + + +
  • + true + +
  • + 30 + 35 +
  • + + + + +
  • + Idle + +
  • + None +
  • + + + + +
  • + + + + diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs new file mode 100644 index 00000000..d9877359 --- /dev/null +++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/CompAutonomousMech.cs @@ -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(); + 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(); + 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 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 list = new List(); + + // 工作模式 + 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.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(); + 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.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"; + } + } +} diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_MechanitorUtility_CanDraftMech.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_MechanitorUtility_CanDraftMech.cs new file mode 100644 index 00000000..40733c7b --- /dev/null +++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_MechanitorUtility_CanDraftMech.cs @@ -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(); + 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(); + 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(); + if (comp != null && comp.ShouldSuppressUncontrolledWarning) + { + string autonomousStatus = comp.GetAutonomousStatusString(); + if (!string.IsNullOrEmpty(autonomousStatus)) + { + __result = autonomousStatus; + } + else + { + __result = ""; + } + } + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_UncontrolledMechDrawPulse.cs b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_UncontrolledMechDrawPulse.cs new file mode 100644 index 00000000..46af4323 --- /dev/null +++ b/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/Patch_UncontrolledMechDrawPulse.cs @@ -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(); + 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(); + + if (pawn != null && pawn.IsColonyMech) + { + var comp = pawn.GetComp(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + if (comp != null && comp.ShouldSuppressUncontrolledWarning) + { + // 提供自主状态描述 + __result = comp.GetAutonomousStatusString() ?? "Autonomous operation"; + return false; // 跳过原始方法 + } + } + return true; + } + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 6d528685..63c63e40 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -104,6 +104,9 @@ + + +