Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/Pawn/WULA_AutonomousMech/DroneGizmo.cs
ProjectKoi-Kalo\Kalo ea31c5f563 重构自主机械体系统:增强UI、AI和兼容性
1.  **核心架构重构**:
    *   将硬编码的 AutonomousWorkMode 枚举替换为基于 XML 定义的 DroneWorkModeDef,以提高扩展性。
    *   定义了基础工作模式:工作、充电、休眠、自动战斗。
    *   重构了 CompAutonomousMech 以支持新的 Def 系统。

2.  **UI 增强**:
    *   添加了 DroneGizmo:为选中的机械体提供控制面板,显示能量水平并允许切换模式。
    *   添加了 PawnColumnWorker_DroneWorkMode 和 PawnColumnWorker_DroneEnergy:在机械体列表中显示工作模式图标和能量条。
    *   通过 Harmony 补丁 Patch_MainTabWindow_Mechs_Pawns 将自主机械体集成到原版机械体主标签页中。
    *   扩展了 PawnTableDefOf.Mechs 以包含新的自定义列。

3.  **AI 与行为改进**:
    *   实现了 JobDriver_DroneSelfShutdown 和 JobGiver_DroneSelfShutdown:机械体现在会在低电量或被命令时寻找安全地点休眠。
    *   添加了 ThinkNode_ConditionalWorkMode_Drone 和 ThinkNode_ConditionalLowEnergy_Drone 用于行为树逻辑。

4.  **兼容性与修复**:
    *   添加了 Patch_MechanitorUtility_EverControllable:确保自主机械体始终可控,防止在没有监管者时失去控制。
    *   修复了机械体缺少监管者警报的误报问题。
2025-11-23 14:58:13 +08:00

115 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
namespace WulaFallenEmpire
{
[StaticConstructorOnStartup]
public class DroneGizmo : Gizmo
{
private CompAutonomousMech comp;
private HashSet<CompAutonomousMech> groupedComps;
private static readonly Texture2D BarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.34f, 0.42f, 0.43f));
private static readonly Texture2D BarHighlightTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.43f, 0.54f, 0.55f));
private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.03f, 0.035f, 0.05f));
// private static readonly Texture2D DragBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.74f, 0.97f, 0.8f));
// private static bool draggingBar;
public DroneGizmo(CompAutonomousMech comp)
{
this.comp = comp;
}
public override float GetWidth(float maxWidth)
{
return 160f;
}
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
Rect rect2 = rect.ContractedBy(10f);
Widgets.DrawWindowBackground(rect);
string text = "WULA_AutonomousMech".Translate();
Rect rect3 = new Rect(rect2.x, rect2.y, rect2.width, Text.CalcHeight(text, rect2.width) + 8f);
Text.Font = GameFont.Small;
Widgets.Label(rect3, text);
Rect rect4 = new Rect(rect2.x, rect3.yMax, rect2.width, rect2.height - rect3.height);
DraggableBarForGroup(rect4);
Text.Anchor = TextAnchor.MiddleCenter;
string energyText = comp.GetEnergyLevel().ToStringPercent();
Widgets.Label(rect4, energyText);
Text.Anchor = TextAnchor.UpperLeft;
TooltipHandler.TipRegion(rect4, () => "WULA_EnergyInfo".Translate(energyText), Gen.HashCombineInt(comp.GetHashCode(), 34242419));
// Work Mode Button
Rect rect6 = new Rect(rect2.x + rect2.width - 24f, rect2.y, 24f, 24f);
if (Widgets.ButtonImageFitted(rect6, comp.CurrentWorkMode?.uiIcon ?? BaseContent.BadTex))
{
Find.WindowStack.Add(new FloatMenu(GetWorkModeOptions(comp, groupedComps).ToList()));
}
TooltipHandler.TipRegion(rect6, "WULA_Switch_Mech_WorkMode".Translate());
Widgets.DrawHighlightIfMouseover(rect6);
return new GizmoResult(GizmoState.Clear);
}
private void DraggableBarForGroup(Rect rect)
{
// We are not actually dragging the energy level, but maybe a threshold?
// For now, just display the energy level.
// If we want to set recharge threshold, we need a property in CompAutonomousMech for that.
// Assuming we want to visualize energy level:
Widgets.FillableBar(rect, comp.GetEnergyLevel(), BarTex, EmptyBarTex, false);
}
public static IEnumerable<FloatMenuOption> GetWorkModeOptions(CompAutonomousMech comp, HashSet<CompAutonomousMech> groupedComps = null)
{
foreach (DroneWorkModeDef mode in DefDatabase<DroneWorkModeDef>.AllDefs.OrderBy(d => d.uiOrder))
{
yield return new FloatMenuOption(mode.LabelCap, delegate
{
comp.SetWorkMode(mode);
if (groupedComps != null)
{
foreach (CompAutonomousMech groupedComp in groupedComps)
{
groupedComp.SetWorkMode(mode);
}
}
}, mode.uiIcon, Color.white);
}
}
public override bool GroupsWith(Gizmo other)
{
return other is DroneGizmo;
}
public override void MergeWith(Gizmo other)
{
base.MergeWith(other);
if (other is DroneGizmo droneGizmo)
{
if (groupedComps == null)
{
groupedComps = new HashSet<CompAutonomousMech>();
}
groupedComps.Add(droneGizmo.comp);
if (droneGizmo.groupedComps != null)
{
groupedComps.AddRange(droneGizmo.groupedComps);
}
}
}
}
}