using RimWorld; using System; using System.Collections.Generic; using System.Linq; using Verse; using Verse.AI; namespace WulaFallenEmpire { public class FloatMenuOptionProvider_EnterMech : FloatMenuOptionProvider { private static readonly List tmpPawns = new List(); // 检查Thing是否为机甲 private bool IsMech(Thing thing) { return thing is Wulamechunit || thing?.GetType()?.IsSubclassOf(typeof(Wulamechunit)) == true; } protected override bool Drafted => false; // 征召状态下不能进入机甲 protected override bool Undrafted => true; // 非征召状态下可以进入 protected override bool Multiselect => true; // 支持多选 // 检查是否适用于当前上下文 protected override bool AppliesInt(FloatMenuContext context) { // 必须有选中的殖民者 if (context.FirstSelectedPawn == null) return false; // 检查点击的单元格中是否有机甲 var clickedThings = context.ClickedThings; if (clickedThings == null || clickedThings.Count == 0) return false; // 查找第一个机甲 Thing mech = null; foreach (var thing in clickedThings) { if (IsMech(thing)) { mech = thing; break; } } if (mech == null) return false; // 检查机甲是否有驾驶员组件 var comp = mech.TryGetComp(); if (comp == null) return false; return true; } // 重写:获取选项 public override IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context) { if (!AppliesInt(context)) yield break; if (context.IsMultiselect) { var option = GetMultiselectEnterMechOption(clickedThing, context); if (option != null) yield return option; yield break; } var singleOption = GetSingleOptionFor(clickedThing, context); if (singleOption != null) yield return singleOption; } // 获取多选选项 private FloatMenuOption GetMultiselectEnterMechOption(Thing clickedThing, FloatMenuContext context) { tmpPawns.Clear(); var mech = clickedThing as Wulamechunit; var comp = mech?.TryGetComp(); if (mech == null || comp == null) return null; // 收集所有可以进入机甲的Pawn foreach (var pawn in context.ValidSelectedPawns) { if (CanPawnEnterMech(pawn, mech, comp)) { tmpPawns.Add(pawn); } } if (tmpPawns.Count == 0) return null; // 检查是否有机甲已满的情况 string failStr = null; if (comp.IsFull) { failStr = "WULA_MechFull".Translate(); } if (!failStr.NullOrEmpty()) { return new FloatMenuOption( "WULA_EnterMech".Translate(mech.LabelShort) + ": " + failStr, null, MenuOptionPriority.DisabledOption ); } // 计算可以进入的数量 int canEnterCount = 0; foreach (var pawn in tmpPawns) { if (comp.HasRoom) { canEnterCount++; } else { break; } } string label = "WULA_EnterMech".Translate(mech.LabelShort); return new FloatMenuOption(label, () => { FleckMaker.Static(mech.DrawPos, mech.MapHeld, FleckDefOf.FeedbackEquip); // 为每个可以进入的Pawn创建Job foreach (var pawn in tmpPawns) { if (comp.HasRoom && CanPawnEnterMech(pawn, mech, comp)) { Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_EnterMech, mech); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); } } }, MenuOptionPriority.High); } // 获取单个选项 protected override FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context) { if (clickedThing == null || context.FirstSelectedPawn == null) return null; // 如果不是机甲,返回null if (!IsMech(clickedThing)) return null; // 获取机甲和组件 var mech = clickedThing as Wulamechunit; var comp = mech?.TryGetComp(); if (mech == null || comp == null) return null; // 检查殖民者是否已经在机甲内 if (IsPawnInMech(context.FirstSelectedPawn, mech)) return null; // 检查各种条件,生成相应的菜单选项 return CreateEnterMechOption(mech, context.FirstSelectedPawn, comp); } // 检查殖民者是否已经在机甲内 private bool IsPawnInMech(Pawn pawn, Thing mech) { var comp = mech.TryGetComp(); if (comp == null) return false; // 尝试通过内部容器检查 var holder = comp as IThingHolder; if (holder != null) { var things = holder.GetDirectlyHeldThings(); if (things != null && things.Contains(pawn)) return true; } return false; } // 创建进入机甲的菜单选项 private FloatMenuOption CreateEnterMechOption(Wulamechunit mech, Pawn pawn, CompMechPilotHolder comp) { string label = "WULA_EnterMech".Translate(mech.LabelShort); string disabledReason = ""; // 检查条件是否允许进入 bool canEnter = CanPawnEnterMech(pawn, mech, comp, ref disabledReason); // 如果条件允许,创建可点击的选项 if (canEnter) { return new FloatMenuOption(label, () => { // 创建进入机甲的工作 Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_EnterMech, mech); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); // 播放音效 FleckMaker.Static(mech.DrawPos, mech.MapHeld, FleckDefOf.FeedbackEquip); }, MenuOptionPriority.High); } else { // 创建禁用的选项,显示原因 return new FloatMenuOption( "WULA_EnterMech".Translate(mech.LabelShort) + ": " + disabledReason, null, MenuOptionPriority.DisabledOption); } } // 检查殖民者是否可以进入机甲(带原因) private bool CanPawnEnterMech(Pawn pawn, Wulamechunit mech, CompMechPilotHolder comp, ref string disabledReason) { // 检查机甲是否已满 if (comp.IsFull) { disabledReason = "WULA_MechFull".Translate(); return false; } // 检查殖民者是否可以成为驾驶员 if (!comp.CanAddPilot(pawn)) { disabledReason = "WULA_CannotBecomePilot".Translate(); return false; } // 检查殖民者是否已经在机甲内 if (IsPawnInMech(pawn, mech)) { disabledReason = "AlreadyInMech".Translate(); return false; } // 检查距离 if (!pawn.CanReach(mech, PathEndMode.Touch, Danger.Deadly)) { disabledReason = "NoPath".Translate(); return false; } // 检查殖民者状态 if (pawn.Downed) { disabledReason = "Downed".Translate(); return false; } if (pawn.Dead) { disabledReason = "Dead".Translate(); return false; } // 检查是否为囚犯 if (pawn.IsPrisoner) { disabledReason = "Prisoner".Translate(); return false; } // 检查是否为奴隶 if (pawn.IsSlave) { disabledReason = "Slave".Translate(); return false; } // 检查机甲状态 if (mech.Downed) { disabledReason = "Downed".Translate(); return false; } if (mech.Dead) { disabledReason = "Dead".Translate(); return false; } // 检查是否被征召(驾驶员不能是征召状态) if (pawn.Drafted) { disabledReason = "Drafted".Translate(); return false; } return true; } // 检查殖民者是否可以进入机甲(简化版) private bool CanPawnEnterMech(Pawn pawn, Wulamechunit mech, CompMechPilotHolder comp) { string disabledReason = ""; return CanPawnEnterMech(pawn, mech, comp, ref disabledReason); } } }