This commit is contained in:
2026-02-25 17:30:59 +08:00
parent 0509f26c3c
commit fff40b0edb
70 changed files with 3951 additions and 1219 deletions

View File

@@ -0,0 +1,213 @@
// File: FloatMenuOptionProvider_EnterMech.cs
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class FloatMenuOptionProvider_EnterMech : FloatMenuOptionProvider
{
// 检查Thing是否为机甲
private bool IsMech(Thing thing)
{
return thing is Wulamechunit || thing?.GetType()?.IsSubclassOf(typeof(Wulamechunit)) == true;
}
protected override bool Drafted => true; // 征召状态下不能进入机甲
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;
// 检查殖民者是否已经在机甲内
// 由于CompMechPilotHolder没有ContainsPilot方法我们需要通过其他方式检查
if (IsPawnInMech(context.FirstSelectedPawn, mech))
return false;
return true;
}
// 检查殖民者是否已经在机甲内替代ContainsPilot
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;
}
// 或者尝试通过其他属性检查
// 这里假设CompMechPilotHolder有HasPilots属性
if (comp.HasPilots)
{
// 如果有必要,可以通过反射或其他方式检查具体驾驶员
// 暂时返回false假设不在机甲内
return false;
}
return false;
}
// 获取单个选项
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 FloatMenuOption CreateEnterMechOption(Wulamechunit mech, Pawn pawn, CompMechPilotHolder comp)
{
string label = "WULA_EnterMech".Translate(mech.LabelShort);
string disabledReason = "";
// 检查条件是否允许进入
bool canEnter = CanEnterMech(mech, pawn, 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 CanEnterMech(Wulamechunit mech, Pawn pawn, 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 (!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;
}
return true;
}
}
}

View File

@@ -0,0 +1,76 @@
// File: JobDriver_EnterMech.cs (不再保留机甲)
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class JobDriver_EnterMech : JobDriver
{
private const TargetIndex MechIndex = TargetIndex.A;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
Pawn pawn = this.pawn;
LocalTargetInfo target = this.job.GetTarget(MechIndex);
// 不再保留机甲,这样多个殖民者可以同时被命令进入同一个机甲
// 只需要检查殖民者是否可以到达机甲
if (!pawn.CanReach(target, PathEndMode.Touch, Danger.Deadly))
{
return false;
}
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
// 0. 初始检查
AddFailCondition(() =>
{
var mech = TargetThingA as Wulamechunit;
if (mech == null || mech.Destroyed)
{
return true;
}
var comp = mech.GetComp<CompMechPilotHolder>();
if (comp == null || comp.IsFull || !comp.CanAddPilot(pawn))
{
return true;
}
if (pawn.Downed || pawn.Dead)
return true;
return false;
});
// 1. 走到机甲旁边
yield return Toils_Goto.GotoThing(MechIndex, PathEndMode.Touch);
// 2. 检查是否仍然可以进入
yield return Toils_General.Wait(10).WithProgressBarToilDelay(MechIndex);
// 3. 进入机甲
Toil enterToil = new Toil();
enterToil.initAction = () =>
{
var mech = TargetThingA as Wulamechunit;
if (mech == null)
return;
var comp = mech.GetComp<CompMechPilotHolder>();
if (comp != null && comp.CanAddPilot(pawn))
{
comp.AddPilot(pawn);
Messages.Message("WULA_PilotEnteredMech".Translate(pawn.LabelShort, mech.LabelShort),
MessageTypeDefOf.PositiveEvent, false);
}
};
enterToil.defaultCompleteMode = ToilCompleteMode.Instant;
yield return enterToil;
}
}
}

View File

@@ -0,0 +1,188 @@
// File: WorkGiver_EnterMech.cs
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class WorkGiver_EnterMech : WorkGiver_Scanner
{
// 缓存机甲定义列表
private static List<ThingDef> cachedMechDefs = null;
public override PathEndMode PathEndMode => PathEndMode.Touch;
// 获取所有机甲定义的列表
private List<ThingDef> GetAllMechDefs()
{
if (cachedMechDefs == null)
{
cachedMechDefs = new List<ThingDef>();
// 搜索所有ThingDef找出继承自Wulamechunit的类
foreach (var def in DefDatabase<ThingDef>.AllDefs)
{
try
{
if (def.thingClass == typeof(Wulamechunit) ||
def.thingClass?.IsSubclassOf(typeof(Wulamechunit)) == true)
{
cachedMechDefs.Add(def);
}
}
catch (Exception ex)
{
// 忽略错误,继续搜索
Log.Warning($"[WULA] Error checking ThingDef {def.defName}: {ex.Message}");
}
}
}
return cachedMechDefs;
}
// 检查Thing是否为机甲
private bool IsMech(Thing thing)
{
return thing is Wulamechunit || thing?.GetType()?.IsSubclassOf(typeof(Wulamechunit)) == true;
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
try
{
// 检查基本条件
if (t == null || pawn == null)
return false;
// 必须是Wulamechunit或其子类
if (!IsMech(t))
return false;
// 检查距离
if (!pawn.CanReach(t, PathEndMode, Danger.Deadly))
return false;
// 检查机甲是否有驾驶员槽位组件
var comp = t.TryGetComp<CompMechPilotHolder>();
if (comp == null)
return false;
// 检查是否已满
if (comp.IsFull)
return false;
// 检查殖民者是否可以成为驾驶员
if (!comp.CanAddPilot(pawn))
return false;
// 检查殖民者状态
if (pawn.Downed || pawn.Dead)
return false;
// 检查殖民者是否正在执行任务
if (pawn.CurJob != null && pawn.CurJob.def != JobDefOf.Wait)
return false;
// 检查是否被征召
if (pawn.Drafted)
return false;
// 检查是否为囚犯
if (pawn.IsPrisoner)
return false;
// 检查是否为奴隶
if (pawn.IsSlave)
return false;
return true;
}
catch (Exception ex)
{
Log.Error($"[WULA] Error in HasJobOnThing: {ex}");
return false;
}
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
try
{
if (IsMech(t))
{
// 创建进入机甲的工作
return JobMaker.MakeJob(Wula_JobDefOf.WULA_EnterMech, t);
}
}
catch (Exception ex)
{
Log.Error($"[WULA] Error creating job: {ex}");
}
return null;
}
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{
try
{
// 只搜索玩家拥有的机甲
List<Thing> potentialMechs = new List<Thing>();
// 获取地图中的所有机甲
if (pawn.Map != null)
{
// 使用缓存的机甲定义列表
var mechDefs = GetAllMechDefs();
foreach (var def in mechDefs)
{
try
{
var allMechs = pawn.Map.listerThings.ThingsOfDef(def);
foreach (var mech in allMechs)
{
if (mech.Faction == Faction.OfPlayer &&
mech.TryGetComp<CompMechPilotHolder>() != null)
{
potentialMechs.Add(mech);
}
}
}
catch (Exception ex)
{
Log.Warning($"[WULA] Error getting mechs for def {def.defName}: {ex.Message}");
}
}
}
return potentialMechs;
}
catch (Exception ex)
{
Log.Error($"[WULA] Error in PotentialWorkThingsGlobal: {ex}");
return Enumerable.Empty<Thing>();
}
}
public override bool ShouldSkip(Pawn pawn, bool forced = false)
{
try
{
// 简化版本:只检查殖民者状态
if (pawn.Downed || pawn.Dead || pawn.Drafted || pawn.IsPrisoner || pawn.IsSlave)
return true;
return false;
}
catch (Exception ex)
{
Log.Error($"[WULA] Error in ShouldSkip: {ex}");
return true;
}
}
}
}