1
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
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;
|
||||
|
||||
// 保留能量管理设置供 ThinkNode 使用
|
||||
public float lowEnergyThreshold = 0.3f; // 低能量阈值
|
||||
public float criticalEnergyThreshold = 0.1f; // 临界能量阈值
|
||||
public float rechargeCompleteThreshold = 0.9f; // 充电完成阈值
|
||||
|
||||
public MechWorkModeDef initialWorkMode;
|
||||
|
||||
public CompProperties_AutonomousMech()
|
||||
{
|
||||
compClass = typeof(CompAutonomousMech);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompAutonomousMech : ThingComp
|
||||
{
|
||||
public CompProperties_AutonomousMech Props => (CompProperties_AutonomousMech)props;
|
||||
|
||||
public Pawn MechPawn => parent as Pawn;
|
||||
|
||||
private MechWorkModeDef currentWorkMode;
|
||||
|
||||
public bool CanBeAutonomous
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MechPawn == null || MechPawn.Dead )
|
||||
return false;
|
||||
|
||||
if (!Props.enableAutonomousDrafting)
|
||||
return false;
|
||||
|
||||
if (MechPawn.GetOverseer() != null)
|
||||
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 bool IsInCombatMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MechPawn == null || MechPawn.Dead || MechPawn.Downed)
|
||||
return false;
|
||||
// 被征召或处于自主战斗模式
|
||||
return MechPawn.Drafted || (CanFightAutonomously && MechPawn.mindState?.duty?.def == DutyDefOf.AssaultColony);
|
||||
}
|
||||
}
|
||||
|
||||
// 在 CompAutonomousMech 类中添加这个新属性
|
||||
public bool CanFightAutonomously
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MechPawn == null || MechPawn.Dead || MechPawn.Downed)
|
||||
return false;
|
||||
|
||||
if (!Props.enableAutonomousDrafting)
|
||||
return false;
|
||||
|
||||
if (MechPawn.GetOverseer() != null)
|
||||
return false;
|
||||
|
||||
if (!MechPawn.drafter?.Drafted == true)
|
||||
return false;
|
||||
|
||||
if (Props.requirePowerForAutonomy)
|
||||
{
|
||||
if (GetEnergyLevel() < Props.criticalEnergyThreshold)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public MechWorkModeDef CurrentWorkMode => currentWorkMode;
|
||||
|
||||
// 新增:能量状态检查方法
|
||||
public float GetEnergyLevel()
|
||||
{
|
||||
var energyNeed = MechPawn.needs?.TryGetNeed<Need_MechEnergy>();
|
||||
return energyNeed?.CurLevelPercentage ?? 0f;
|
||||
}
|
||||
|
||||
public bool IsLowEnergy => GetEnergyLevel() < Props.lowEnergyThreshold;
|
||||
public bool IsCriticalEnergy => GetEnergyLevel() < Props.criticalEnergyThreshold;
|
||||
public bool IsFullyCharged => GetEnergyLevel() >= Props.rechargeCompleteThreshold;
|
||||
|
||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
||||
{
|
||||
base.PostSpawnSetup(respawningAfterLoad);
|
||||
|
||||
if (currentWorkMode == null)
|
||||
{
|
||||
currentWorkMode = Props.initialWorkMode ?? MechWorkModeDefOf.Work;
|
||||
}
|
||||
|
||||
// 确保使用独立战斗系统
|
||||
InitializeAutonomousCombat();
|
||||
}
|
||||
|
||||
private void InitializeAutonomousCombat()
|
||||
{
|
||||
// 确保有 draftController
|
||||
if (MechPawn.drafter == null)
|
||||
{
|
||||
MechPawn.drafter = new Pawn_DraftController(MechPawn);
|
||||
}
|
||||
|
||||
// 强制启用 FireAtWill
|
||||
if (MechPawn.drafter != null)
|
||||
{
|
||||
MechPawn.drafter.FireAtWill = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
|
||||
// 每60 tick检查一次能量状态
|
||||
if (MechPawn != null && MechPawn.IsColonyMech && Find.TickManager.TicksGame % 60 == 0)
|
||||
{
|
||||
// 删除了自动切换模式的 CheckEnergyStatus 调用
|
||||
EnsureWorkSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// 删除了整个 CheckEnergyStatus 方法,因为充电逻辑在 ThinkNode 中处理
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
if (MechPawn == null || !CanBeAutonomous)
|
||||
yield break;
|
||||
|
||||
// 工作模式切换按钮
|
||||
if (CanWorkAutonomously)
|
||||
{
|
||||
DroneGizmo droneGizmo = new DroneGizmo(this);
|
||||
if (droneGizmo != null)
|
||||
{
|
||||
yield return droneGizmo;
|
||||
}
|
||||
}
|
||||
// 更换武器按钮 - 确保不返回null
|
||||
Gizmo weaponSwitchGizmo = CreateWeaponSwitchGizmo();
|
||||
if (weaponSwitchGizmo != null)
|
||||
{
|
||||
yield return weaponSwitchGizmo;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建更换武器的Gizmo
|
||||
/// </summary>
|
||||
private Gizmo CreateWeaponSwitchGizmo()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查Pawn是否属于玩家派系
|
||||
if (MechPawn?.Faction != Faction.OfPlayer)
|
||||
{
|
||||
return null; // 非玩家派系时不显示
|
||||
}
|
||||
// 检查Pawn是否有效
|
||||
if (MechPawn == null || MechPawn.Dead || MechPawn.Destroyed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// 检查equipment是否有效
|
||||
if (MechPawn.equipment == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Command_Action switchWeaponCommand = new Command_Action
|
||||
{
|
||||
defaultLabel = "WULA_SwitchWeapon".Translate(),
|
||||
defaultDesc = "WULA_SwitchWeapon_Desc".Translate(),
|
||||
icon = ContentFinder<Texture2D>.Get("Wula/UI/Abilities/WULA_WeaponSwitchAbility", false) ?? BaseContent.BadTex,
|
||||
action = SwitchWeapon,
|
||||
};
|
||||
// 确保Command不为null
|
||||
if (switchWeaponCommand == null)
|
||||
{
|
||||
WulaLog.Debug($"Failed to create weapon switch gizmo for {MechPawn?.LabelCap}");
|
||||
return null;
|
||||
}
|
||||
return switchWeaponCommand;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
WulaLog.Debug($"Error creating weapon switch gizmo: {ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更换武器逻辑
|
||||
/// </summary>
|
||||
private void SwitchWeapon()
|
||||
{
|
||||
if (MechPawn == null || MechPawn.Destroyed || !MechPawn.Spawned)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 扔掉当前武器
|
||||
ThingWithComps currentWeapon = MechPawn.equipment?.Primary;
|
||||
if (currentWeapon != null)
|
||||
{
|
||||
// 将武器扔在地上
|
||||
MechPawn.equipment.TryDropEquipment(currentWeapon, out ThingWithComps droppedWeapon, MechPawn.Position, true);
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
WulaLog.Debug($"[CompAutonomousMech] {MechPawn.LabelCap} dropped weapon: {currentWeapon.LabelCap}");
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 从PawnKind允许的武器中生成新武器
|
||||
ThingDef newWeaponDef = GetRandomWeaponFromPawnKind();
|
||||
if (newWeaponDef != null)
|
||||
{
|
||||
// 生成新武器
|
||||
Thing newWeapon = ThingMaker.MakeThing(newWeaponDef);
|
||||
if (newWeapon is ThingWithComps newWeaponWithComps)
|
||||
{
|
||||
// 使用 AddEquipment 方法装备新武器
|
||||
MechPawn.equipment.AddEquipment(newWeaponWithComps);
|
||||
|
||||
Messages.Message("WULA_WeaponSwitched".Translate(MechPawn.LabelCap, newWeaponDef.LabelCap),
|
||||
MechPawn, MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
WulaLog.Debug($"[CompAutonomousMech] {MechPawn.LabelCap} equipped new weapon: {newWeaponDef.LabelCap}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("WULA_NoWeaponAvailable".Translate(MechPawn.LabelCap),
|
||||
MechPawn, MessageTypeDefOf.NegativeEvent);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
WulaLog.Debug($"[CompAutonomousMech] Error switching weapon for {MechPawn?.LabelCap}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从PawnKind允许的武器中随机获取一个武器定义
|
||||
/// </summary>
|
||||
private ThingDef GetRandomWeaponFromPawnKind()
|
||||
{
|
||||
if (MechPawn.kindDef?.weaponTags == null || MechPawn.kindDef.weaponTags.Count == 0)
|
||||
return null;
|
||||
|
||||
// 收集所有匹配的武器
|
||||
List<ThingDef> availableWeapons = new List<ThingDef>();
|
||||
|
||||
foreach (string weaponTag in MechPawn.kindDef.weaponTags)
|
||||
{
|
||||
foreach (ThingDef thingDef in DefDatabase<ThingDef>.AllDefs)
|
||||
{
|
||||
if (thingDef.IsWeapon && thingDef.weaponTags != null && thingDef.weaponTags.Contains(weaponTag))
|
||||
{
|
||||
availableWeapons.Add(thingDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (availableWeapons.Count == 0)
|
||||
return null;
|
||||
|
||||
// 随机选择一个武器
|
||||
return availableWeapons.RandomElement();
|
||||
}
|
||||
|
||||
public void SetWorkMode(MechWorkModeDef mode)
|
||||
{
|
||||
currentWorkMode = mode;
|
||||
|
||||
// 清除当前工作,让机械族重新选择符合新模式的工作
|
||||
if (MechPawn.CurJob != null && MechPawn.CurJob.def != JobDefOf.Wait_Combat)
|
||||
{
|
||||
MechPawn.jobs.StopAll();
|
||||
}
|
||||
|
||||
Messages.Message("WULA_SwitchedToMode".Translate(MechPawn.LabelCap, mode.label),
|
||||
MechPawn, MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
|
||||
private void EnsureWorkSettings()
|
||||
{
|
||||
if (MechPawn.workSettings == null)
|
||||
{
|
||||
MechPawn.workSettings = new Pawn_WorkSettings(MechPawn);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetAutonomousStatusString()
|
||||
{
|
||||
if (!CanBeAutonomous)
|
||||
return null;
|
||||
|
||||
string energyInfo = "WULA_EnergyInfoShort".Translate(GetEnergyLevel().ToStringPercent());
|
||||
|
||||
if (MechPawn.Drafted)
|
||||
return "WULA_Autonomous_Drafted".Translate() + energyInfo;
|
||||
else
|
||||
return "WULA_Autonomous_Mode".Translate(currentWorkMode?.label ?? "Unknown") + energyInfo;
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Defs.Look(ref currentWorkMode, "currentWorkMode");
|
||||
// 删除了 wasLowEnergy 的序列化
|
||||
}
|
||||
}
|
||||
}
|
||||
115
Source/WulaFallenEmpire/Pawn_Comps/AutonomousMech/DroneGizmo.cs
Normal file
115
Source/WulaFallenEmpire/Pawn_Comps/AutonomousMech/DroneGizmo.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
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 (MechWorkModeDef mode in DefDatabase<MechWorkModeDef>.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class JobGiver_DroneSelfShutdown : ThinkNode_JobGiver
|
||||
{
|
||||
protected override Job TryGiveJob(Pawn pawn)
|
||||
{
|
||||
if (!RCellFinder.TryFindNearbyMechSelfShutdownSpot(pawn.Position, pawn, pawn.Map, out var result, allowForbidden: true))
|
||||
{
|
||||
result = pawn.Position;
|
||||
}
|
||||
Job job = JobMaker.MakeJob(JobDefOf.SelfShutdown, result);
|
||||
job.forceSleep = true;
|
||||
return job;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public class PawnColumnWorker_DroneEnergy : PawnColumnWorker
|
||||
{
|
||||
private const int Width = 120;
|
||||
|
||||
private const int BarPadding = 4;
|
||||
|
||||
public static readonly Texture2D EnergyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color32(252, byte.MaxValue, byte.MaxValue, 65));
|
||||
|
||||
public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
|
||||
{
|
||||
CompAutonomousMech comp = pawn.TryGetComp<CompAutonomousMech>();
|
||||
if (comp == null || !comp.CanBeAutonomous)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widgets.FillableBar(rect.ContractedBy(4f), comp.GetEnergyLevel(), EnergyBarTex, BaseContent.ClearTex, doBorder: false);
|
||||
Text.Font = GameFont.Small;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(rect, comp.GetEnergyLevel().ToStringPercent());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
Text.Font = GameFont.Small;
|
||||
}
|
||||
|
||||
public override int GetMinWidth(PawnTable table)
|
||||
{
|
||||
return Mathf.Max(base.GetMinWidth(table), 120);
|
||||
}
|
||||
|
||||
public override int GetMaxWidth(PawnTable table)
|
||||
{
|
||||
return Mathf.Min(base.GetMaxWidth(table), GetMinWidth(table));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class PawnColumnWorker_DroneWorkMode : PawnColumnWorker_Icon
|
||||
{
|
||||
protected override int Padding => 0;
|
||||
|
||||
public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
|
||||
{
|
||||
CompAutonomousMech comp = pawn.TryGetComp<CompAutonomousMech>();
|
||||
if (comp == null || !comp.CanBeAutonomous)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Widgets.ButtonInvisible(rect))
|
||||
{
|
||||
Find.WindowStack.Add(new FloatMenu(DroneGizmo.GetWorkModeOptions(comp).ToList()));
|
||||
}
|
||||
base.DoCell(rect, pawn, table);
|
||||
}
|
||||
|
||||
protected override Texture2D GetIconFor(Pawn pawn)
|
||||
{
|
||||
return pawn?.TryGetComp<CompAutonomousMech>()?.CurrentWorkMode?.uiIcon;
|
||||
}
|
||||
|
||||
protected override string GetIconTip(Pawn pawn)
|
||||
{
|
||||
string text = pawn.TryGetComp<CompAutonomousMech>()?.CurrentWorkMode?.description;
|
||||
if (!text.NullOrEmpty())
|
||||
{
|
||||
return text;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ThinkNode_ConditionalAutonomousWorkMode : ThinkNode_Conditional
|
||||
{
|
||||
public MechWorkModeDef requiredMode;
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
|
||||
// 检查是否有自主机械组件
|
||||
var comp = pawn.GetComp<CompAutonomousMech>();
|
||||
if (comp == null)
|
||||
return false;
|
||||
|
||||
// 检查当前工作模式是否匹配要求
|
||||
if (comp.CurrentWorkMode != requiredMode)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
WulaLog.Debug($"[WULA] Exception in ThinkNode_ConditionalAutonomousWorkMode.Satisfied for pawn {pawn?.LabelShort}: {ex}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ThinkNode_ConditionalLowEnergy_Drone : ThinkNode_Conditional
|
||||
{
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
CompAutonomousMech compDrone = pawn.TryGetComp<CompAutonomousMech>();
|
||||
if (compDrone != null && compDrone.IsLowEnergy)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
// 检查机械族是否需要充电
|
||||
public class ThinkNode_ConditionalNeedRecharge : ThinkNode_Conditional
|
||||
{
|
||||
public float energyThreshold = 0.3f;
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
|
||||
var energyNeed = pawn.needs?.TryGetNeed<Need_MechEnergy>();
|
||||
if (energyNeed == null)
|
||||
return false;
|
||||
|
||||
return energyNeed.CurLevelPercentage < energyThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查机械族是否紧急需要充电
|
||||
public class ThinkNode_ConditionalEmergencyRecharge : ThinkNode_Conditional
|
||||
{
|
||||
public float emergencyThreshold = 0.1f;
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
|
||||
var energyNeed = pawn.needs?.TryGetNeed<Need_MechEnergy>();
|
||||
if (energyNeed == null)
|
||||
return false;
|
||||
|
||||
return energyNeed.CurLevelPercentage < emergencyThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查机械族是否充满电
|
||||
public class ThinkNode_ConditionalFullyCharged : ThinkNode_Conditional
|
||||
{
|
||||
public float fullChargeThreshold = 0.9f;
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
|
||||
var energyNeed = pawn.needs?.TryGetNeed<Need_MechEnergy>();
|
||||
if (energyNeed == null)
|
||||
return false;
|
||||
|
||||
return energyNeed.CurLevelPercentage >= fullChargeThreshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ThinkNode_ConditionalWorkMode_Drone : ThinkNode_Conditional
|
||||
{
|
||||
public MechWorkModeDef workMode;
|
||||
|
||||
public override ThinkNode DeepCopy(bool resolve = true)
|
||||
{
|
||||
ThinkNode_ConditionalWorkMode_Drone thinkNode_ConditionalWorkMode_Drone = (ThinkNode_ConditionalWorkMode_Drone)base.DeepCopy(resolve);
|
||||
thinkNode_ConditionalWorkMode_Drone.workMode = workMode;
|
||||
return thinkNode_ConditionalWorkMode_Drone;
|
||||
}
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
if (!pawn.RaceProps.IsMechanoid || pawn.Faction != Faction.OfPlayer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CompAutonomousMech compDrone = pawn.TryGetComp<CompAutonomousMech>();
|
||||
if (compDrone == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return compDrone.CurrentWorkMode == workMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user