Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/Work/EnterMech/FloatMenuOptionProvider_EnterMech.cs
2026-02-28 11:50:54 +08:00

313 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<Pawn> tmpPawns = new List<Pawn>();
// 检查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<CompMechPilotHolder>();
if (comp == null)
return false;
return true;
}
// 重写:获取选项
public override IEnumerable<FloatMenuOption> 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<CompMechPilotHolder>();
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<CompMechPilotHolder>();
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<CompMechPilotHolder>();
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);
}
}
}