diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index 321b2a61..54cb00aa 100644
Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ
diff --git a/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml b/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml
index ea7a7900..ed0d9e4c 100644
--- a/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml
+++ b/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml
@@ -85,14 +85,22 @@
WULA_EnterMech
WulaFallenEmpire.JobDriver_EnterMech
- Entering mech.
+ 驾驶构装体。
+
+ false
+
+
+
+ WULA_BoardMech
+ WulaFallenEmpire.JobDriver_BoardMech
+ 作为乘员登上构装体。
false
WULA_RefuelMech
WulaFallenEmpire.JobDriver_RefuelMech
- Refuleing TargetA.
+ 为 TargetA 加注燃料。
false
@@ -113,7 +121,7 @@
WULA_RepairMech
WulaFallenEmpire.JobDriver_RepairMech
- Repairing TargetA.
+ 维修 TargetA。
false
false
@@ -127,12 +135,12 @@
Repair
Repair Mech
-
+
WULA_ForceEjectPilot
WulaFallenEmpire.JobDriver_ForceEjectPilot
- Prise TargetA.
+ 撬开 TargetA。
false
@@ -140,7 +148,7 @@
WULA_CarryToMech
WulaFallenEmpire.JobDriver_CarryToMech
- carrying TargetA to TargetB.
+ 携带 TargetA 到 TargetB。
false
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Shuttle_Building.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Shuttle_Building.xml
index eb92e0d2..de9c901f 100644
--- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Shuttle_Building.xml
+++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Shuttle_Building.xml
@@ -182,8 +182,9 @@
WULA_ArmedShuttleWithPocket
- 乌拉帝国用于在舰队和地表构建联系的特种穿梭机,拥有巨大的货仓和一个内部折叠的生活区,因此载重量惊人且可以在内部活动。它同时还拥有一面高反射概率的反射盾和MLt-1"棱晶"涡轮激光炮 ,可以抵挡大部分袭击。
- WulaFallenEmpire.Building_ArmedShuttleWithPocket
+ 乌拉帝国用于在舰队和地表构建联系的特种穿梭机,拥有载重量惊人的货仓。它同时还拥有一面高反射概率的反射盾和MLt-1"棱晶"涡轮激光炮 ,可以抵挡大部分袭击。
+
+ Building_TurretGun
true
Building
50
@@ -214,7 +215,7 @@
500
150
25
- 4
+ 2
true
true
@@ -235,8 +236,6 @@
ShuttleEngine
ShuttleEngine
- ShuttleEngine
- ShuttleEngine
1000
@@ -269,7 +268,7 @@
{0} is ready to launch again.
- 5000
+ 5000000
true
true
Shuttle_PawnLoaded
@@ -298,7 +297,7 @@
ShuttleIdle_Ambience
- 15
+ 10
30
2400
30
@@ -318,55 +317,25 @@
true
- 0.75
+ 0.5
30
0
Interceptor_BlockedProjectile
-
- 15
- 30
- Flame
- 1
- false
- false
- false
- true
- false
- false
- false
- 热辐射
- CVe-3"渡鸦"可以启动防御设施,蒸发胆敢进入反射立场内的敌军——这同时会使得它伤害附近所有的散落物品。
- Wula/UI/Commands/Wula_Psi_Titan_AreaDamage
-
CompPowerPlant
-2000
true
-
-
-
-
- 2000
- true
- true
- false
- Shuttle_PawnLoaded
- Shuttle_PawnExit
-
-
- ShuttleIdle_Ambience
-
-
+
PlaceWorker_NotUnderRoof
PlaceWorker_TurretTop
@@ -428,7 +397,6 @@
-
WULA_PocketMapExit
@@ -458,80 +426,6 @@
-
- WULA_Shuttle_Autocannon
-
- 由乌拉帝国的穿梭机所装备的自动炮,能够组织起高射速的弹幕压制杀伤大规模目标。
- Ultra
- 0
-
- Wula/Weapon/WULA_Weapon_Empty
- Graphic_Single
- 2
-
- 0.5
- None
-
- 40000
- 150
- 0.5
- 0.5
- 0.4
- 0.35
- 1.5
-
-
-
-
- 500
- 150
- 8
-
-
-
- Verb_Shoot
- true
- Bullet_WULA_Shuttle_Autocannon
- 0.25
- 24
- 10
- 0.35
- 6
- Shot_TurretSniper
- GunTail_Heavy
- 12
-
- true
- true
- true
-
-
-
-
-
- Bullet_WULA_Shuttle_Autocannon
-
- Projectile_Explosive
- Normal
- True
-
- Wula/Projectile/WULA_Bullet_ChargeLanceShot_Red_Double
- Graphic_Single
-
- (0.75,1)
-
-
- WULA_Shuttle_Autocannon_Bullet
- 14
- 120
- 2.4
- 0.4
- Explosion_Rocket
- 0.75
- 0.1
-
-
-
ArmedShuttleIncoming_WULA
diff --git a/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml b/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml
index 81918af3..66c3da25 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml
@@ -147,14 +147,6 @@
-
- 36000
- 8.2
- 8.4
- 0.02
- 4.0
- false
-
@@ -336,7 +328,7 @@
Wula_AI_Rocket_Panzer
- 乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,拥有车体臼炮和两具可以发射大量燃烧火箭弹的转轮导弹巢,但是未像其姊妹型号那样装备护盾。
+ 乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,拥有车体臼炮和两具可以发射大量燃烧火箭弹的转轮导弹巢。
2
2
diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml
index a87ce8c4..d91e3bd6 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml
@@ -208,12 +208,25 @@
{0} 已经从 {1} 离开
征召驾驶员···
指定一名驾驶员进入构装体
+ 紧急登机
+ 立刻召集上次驾驶过该构装体的驾驶员驾驶此构装体。
离开构装体
让该构装体的驾驶员离开构装体
没有可以作为构装体驾驶员的殖民者
此装备不能由此构装体使用
此装备不是为构装体设计的
此装备是专为构装体设计的,非构装体单位无法装备
+
+ 快速装载
+ 命令附近的殖民者和机械族作为乘员登上构装体,乘员不会参与构装体的驾驶。
+ 释放乘员
+ 命令所有乘员快速离开构装体。
+ {0} 登上了 {1}
+ {0} 离开了 {1}
+ 已命令 {0} 个单位登上 {1}
+ 无法成为乘员
+ 构装体乘员位已满
+ 登上构装体 {0}
构装体重新启动
没有可以执行操作的殖民者
@@ -274,4 +287,9 @@
使地堡发出号召,让地图上所有的乌拉猫猫自动进入征召状态并聚集到该地堡附近。
集合能力冷却中
地堡被停用,无法进行集结征召
+
+ 飞行姿态
+ 手动控制此单位是否保持飞行姿态。
+ 已启用飞行姿态
+ 停用飞行姿态
diff --git a/Content/Textures/Wula/UI/Commands/WFE_FlightToggle.png b/Content/Textures/Wula/UI/Commands/WFE_FlightToggle.png
deleted file mode 100644
index 411f2f52..00000000
Binary files a/Content/Textures/Wula/UI/Commands/WFE_FlightToggle.png and /dev/null differ
diff --git a/Content/Textures/Wula/UI/Commands/WULA_FlightToggle.png b/Content/Textures/Wula/UI/Commands/WULA_FlightToggle.png
new file mode 100644
index 00000000..76415100
Binary files /dev/null and b/Content/Textures/Wula/UI/Commands/WULA_FlightToggle.png differ
diff --git a/Source/WulaFallenEmpire/Pawn/Mechunit.cs b/Source/WulaFallenEmpire/Pawn/Mechunit.cs
index 68aae6c4..ba85be4d 100644
--- a/Source/WulaFallenEmpire/Pawn/Mechunit.cs
+++ b/Source/WulaFallenEmpire/Pawn/Mechunit.cs
@@ -1,7 +1,7 @@
-// File: Wulamechunit_Fixed.cs
using RimWorld;
using System.Collections.Generic;
using Verse;
+using Verse.AI;
using Verse.AI.Group;
namespace WulaFallenEmpire
@@ -32,6 +32,16 @@ namespace WulaFallenEmpire
}
}
+ // 添加乘员相关的Gizmo
+ var crewComp = this.TryGetComp();
+ if (crewComp != null)
+ {
+ foreach (var gizmo in crewComp.CompGetGizmosExtra())
+ {
+ yield return gizmo;
+ }
+ }
+
// 原有的征兆Gizmo
if (drafter == null)
{
@@ -121,34 +131,66 @@ namespace WulaFallenEmpire
// 关键修复:重写死亡相关方法
public override void Kill(DamageInfo? dinfo = null, Hediff exactCulprit = null)
{
- // 在死亡前弹出所有驾驶员
+ // 在死亡前弹出所有驾驶员和乘员
var pilotComp = this.TryGetComp();
if (pilotComp != null && pilotComp.HasPilots)
{
pilotComp.EjectAllPilotsOnDeath();
}
+ var crewComp = this.TryGetComp();
+ if (crewComp != null && crewComp.HasCrew)
+ {
+ crewComp.RemoveAllCrew();
+ }
+
base.Kill(dinfo, exactCulprit);
}
// 重写销毁方法
public override void Destroy(DestroyMode mode = DestroyMode.Vanish)
{
- // 在销毁前弹出所有驾驶员
+ // 在销毁前弹出所有驾驶员和乘员
var pilotComp = this.TryGetComp();
if (pilotComp != null && pilotComp.HasPilots)
{
pilotComp.EjectAllPilotsOnDeath();
}
+ var crewComp = this.TryGetComp();
+ if (crewComp != null && crewComp.HasCrew)
+ {
+ crewComp.RemoveAllCrew();
+ }
+
base.Destroy(mode);
}
// IThingHolder 接口实现
public new ThingOwner GetDirectlyHeldThings()
{
+ // 合并驾驶员和乘员容器
var pilotComp = this.TryGetComp();
- return pilotComp?.GetDirectlyHeldThings();
+ var crewComp = this.TryGetComp();
+
+ if (pilotComp != null && crewComp != null)
+ {
+ // 合并两个容器
+ var combined = new ThingOwner(this);
+ combined.TryAddRangeOrTransfer(pilotComp.innerContainer);
+ combined.TryAddRangeOrTransfer(crewComp.innerContainer);
+ return combined;
+ }
+ else if (pilotComp != null)
+ {
+ return pilotComp.innerContainer;
+ }
+ else if (crewComp != null)
+ {
+ return crewComp.innerContainer;
+ }
+
+ return null;
}
public new void GetChildHolders(List outChildren)
@@ -159,8 +201,6 @@ namespace WulaFallenEmpire
public override void ExposeData()
{
base.ExposeData();
-
- // 驾驶员容器的数据会在CompMechPilotHolder中自动保存
}
}
}
diff --git a/Source/WulaFallenEmpire/Pawn_Comps/MechCrewHolder/CompProperties_MechCrewHolder.cs b/Source/WulaFallenEmpire/Pawn_Comps/MechCrewHolder/CompProperties_MechCrewHolder.cs
new file mode 100644
index 00000000..e4b26a40
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn_Comps/MechCrewHolder/CompProperties_MechCrewHolder.cs
@@ -0,0 +1,472 @@
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ // 机甲乘员组件属性
+ public class CompProperties_MechCrewHolder : CompProperties
+ {
+ public int maxCrew = 3; // 最大乘员数
+ public float boardingRadius = 10f; // 登机半径
+ public float maxPawnSize = 1.0f; // 最大装载体型大小
+ public bool allowMechanoids = true; // 是否允许搭载机械族
+ public bool draftOnExit = true; // 下车时是否进入征召状态
+
+ // 外观配置
+ public string boardCrewIcon = "Wula/UI/Commands/WULA_BoardCrew";
+ public string exitCrewIcon = "Wula/UI/Commands/WULA_ExitCrew";
+
+ // 工作配置
+ public bool requireWorkTag = false; // 是否需要工作标签
+ public string workTag = "CrewMember"; // 工作标签(如果需要)
+
+ public CompProperties_MechCrewHolder()
+ {
+ compClass = typeof(CompMechCrewHolder);
+ }
+
+ // 获取图标
+ public Texture2D GetBoardCrewIcon()
+ {
+ if (!string.IsNullOrEmpty(boardCrewIcon) &&
+ ContentFinder.Get(boardCrewIcon, false) != null)
+ {
+ return ContentFinder.Get(boardCrewIcon);
+ }
+ return ContentFinder.Get("UI/Commands/BoardCrew", false) ?? BaseContent.BadTex;
+ }
+
+ public Texture2D GetExitCrewIcon()
+ {
+ if (!string.IsNullOrEmpty(exitCrewIcon) &&
+ ContentFinder.Get(exitCrewIcon, false) != null)
+ {
+ return ContentFinder.Get(exitCrewIcon);
+ }
+ return ContentFinder.Get("UI/Commands/ExitCrew", false) ?? BaseContent.BadTex;
+ }
+ }
+
+ // 机甲乘员组件实现
+ public class CompMechCrewHolder : ThingComp, IThingHolder
+ {
+ public ThingOwner innerContainer;
+
+ private Command_Action cachedBoardGizmo;
+ private Command_Action cachedExitGizmo;
+ private bool gizmosInitialized = false;
+
+ // 属性
+ public CompProperties_MechCrewHolder Props => (CompProperties_MechCrewHolder)props;
+
+ public int CurrentCrewCount => innerContainer.Count;
+ public bool HasCrew => innerContainer.Count > 0;
+ public bool HasRoom => innerContainer.Count < Props.maxCrew;
+ public bool IsFull => innerContainer.Count >= Props.maxCrew;
+
+ // 初始化
+ public CompMechCrewHolder()
+ {
+ innerContainer = new ThingOwner(this);
+ }
+
+ public override void Initialize(CompProperties props)
+ {
+ base.Initialize(props);
+
+ if (innerContainer == null)
+ {
+ innerContainer = new ThingOwner(this);
+ }
+ }
+
+ // 检查是否可以添加乘员
+ public bool CanAddCrew(Pawn pawn)
+ {
+ if (pawn == null || pawn.Dead)
+ return false;
+
+ if (!HasRoom)
+ return false;
+
+ if (innerContainer.Contains(pawn))
+ return false;
+
+ // 检查体型大小
+ if (pawn.BodySize > Props.maxPawnSize)
+ return false;
+
+ // 检查是否允许机械族
+ if (pawn.RaceProps.IsMechanoid && !Props.allowMechanoids)
+ return false;
+
+ // 检查工作标签(如果需要)
+ if (Props.requireWorkTag)
+ {
+ WorkTags tag;
+ if (Enum.TryParse(Props.workTag, out tag))
+ {
+ if (pawn.WorkTagIsDisabled(tag))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // 添加乘员
+ public void AddCrew(Pawn pawn)
+ {
+ if (!CanAddCrew(pawn))
+ return;
+
+ try
+ {
+ // 停止Pawn当前工作
+ pawn.jobs?.StopAll();
+ pawn.pather?.StopDead();
+
+ // 从地图移除并添加到容器
+ if (pawn.Spawned)
+ pawn.DeSpawn();
+
+ innerContainer.TryAdd(pawn, true);
+
+ // 触发事件
+ Notify_CrewAdded(pawn);
+
+ // 记录日志
+ if (Prefs.DevMode)
+ {
+ Log.Message($"[CompMechCrewHolder] {pawn.LabelShort} boarded {parent.LabelShort}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Error adding crew {pawn.LabelShort} to {parent.LabelShort}: {ex.Message}");
+ }
+ }
+
+ // 移除乘员
+ public void RemoveCrew(Pawn pawn, IntVec3? exitPos = null)
+ {
+ if (!innerContainer.Contains(pawn))
+ return;
+
+ try
+ {
+ // 从容器移除
+ innerContainer.Remove(pawn);
+
+ // 生成到地图
+ TrySpawnCrewAtPosition(pawn, exitPos ?? parent.Position);
+
+ // 如果设置为征召状态
+ if (Props.draftOnExit && pawn.drafter != null)
+ {
+ pawn.drafter.Drafted = true;
+ }
+
+ // 触发事件
+ Notify_CrewRemoved(pawn);
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Error removing crew {pawn.LabelShort} from {parent.LabelShort}: {ex.Message}");
+ }
+ }
+
+ // 移除所有乘员
+ public void RemoveAllCrew(IntVec3? exitPos = null)
+ {
+ var crewToRemove = innerContainer;
+
+ foreach (var thing in crewToRemove)
+ {
+ if (thing is Pawn pawn)
+ {
+ RemoveCrew(pawn, exitPos);
+ }
+ }
+ }
+
+ // 获取所有符合条件的登机Pawn(半径内)
+ public List GetEligiblePawnsInRadius()
+ {
+ var eligiblePawns = new List();
+
+ if (parent.Map == null || !parent.Spawned)
+ return eligiblePawns;
+
+ // 获取半径内的所有Pawn
+ var pawnsInRadius = parent.Map.mapPawns.AllPawnsSpawned
+ .Where(p => p.Position.DistanceTo(parent.Position) <= Props.boardingRadius)
+ .ToList();
+
+ foreach (var pawn in pawnsInRadius)
+ {
+ // 检查是否满足条件
+ if (CanAddCrew(pawn) &&
+ pawn.Faction == parent.Faction &&
+ !pawn.Downed &&
+ !pawn.Dead &&
+ !pawn.IsPrisoner)
+ {
+ eligiblePawns.Add(pawn);
+ }
+ }
+
+ return eligiblePawns;
+ }
+
+ // 命令所有符合条件的Pawn登机
+ public void OrderAllEligibleToBoard()
+ {
+ var eligiblePawns = GetEligiblePawnsInRadius();
+
+ int count = 0;
+ foreach (var pawn in eligiblePawns)
+ {
+ if (!HasRoom)
+ break;
+
+ // 创建登机工作
+ Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_BoardMech, parent);
+ pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
+ count++;
+ }
+
+ // 显示消息
+ if (count > 0)
+ {
+ Messages.Message(
+ "WULA_CrewOrderedToBoard".Translate(count, parent.LabelShort),
+ parent,
+ MessageTypeDefOf.NeutralEvent
+ );
+ }
+ }
+
+ // 生成乘员到指定位置
+ private bool TrySpawnCrewAtPosition(Pawn pawn, IntVec3 position)
+ {
+ Map map = parent.Map;
+ if (map == null)
+ return false;
+
+ try
+ {
+ // 寻找安全位置
+ if (!position.Walkable(map) || position.Fogged(map))
+ {
+ CellFinder.TryFindRandomCellNear(position, map, 3,
+ c => c.Walkable(map) && !c.Fogged(map),
+ out position);
+ }
+
+ GenSpawn.Spawn(pawn, position, map, WipeMode.Vanish);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Error spawning crew {pawn.LabelShort}: {ex.Message}");
+ return false;
+ }
+ }
+
+ // 事件通知
+ private void Notify_CrewAdded(Pawn crew)
+ {
+ if (crew.Faction == Faction.OfPlayer)
+ {
+ Messages.Message(
+ "WULA_CrewBoarded".Translate(crew.LabelShort, parent.LabelShort),
+ parent,
+ MessageTypeDefOf.PositiveEvent
+ );
+ }
+ }
+
+ private void Notify_CrewRemoved(Pawn crew)
+ {
+ if (crew.Faction == Faction.OfPlayer)
+ {
+ Messages.Message(
+ "WULA_CrewExited".Translate(crew.LabelShort, parent.LabelShort),
+ parent,
+ MessageTypeDefOf.NeutralEvent
+ );
+ }
+ }
+
+ // Gizmo显示
+ public override IEnumerable CompGetGizmosExtra()
+ {
+ // 只对玩家派系显示
+ if (parent.Faction != Faction.OfPlayer)
+ yield break;
+
+ // 延迟初始化Gizmo
+ if (!gizmosInitialized)
+ {
+ InitializeGizmos();
+ gizmosInitialized = true;
+ }
+
+ // 登机按钮(如果有空间)
+ if (HasRoom)
+ {
+ yield return cachedBoardGizmo;
+ }
+
+ // 下机按钮(如果有乘员)
+ if (HasCrew)
+ {
+ yield return cachedExitGizmo;
+ }
+ }
+
+ private void InitializeGizmos()
+ {
+ // 登机Gizmo
+ cachedBoardGizmo = new Command_Action
+ {
+ defaultLabel = "WULA_BoardCrew".Translate(),
+ defaultDesc = "WULA_BoardCrewDesc".Translate(),
+ icon = Props.GetBoardCrewIcon(),
+ action = OrderAllEligibleToBoard,
+ hotKey = KeyBindingDefOf.Misc4
+ };
+
+ // 下机Gizmo
+ cachedExitGizmo = new Command_Action
+ {
+ defaultLabel = "WULA_ExitCrew".Translate(),
+ defaultDesc = "WULA_ExitCrewDesc".Translate(),
+ icon = Props.GetExitCrewIcon(),
+ action = () => RemoveAllCrew(),
+ hotKey = KeyBindingDefOf.Misc5
+ };
+ }
+
+ // 每帧更新
+ public override void CompTick()
+ {
+ base.CompTick();
+
+ // 定期检查乘员状态
+ if (Find.TickManager.TicksGame % 60 == 0)
+ {
+ CheckCrewStatus();
+ }
+ }
+
+ private void CheckCrewStatus()
+ {
+ var crewToRemove = new List();
+
+ foreach (var thing in innerContainer)
+ {
+ if (thing is Pawn pawn)
+ {
+ // 检查是否死亡
+ if (pawn.Dead)
+ {
+ crewToRemove.Add(pawn);
+ }
+
+ // 确保乘员不执行工作
+ pawn.jobs?.StopAll();
+ pawn.pather?.StopDead();
+ }
+ }
+
+ foreach (var pawn in crewToRemove)
+ {
+ RemoveCrew(pawn);
+ }
+ }
+
+ // 数据保存/加载
+ public override void PostExposeData()
+ {
+ base.PostExposeData();
+
+ Scribe_Deep.Look(ref innerContainer, "crewContainer", this);
+
+ if (Scribe.mode == LoadSaveMode.PostLoadInit)
+ {
+ // 重置Gizmo状态
+ gizmosInitialized = false;
+ cachedBoardGizmo = null;
+ cachedExitGizmo = null;
+ }
+ }
+
+ // IThingHolder接口实现
+ public ThingOwner GetDirectlyHeldThings()
+ {
+ return innerContainer;
+ }
+
+ public void GetChildHolders(List outChildren)
+ {
+ ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings());
+ }
+
+ // 获取乘员列表
+ public IEnumerable GetCrew()
+ {
+ foreach (var thing in innerContainer)
+ {
+ if (thing is Pawn pawn)
+ yield return pawn;
+ }
+ }
+
+ // 死亡/销毁时处理
+ public override void PostDestroy(DestroyMode mode, Map previousMap)
+ {
+ // 移除所有乘员
+ if (HasCrew)
+ {
+ RemoveAllCrew();
+ }
+
+ base.PostDestroy(mode, previousMap);
+ }
+
+ // 死亡时处理
+ public override void PostPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
+ {
+ base.PostPostApplyDamage(dinfo, totalDamageDealt);
+
+ // 如果机甲死亡,移除所有乘员
+ if (parent is Pawn mech && mech.Dead && HasCrew)
+ {
+ RemoveAllCrew();
+ }
+ }
+
+ // 绘制效果(可选)
+ public override void PostDraw()
+ {
+ base.PostDraw();
+
+ // 可以添加一些视觉效果,比如显示乘员数等
+ if (parent.Spawned && HasCrew)
+ {
+ // 在机甲上方显示乘员数量
+ Vector3 drawPos = parent.DrawPos;
+ drawPos.y = AltitudeLayer.MetaOverlays.AltitudeFor();
+
+ GenMapUI.DrawThingLabel(drawPos, $"x{CurrentCrewCount}", Color.green);
+ }
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Pawn_Comps/MechPilotHolder/CompMechPilotHolder.cs b/Source/WulaFallenEmpire/Pawn_Comps/MechPilotHolder/CompMechPilotHolder.cs
index 07cef3a7..ff297120 100644
--- a/Source/WulaFallenEmpire/Pawn_Comps/MechPilotHolder/CompMechPilotHolder.cs
+++ b/Source/WulaFallenEmpire/Pawn_Comps/MechPilotHolder/CompMechPilotHolder.cs
@@ -1,4 +1,3 @@
-// File: CompMechPilotHolder.cs (添加残疾殖民者搬运逻辑)
using WulaFallenEmpire;
using RimWorld;
using System;
@@ -15,26 +14,31 @@ namespace WulaFallenEmpire
public int maxPilots = 1;
public string pilotWorkTag = "MechPilot";
- // 新增:驾驶员图标配置
+ // 图标配置
public string summonPilotIcon = "Wula/UI/Commands/WULA_Enter_Mech";
public string ejectPilotIcon = "Wula/UI/Commands/WULA_Exit_Mech";
+ public string recallPilotIcon = "Wula/UI/Commands/WULA_Recall_Pilot";
+
+ // 快速登机配置
+ public bool enableQuickRecall = true;
+ public float recallRadius = 30f;
- public float ejectPilotHealthPercentThreshold = 0.1f; // 默认30%血量
- public bool allowEntryBelowThreshold = false; // 血量低于阈值时是否允许进入
+ public float ejectPilotHealthPercentThreshold = 0.1f;
+ public bool allowEntryBelowThreshold = false;
- // 新增:Hediff同步配置
- public bool syncPilotHediffs = true; // 是否同步驾驶员的Hediff
- public List syncedHediffDefs = null; // 需要同步的Hediff列表(null表示全部)
- public bool autoApplyHediffOnEntry = false; // 进入时自动添加指定的Hediff
- public HediffDef autoHediffDef = null; // 自动添加的Hediff
- public float autoHediffSeverity = 0.5f; // 自动添加的Hediff严重性
+ // Hediff同步配置
+ public bool syncPilotHediffs = true;
+ public List syncedHediffDefs = null;
+ public bool autoApplyHediffOnEntry = false;
+ public HediffDef autoHediffDef = null;
+ public float autoHediffSeverity = 0.5f;
public CompProperties_MechPilotHolder()
{
this.compClass = typeof(CompMechPilotHolder);
}
- // 新增:加载图标的方法
+ // 图标加载方法
public Texture2D GetSummonPilotIcon()
{
if (!string.IsNullOrEmpty(summonPilotIcon) && ContentFinder.Get(summonPilotIcon, false) != null)
@@ -54,20 +58,28 @@ namespace WulaFallenEmpire
return ContentFinder.Get("UI/Commands/Eject", false) ??
BaseContent.BadTex;
}
+
+ public Texture2D GetRecallPilotIcon()
+ {
+ if (!string.IsNullOrEmpty(recallPilotIcon) && ContentFinder.Get(recallPilotIcon, false) != null)
+ {
+ return ContentFinder.Get(recallPilotIcon);
+ }
+ return ContentFinder.Get("UI/Commands/SummonPilot", false) ??
+ BaseContent.BadTex;
+ }
}
public class CompMechPilotHolder : ThingComp, IThingHolder, ISuspendableThingHolder
{
public ThingOwner innerContainer;
- // 标记是否正在处理死亡/销毁事件,避免重复处理
private bool isProcessingDestruction = false;
-
- // 新增:记录是否已经因为低血量弹出过驾驶员
private bool hasEjectedDueToLowHealth = false;
-
- // 新增:存储驾驶员同步的Hediff
private Dictionary> syncedHediffs = new Dictionary>();
+
+ // 新增:记录上一次的驾驶员
+ private Pawn lastPilot = null;
public CompProperties_MechPilotHolder Props => (CompProperties_MechPilotHolder)props;
@@ -78,17 +90,15 @@ namespace WulaFallenEmpire
public bool IsContentsSuspended => true;
- // 新增:获取精神状态定义
+ // 精神状态定义
private MentalStateDef MechNoPilotStateDef => WULA_MentalStateDefOf.WULA_MechNoPilot;
- // 新增:检查并更新精神状态
private void CheckAndUpdateMentalState()
{
var mech = parent as Pawn;
if (mech == null || mech.Dead || MechNoPilotStateDef == null)
return;
- // 如果没有驾驶员,尝试进入待机状态
if (!HasPilots)
{
if (mech.MentalStateDef != MechNoPilotStateDef && !mech.InMentalState)
@@ -96,7 +106,6 @@ namespace WulaFallenEmpire
mech.mindState.mentalStateHandler.TryStartMentalState(MechNoPilotStateDef, null, true);
}
}
- // 如果有驾驶员,确保退出待机状态
else
{
if (mech.MentalStateDef == MechNoPilotStateDef)
@@ -106,45 +115,43 @@ namespace WulaFallenEmpire
}
}
- // 修改:添加驾驶员 - 添加Hediff同步功能
+ // 添加驾驶员
public void AddPilot(Pawn pawn)
{
if (!CanAddPilot(pawn))
return;
- // 将pawn添加到容器中
+ // 记录驾驶员
+ if (lastPilot != pawn)
+ {
+ lastPilot = pawn;
+ }
+
if (pawn.Spawned)
pawn.DeSpawnOrDeselect();
innerContainer.TryAdd(pawn, true);
- // 停止pawn的移动
pawn.pather?.StopDead();
pawn.jobs?.StopAll();
- // 触发事件
Notify_PilotAdded(pawn);
-
- // 更新机甲的精神状态
CheckAndUpdateMentalState();
- // 新增:同步驾驶员的Hediff
if (Props.syncPilotHediffs)
{
SyncPilotHediffs(pawn);
}
- // 新增:自动添加Hediff
if (Props.autoApplyHediffOnEntry && Props.autoHediffDef != null)
{
AddAutoHediff(pawn);
}
}
- // 修改:移除驾驶员 - 添加Hediff取消同步功能
+ // 移除驾驶员
public void RemovePilot(Pawn pawn, IntVec3? exitPos = null)
{
- // 新增:移除前,清理同步的Hediff
if (Props.syncPilotHediffs)
{
UnsyncPilotHediffs(pawn);
@@ -152,27 +159,16 @@ namespace WulaFallenEmpire
if (innerContainer.Contains(pawn))
{
- // 从容器中移除
innerContainer.Remove(pawn);
-
- // 将pawn放回地图
TrySpawnPilotAtPosition(pawn, exitPos ?? parent.Position);
-
- // 触发事件
Notify_PilotRemoved(pawn);
-
- // 停止机甲的工作
StopMechJobs();
-
- // 更新机甲的精神状态
CheckAndUpdateMentalState();
}
}
- // 新增:同步驾驶员的Hediff
private void SyncPilotHediffs(Pawn pawn)
{
- // 修复:确保parent是Wulamechunit类型
if (pawn == null || !(parent is Wulamechunit mech))
return;
@@ -180,23 +176,19 @@ namespace WulaFallenEmpire
{
var hediffsToSync = new List();
- // 收集需要同步的Hediff
foreach (var hediff in pawn.health.hediffSet.hediffs)
{
if (ShouldSyncHediff(hediff))
{
hediffsToSync.Add(hediff);
-
- // 激活Hediff的同步组件
var syncComp = hediff.TryGetComp();
if (syncComp != null)
{
- syncComp.OnPilotEnteredMech(mech); // 这里现在应该可以了
+ syncComp.OnPilotEnteredMech(mech);
}
}
}
- // 存储同步的Hediff
if (hediffsToSync.Count > 0)
{
syncedHediffs[pawn] = hediffsToSync;
@@ -208,7 +200,6 @@ namespace WulaFallenEmpire
}
}
- // 新增:取消同步驾驶员的Hediff
private void UnsyncPilotHediffs(Pawn pawn)
{
if (pawn == null || !syncedHediffs.ContainsKey(pawn))
@@ -216,7 +207,6 @@ namespace WulaFallenEmpire
try
{
- // 通知所有同步的Hediff断开连接
foreach (var hediff in syncedHediffs[pawn])
{
var syncComp = hediff.TryGetComp();
@@ -226,7 +216,6 @@ namespace WulaFallenEmpire
}
}
- // 从记录中移除
syncedHediffs.Remove(pawn);
}
catch (Exception ex)
@@ -235,34 +224,27 @@ namespace WulaFallenEmpire
}
}
- // 新增:判断Hediff是否需要同步
private bool ShouldSyncHediff(Hediff hediff)
{
if (hediff == null)
return false;
- // 检查是否有同步组件
var syncComp = hediff.TryGetComp();
if (syncComp == null)
return false;
- // 检查是否在指定的同步列表中
- if (Props.syncedHediffDefs != null &&
- Props.syncedHediffDefs.Count > 0)
+ if (Props.syncedHediffDefs != null && Props.syncedHediffDefs.Count > 0)
{
return Props.syncedHediffDefs.Contains(hediff.def.defName);
}
- // 默认同步所有有同步组件的Hediff
return true;
}
- // 新增:自动添加Hediff
private void AddAutoHediff(Pawn pawn)
{
try
{
- // 检查是否已经有相同的Hediff
var existingHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.autoHediffDef);
if (existingHediff == null)
{
@@ -277,27 +259,23 @@ namespace WulaFallenEmpire
}
}
- // 修改:在CompTick中添加Hediff同步检查
public override void CompTick()
{
base.CompTick();
try
{
- // 每60帧检查一次血量和精神状态
if (Find.TickManager.TicksGame % 60 == 0)
{
CheckLowHealth();
CheckAndUpdateMentalState();
}
- // 每120帧检查一次Hediff同步状态
if (Find.TickManager.TicksGame % 120 == 0)
{
CheckHediffSync();
}
- // 检查机甲是否死亡
var mech = parent as Pawn;
if (mech != null && mech.Dead && HasPilots)
{
@@ -305,11 +283,10 @@ namespace WulaFallenEmpire
return;
}
- // 定期检查驾驶员状态
var pilotsToRemove = new List();
foreach (var thing in innerContainer)
{
- if (thing is Pawn pawn && (pawn.Dead))
+ if (thing is Pawn pawn && pawn.Dead)
{
pilotsToRemove.Add(pawn);
}
@@ -320,12 +297,10 @@ namespace WulaFallenEmpire
RemovePilot(pawn);
}
- // 确保容器内的pawn处于正确状态
foreach (var thing in innerContainer)
{
if (thing is Pawn pawn)
{
- // 确保pawn在容器内不执行任何工作
pawn.jobs?.StopAll();
pawn.pather?.StopDead();
}
@@ -337,37 +312,30 @@ namespace WulaFallenEmpire
}
}
- // 新增:检查Hediff同步状态
private void CheckHediffSync()
{
- // 修复:确保parent是Wulamechunit类型
if (!Props.syncPilotHediffs || !(parent is Wulamechunit))
return;
try
{
- // 检查每个驾驶员的同步状态
foreach (var pilot in GetPilots())
{
if (pilot == null || pilot.Dead || pilot.Destroyed)
continue;
- // 检查是否有新的需要同步的Hediff
SyncPilotHediffs(pilot);
- // 检查是否有需要移除的Hediff
if (syncedHediffs.ContainsKey(pilot))
{
var currentHediffs = pilot.health.hediffSet.hediffs
.Where(ShouldSyncHediff)
.ToList();
- // 找出不再存在的Hediff
var removedHediffs = syncedHediffs[pilot]
.Where(h => !currentHediffs.Contains(h))
.ToList();
- // 清理不再存在的Hediff
foreach (var hediff in removedHediffs)
{
var syncComp = hediff.TryGetComp();
@@ -377,7 +345,6 @@ namespace WulaFallenEmpire
}
}
- // 更新记录
syncedHediffs[pilot] = currentHediffs;
}
}
@@ -388,7 +355,6 @@ namespace WulaFallenEmpire
}
}
- // 修改:在生成后初始化精神状态
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
@@ -398,16 +364,13 @@ namespace WulaFallenEmpire
Log.Warning($"[WULA] CompMechPilotHolder attached to non-mech: {parent}");
}
- // 确保加载后恢复状态
if (innerContainer == null)
{
innerContainer = new ThingOwner(this);
}
- // 初始化精神状态
CheckAndUpdateMentalState();
- // 新增:加载后重新同步Hediff
if (Props.syncPilotHediffs)
{
foreach (var pilot in GetPilots())
@@ -417,7 +380,6 @@ namespace WulaFallenEmpire
}
}
- // 修改:在数据保存和加载时处理Hediff同步
public override void PostExposeData()
{
base.PostExposeData();
@@ -425,17 +387,15 @@ namespace WulaFallenEmpire
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
Scribe_Values.Look(ref isProcessingDestruction, "isProcessingDestruction", false);
Scribe_Values.Look(ref hasEjectedDueToLowHealth, "hasEjectedDueToLowHealth", false);
- Scribe_Collections.Look(ref syncedHediffs, "syncedHediffs",
- LookMode.Reference, LookMode.Deep);
+ Scribe_Collections.Look(ref syncedHediffs, "syncedHediffs", LookMode.Reference, LookMode.Deep);
+ Scribe_References.Look(ref lastPilot, "lastPilot");
- // 加载后检查精神状态和Hediff同步
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
CheckAndUpdateMentalState();
if (Props.syncPilotHediffs)
{
- // 重新同步所有驾驶员的Hediff
foreach (var pilot in GetPilots())
{
SyncPilotHediffs(pilot);
@@ -444,34 +404,25 @@ namespace WulaFallenEmpire
}
}
- // 新增:停止机甲所有工作
private void StopMechJobs()
{
var mech = parent as Pawn;
if (mech == null)
return;
- // 停止所有工作
mech.jobs?.StopAll();
-
- // 停止移动
mech.pather?.StopDead();
- // 取消征召
var drafter = mech.drafter;
if (drafter != null && mech.Drafted)
{
mech.drafter.Drafted = false;
}
- // 停止当前所有工作队列
mech.jobs?.ClearQueuedJobs();
-
- // 清除敌人目标
mech.mindState.enemyTarget = null;
}
- // 获取机甲当前血量百分比
public float CurrentHealthPercent
{
get
@@ -484,30 +435,21 @@ namespace WulaFallenEmpire
}
}
- // 检查机甲是否低于血量阈值
- public bool IsBelowHealthThreshold
- {
- get
- {
- return CurrentHealthPercent < Props.ejectPilotHealthPercentThreshold;
- }
- }
+ public bool IsBelowHealthThreshold => CurrentHealthPercent < Props.ejectPilotHealthPercentThreshold;
- // 修改 CanAddPilot 方法,添加血量检查
public bool CanAddPilot(Pawn pawn)
{
if (pawn == null || pawn.Dead)
return false;
- // 允许无法行动但还活着的殖民者
if (pawn.Downed)
- return true; // 这是新增的关键修改
+ return true;
if (!HasRoom)
return false;
if (innerContainer.Contains(pawn))
return false;
- // 检查工作标签
+
if (!string.IsNullOrEmpty(Props.pilotWorkTag))
{
WorkTags tag;
@@ -518,7 +460,6 @@ namespace WulaFallenEmpire
}
}
- // 新增:检查血量阈值
if (!Props.allowEntryBelowThreshold && IsBelowHealthThreshold)
{
return false;
@@ -526,45 +467,36 @@ namespace WulaFallenEmpire
return true;
}
- // 修改:检查殖民者是否能够自行移动到机甲
private bool CanPawnMoveToMech(Pawn pawn, Wulamechunit mech)
{
if (pawn == null || mech == null)
return false;
- // 如果殖民者无法行动,需要搬运
if (pawn.Downed)
return false;
- // 检查殖民者是否能到达机甲
return pawn.CanReach(mech, PathEndMode.Touch, Danger.Deadly);
}
- // 修改 CompMechPilotHolder 的 CheckLowHealth 方法
private void CheckLowHealth()
{
if (IsBelowHealthThreshold && HasPilots)
{
- // 如果低于阈值且有驾驶员,弹出所有驾驶员
EjectPilotsDueToLowHealth();
}
else if (!IsBelowHealthThreshold)
{
- // 如果恢复到阈值以上,重置标记
hasEjectedDueToLowHealth = false;
}
}
- // 新增:因为低血量弹出驾驶员
private void EjectPilotsDueToLowHealth()
{
if (hasEjectedDueToLowHealth)
return;
- // 弹出所有驾驶员
RemoveAllPilots();
- // 发送消息
if (parent.Faction == Faction.OfPlayer)
{
Messages.Message("WULA_PilotsEjectedDueToLowHealth".Translate(parent.LabelShort,
@@ -575,12 +507,10 @@ namespace WulaFallenEmpire
hasEjectedDueToLowHealth = true;
}
- // 新增:在承受伤害后检查血量
public override void PostPostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
{
base.PostPostApplyDamage(dinfo, totalDamageDealt);
- // 如果机甲死亡,弹出驾驶员
var mech = parent as Pawn;
if (mech != null && mech.Dead)
{
@@ -588,19 +518,27 @@ namespace WulaFallenEmpire
}
else
{
- // 检查是否因为伤害导致血量过低
CheckLowHealth();
}
}
- // 修改 Gizmo 显示,添加血量信息和Hediff同步状态
+ // 修改Gizmo显示:只在条件满足时显示快速登机按钮
public override IEnumerable CompGetGizmosExtra()
{
- // 修复:确保parent是Wulamechunit类型
if (!(parent is Wulamechunit mech) || mech.Faction != Faction.OfPlayer)
yield break;
- // 召唤驾驶员Gizmo
+ // 快速登机按钮(只有在所有条件都满足时才显示)
+ if (Props.enableQuickRecall && HasRoom && !IsBelowHealthThreshold)
+ {
+ var recallGizmo = CreateRecallGizmo();
+ if (recallGizmo != null)
+ {
+ yield return recallGizmo;
+ }
+ }
+
+ // 召唤驾驶员按钮
if (HasRoom)
{
Command_Action summonCommand = new Command_Action
@@ -615,7 +553,6 @@ namespace WulaFallenEmpire
hotKey = KeyBindingDefOf.Misc2
};
- // 如果血量低于阈值且不允许进入,禁用按钮
if (!Props.allowEntryBelowThreshold && IsBelowHealthThreshold)
{
summonCommand.Disable("WULA_MechTooDamagedForEntry".Translate());
@@ -640,22 +577,82 @@ namespace WulaFallenEmpire
};
}
}
+
+ // 创建快速登机Gizmo(只有条件完全满足时才创建)
+ private Command_Action CreateRecallGizmo()
+ {
+ // 检查是否有上次驾驶员
+ if (lastPilot == null)
+ return null;
+
+ // 检查驾驶员是否可用
+ if (!IsPilotAvailableForRecall(lastPilot))
+ return null;
+
+ // 创建并返回Gizmo
+ return new Command_Action
+ {
+ defaultLabel = "WULA_RecallLastPilot".Translate(),
+ defaultDesc = "WULA_RecallLastPilotDesc".Translate(),
+ icon = Props.GetRecallPilotIcon(),
+ action = () =>
+ {
+ RecallLastPilot();
+ },
+ hotKey = KeyBindingDefOf.Misc3
+ };
+ }
+
+ // 检查驾驶员是否可用于快速登机
+ private bool IsPilotAvailableForRecall(Pawn pilot)
+ {
+ if (pilot == null || pilot.Dead || pilot.Destroyed)
+ return false;
+
+ if (innerContainer.Contains(pilot))
+ return false;
+
+ if (!CanAddPilot(pilot))
+ return false;
+
+ if (parent.Map == null || !pilot.Spawned || pilot.Map != parent.Map)
+ return false;
+
+ if (pilot.Position.DistanceTo(parent.Position) > Props.recallRadius)
+ return false;
+
+ if (!pilot.CanReach(parent, PathEndMode.Touch, Danger.Deadly))
+ return false;
+
+ if (pilot.IsPrisoner || pilot.IsSlave)
+ return false;
+
+ return true;
+ }
+
+ // 召回上次驾驶员
+ private void RecallLastPilot()
+ {
+ if (lastPilot == null || IsFull || !IsPilotAvailableForRecall(lastPilot))
+ {
+ return;
+ }
+
+ Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_EnterMech, parent);
+ lastPilot.jobs.TryTakeOrderedJob(job, JobTag.Misc);
+ }
public CompMechPilotHolder()
{
innerContainer = new ThingOwner(this);
}
- // 修改:弹出所有驾驶员时取消Hediff同步
public void RemoveAllPilots(IntVec3? exitPos = null)
{
- // 记录是否有驾驶员
bool hadPilots = HasPilots;
- // 复制列表以避免迭代时修改的问题
var pilotsToRemove = innerContainer.ToList();
- // 先取消所有Hediff同步
foreach (var thing in pilotsToRemove)
{
if (thing is Pawn pawn)
@@ -664,7 +661,6 @@ namespace WulaFallenEmpire
}
}
- // 然后移除所有驾驶员
foreach (var thing in pilotsToRemove)
{
if (thing is Pawn pawn)
@@ -673,14 +669,12 @@ namespace WulaFallenEmpire
}
}
- // 如果有机甲并且原来有驾驶员,现在没有了,停止工作
if (hadPilots && parent is Pawn mech)
{
StopMechJobs();
}
}
- // 修改:专门用于死亡/销毁时弹出驾驶员的方法,取消Hediff同步
public void EjectAllPilotsOnDeath()
{
if (isProcessingDestruction)
@@ -695,7 +689,6 @@ namespace WulaFallenEmpire
return;
}
- // 先取消所有Hediff同步
var pilots = innerContainer.ToList();
foreach (var thing in pilots)
{
@@ -705,26 +698,14 @@ namespace WulaFallenEmpire
}
}
- // 获取安全位置
IntVec3 ejectPos = FindSafeEjectPosition();
- // 弹出所有驾驶员
foreach (var thing in pilots)
{
if (thing is Pawn pawn)
{
- // 从容器中移除
innerContainer.Remove(pawn);
-
- // 尝试生成到地图上
- if (TrySpawnPilotAtPosition(pawn, ejectPos))
- {
- // 驾驶员成功弹出
- }
- else
- {
- Log.Error($"[WULA] 无法弹出驾驶员: {pawn.LabelShort}");
- }
+ TrySpawnPilotAtPosition(pawn, ejectPos);
}
}
}
@@ -744,10 +725,8 @@ namespace WulaFallenEmpire
if (map == null)
return parent.Position;
- // 优先选择机甲周围的安全位置
IntVec3 pos = parent.Position;
- // 如果当前位置不安全,查找周围安全位置
if (!pos.Walkable(map) || pos.Fogged(map))
{
for (int i = 1; i <= 5; i++)
@@ -762,7 +741,6 @@ namespace WulaFallenEmpire
}
}
- // 如果周围没有安全位置,使用随机位置
if (!pos.Walkable(map) || pos.Fogged(map))
{
CellFinder.TryFindRandomCellNear(pos, map, 10,
@@ -782,7 +760,6 @@ namespace WulaFallenEmpire
return false;
}
- // 尝试在指定位置生成
try
{
if (GenGrid.InBounds(position, map) && position.Walkable(map) && !position.Fogged(map))
@@ -791,7 +768,6 @@ namespace WulaFallenEmpire
return true;
}
- // 如果指定位置不行,找附近的位置
IntVec3 spawnPos;
if (RCellFinder.TryFindRandomCellNearWith(position,
cell => cell.Walkable(map) && !cell.Fogged(map),
@@ -801,7 +777,6 @@ namespace WulaFallenEmpire
return true;
}
- // 实在找不到位置,就在任意位置生成
CellFinder.TryFindRandomCellNear(position, map, 20,
cell => cell.Walkable(map) && !cell.Fogged(map),
out spawnPos);
@@ -855,10 +830,8 @@ namespace WulaFallenEmpire
}
}
- // 关键修复:重写销毁相关方法
public override void PostDestroy(DestroyMode mode, Map previousMap)
{
- // 先弹出所有驾驶员并取消Hediff同步
if (HasPilots)
{
EjectAllPilotsOnDeath();
@@ -867,7 +840,6 @@ namespace WulaFallenEmpire
base.PostDestroy(mode, previousMap);
}
- // IThingHolder 接口实现
public ThingOwner GetDirectlyHeldThings()
{
return innerContainer;
@@ -878,32 +850,26 @@ namespace WulaFallenEmpire
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings());
}
- // 修改:显示驾驶员选择菜单,包含无法行动的殖民者
private void ShowPilotSelectionMenu()
{
- // 修复:确保parent是Wulamechunit类型
if (!(parent is Wulamechunit mech))
return;
List options = new List();
- // 获取所有可用的殖民者(包括无法行动的)
var allColonists = mech.Map.mapPawns.FreeColonists
.Where(p => CanAddPilot(p))
.ToList();
- // 分类:能够行动和无法行动的
var ableColonists = allColonists.Where(p => CanPawnMoveToMech(p, mech)).ToList();
var disabledColonists = allColonists.Where(p => !CanPawnMoveToMech(p, mech)).ToList();
- // 为能够行动的殖民者创建选项
if (ableColonists.Count == 0 && disabledColonists.Count == 0)
{
options.Add(new FloatMenuOption("WULA_NoAvailablePilots".Translate(), null));
}
else
{
- // 能够行动的殖民者:直接进入
foreach (var colonist in ableColonists)
{
string colonistLabel = colonist.LabelShortCap;
@@ -914,20 +880,12 @@ namespace WulaFallenEmpire
action,
colonist,
Color.white,
- MenuOptionPriority.Default,
- null,
- null,
- 0f,
- null,
- null,
- true,
- 0
+ MenuOptionPriority.Default
);
options.Add(option);
}
- // 无法行动的殖民者:需要搬运
foreach (var colonist in disabledColonists)
{
string colonistLabel = colonist.LabelShortCap + " " + "WULA_DisabledColonistRequiresCarry".Translate();
@@ -938,14 +896,7 @@ namespace WulaFallenEmpire
action,
colonist,
Color.yellow,
- MenuOptionPriority.Default,
- null,
- null,
- 0f,
- null,
- null,
- true,
- 0
+ MenuOptionPriority.Default
);
options.Add(option);
@@ -957,22 +908,18 @@ namespace WulaFallenEmpire
private void OrderColonistToEnterMech(Pawn colonist)
{
- // 修复:确保parent是Wulamechunit类型
if (!(parent is Wulamechunit mech) || colonist == null)
return;
- // 为殖民者安排进入机甲的工作
Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_EnterMech, mech);
colonist.jobs.TryTakeOrderedJob(job, JobTag.Misc);
}
- // 新增:为残疾殖民者安排搬运工作
private void OrderCarryDisabledColonistToMech(Pawn disabledColonist)
{
if (!(parent is Wulamechunit mech) || disabledColonist == null)
return;
- // 寻找最近的、能够搬运的殖民者
Pawn carrier = FindClosestAvailableCarrier(disabledColonist, mech);
if (carrier == null)
@@ -982,7 +929,6 @@ namespace WulaFallenEmpire
return;
}
- // 为搬运者安排搬运工作
Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_CarryToMech, disabledColonist, mech);
carrier.jobs.TryTakeOrderedJob(job, JobTag.Misc);
@@ -990,13 +936,11 @@ namespace WulaFallenEmpire
parent, MessageTypeDefOf.PositiveEvent);
}
- // 新增:寻找最近的可用搬运者
private Pawn FindClosestAvailableCarrier(Pawn disabledColonist, Wulamechunit mech)
{
if (disabledColonist.Map == null)
return null;
- // 寻找能够行动的殖民者,并且能够搬运
var potentialCarriers = disabledColonist.Map.mapPawns.FreeColonists
.Where(p => p != disabledColonist && !p.Downed &&
p.CanReserveAndReach(disabledColonist, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, false) &&
@@ -1006,7 +950,6 @@ namespace WulaFallenEmpire
if (potentialCarriers.Count == 0)
return null;
- // 选择最近的殖民者
return potentialCarriers
.OrderBy(p => p.Position.DistanceTo(disabledColonist.Position))
.FirstOrDefault();
diff --git a/Source/WulaFallenEmpire/Pawn_Comps/Pawn_Flight/CompPawnFlight.cs b/Source/WulaFallenEmpire/Pawn_Comps/Pawn_Flight/CompPawnFlight.cs
index bd728922..acdc7d9f 100644
--- a/Source/WulaFallenEmpire/Pawn_Comps/Pawn_Flight/CompPawnFlight.cs
+++ b/Source/WulaFallenEmpire/Pawn_Comps/Pawn_Flight/CompPawnFlight.cs
@@ -25,10 +25,10 @@ namespace WulaFallenEmpire
{
yield return new Command_Toggle
{
- defaultLabel = "Toggle Flight",
- defaultDesc = "Toggle flight mode on or off.",
+ defaultLabel = "WULA_ToggleFlight".Translate(),
+ defaultDesc = "WULA_ToggleFlight_Desc".Translate() + (flightEnabled ? "WULA_ToggleFlight_Enable".Translate() : "WULA_ToggleFlight_Disable".Translate()),
Order = 100f,
- icon = ContentFinder.Get("Wula/UI/Commands/WFE_FlightToggle", false)
+ icon = ContentFinder.Get("Wula/UI/Commands/WULA_FlightToggle", false)
?? RimWorld.TexCommand.GatherSpotActive,
isActive = () => flightEnabled,
toggleAction = () =>
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
index 6dc6f405..3a096abf 100644
--- a/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_AreaDamage/CompAreaDamage.cs
@@ -1,5 +1,6 @@
-using System.Collections.Generic;
using RimWorld;
+using System.Collections.Generic;
+using System.Runtime.Remoting.Messaging;
using UnityEngine;
using Verse;
@@ -23,10 +24,20 @@ namespace WulaFallenEmpire
public override void CompTick()
{
base.CompTick();
-
- if (!parent.Spawned || !enabled)
+
+ if (!enabled)
return;
+ if (parent is Pawn pawn && (pawn.IsSelfShutdown() || !pawn.Awake() || pawn.Dead || pawn.Downed || !pawn.Spawned || pawn.Destroyed))
+ return;
+
+ //对于mechunit,需要判定有没有驾驶员
+ var MechPilotComp = parent.TryGetComp();
+ if (MechPilotComp != null && !MechPilotComp.HasPilots)
+ {
+ return;
+ }
+
ticksUntilNextDamage--;
if (ticksUntilNextDamage <= 0)
{
diff --git a/Source/WulaFallenEmpire/ThingComp/WULA_AreaShield/ThingComp_AreaShield.cs b/Source/WulaFallenEmpire/ThingComp/WULA_AreaShield/ThingComp_AreaShield.cs
index c73cc423..8438c6fa 100644
--- a/Source/WulaFallenEmpire/ThingComp/WULA_AreaShield/ThingComp_AreaShield.cs
+++ b/Source/WulaFallenEmpire/ThingComp/WULA_AreaShield/ThingComp_AreaShield.cs
@@ -1,16 +1,16 @@
-using RimWorld;
-using Verse;
-using UnityEngine;
-using Verse.Sound;
+using HarmonyLib;
+using RimWorld;
using System.Collections.Generic;
-using HarmonyLib;
+using UnityEngine;
+using Verse;
+using Verse.Sound;
+using static RimWorld.MechClusterSketch;
namespace WulaFallenEmpire
{
[StaticConstructorOnStartup]
public class ThingComp_AreaShield : ThingComp
{
- // 现有的字段保持不变...
private int lastInterceptTicks = -999999;
public int ticksToReset = 0;
public int currentHitPoints;
@@ -122,7 +122,6 @@ namespace WulaFallenEmpire
}
}
- // 现有的其他方法保持不变...
private float GetCurrentAlpha()
{
// 多个透明度来源叠加,取最大值
@@ -220,14 +219,21 @@ namespace WulaFallenEmpire
if (Holder == null || !Holder.Spawned || Holder.Destroyed)
return false;
- if (Holder is Pawn pawn && (pawn.Dead || pawn.Downed))
+ if (Holder is Pawn pawn && (pawn.IsSelfShutdown() || !pawn.Awake() || pawn.Dead || pawn.Downed || !pawn.Spawned))
return false;
if (IsOnCooldown)
return false;
-
+
+ //对于mechunit,需要判定有没有驾驶员
+ var MechPilotComp = Holder.TryGetComp();
+ if (MechPilotComp != null && !MechPilotComp.HasPilots)
+ {
+ return false;
+ }
+
// 装备:只有在立定时才激活
- if (IsEquipment && IsHolderMoving)
+ if (IsHolderMoving)
return false;
return true;
@@ -338,7 +344,6 @@ namespace WulaFallenEmpire
}
}
- // 现有的其他方法保持不变...
private void ApplyCosts(int cost = 1)
{
currentHitPoints -= cost;
@@ -359,7 +364,7 @@ namespace WulaFallenEmpire
if (currentHitPoints <= 0)
return false;
-
+
try
{
if (!GenGeo.IntersectLineCircleOutline(Holder.Position.ToVector2(), Props.radius, lastExactPos.ToVector2(), newExactPos.ToVector2()))
diff --git a/Source/WulaFallenEmpire/Work/BoardMech/FloatMenuOptionProvider_BoardMech.cs b/Source/WulaFallenEmpire/Work/BoardMech/FloatMenuOptionProvider_BoardMech.cs
new file mode 100644
index 00000000..0e899a6f
--- /dev/null
+++ b/Source/WulaFallenEmpire/Work/BoardMech/FloatMenuOptionProvider_BoardMech.cs
@@ -0,0 +1,293 @@
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Verse;
+using Verse.AI;
+
+namespace WulaFallenEmpire
+{
+ public class FloatMenuOptionProvider_BoardMech : FloatMenuOptionProvider
+ {
+ private static readonly List tmpPawns = new List();
+
+ protected override bool Drafted => false; // 征召状态下不能登机
+ protected override bool Undrafted => true; // 非征召状态下可以登机
+ protected override bool Multiselect => true; // 支持多选
+
+ // 检查Thing是否为机甲
+ private bool IsMech(Thing thing)
+ {
+ // 检查是否有CompMechCrewHolder组件
+ return thing?.TryGetComp() != null;
+ }
+
+ // 检查Pawn是否在机甲内
+ 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;
+ }
+
+ 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
+ Thing mech = null;
+ foreach (var thing in clickedThings)
+ {
+ if (IsMech(thing))
+ {
+ mech = thing;
+ break;
+ }
+ }
+
+ if (mech == null)
+ return false;
+
+ return true;
+ }
+
+ // 重写:获取选项
+ public override IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context)
+ {
+ if (!AppliesInt(context))
+ yield break;
+
+ if (context.IsMultiselect)
+ {
+ var option = GetMultiselectBoardMechOption(clickedThing, context);
+ if (option != null)
+ yield return option;
+ yield break;
+ }
+
+ var singleOption = GetSingleOptionFor(clickedThing, context);
+ if (singleOption != null)
+ yield return singleOption;
+ }
+
+ // 获取多选选项
+ private FloatMenuOption GetMultiselectBoardMechOption(Thing clickedThing, FloatMenuContext context)
+ {
+ tmpPawns.Clear();
+
+ var comp = clickedThing.TryGetComp();
+ if (comp == null)
+ return null;
+
+ // 收集所有可以登机的Pawn
+ foreach (var pawn in context.ValidSelectedPawns)
+ {
+ if (CanPawnBoardMech(pawn, clickedThing, 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_BoardMech".Translate(clickedThing.LabelShort) + ": " + failStr,
+ null,
+ MenuOptionPriority.DisabledOption
+ );
+ }
+
+ // 计算可以登机的数量
+ int canBoardCount = 0;
+ foreach (var pawn in tmpPawns)
+ {
+ if (comp.HasRoom)
+ {
+ canBoardCount++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ string label = "WULA_BoardMech".Translate(clickedThing.LabelShort);
+
+ return new FloatMenuOption(label, () =>
+ {
+ FleckMaker.Static(clickedThing.DrawPos, clickedThing.MapHeld, FleckDefOf.FeedbackEquip);
+
+ // 为每个可以登机的Pawn创建Job
+ foreach (var pawn in tmpPawns)
+ {
+ if (comp.HasRoom && CanPawnBoardMech(pawn, clickedThing, comp))
+ {
+ Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_BoardMech, clickedThing);
+ pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
+ }
+ }
+ }, MenuOptionPriority.High);
+ }
+
+ // 获取单个选项
+ protected override FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context)
+ {
+ if (clickedThing == null || context.FirstSelectedPawn == null)
+ return null;
+
+ // 检查是否有乘员组件
+ var comp = clickedThing.TryGetComp();
+ if (comp == null)
+ return null;
+
+ // 创建菜单选项
+ return CreateBoardMechOption(clickedThing, context.FirstSelectedPawn, comp);
+ }
+
+ // 创建登机菜单选项
+ private FloatMenuOption CreateBoardMechOption(Thing mech, Pawn pawn, CompMechCrewHolder comp)
+ {
+ string label = "WULA_BoardMech".Translate(mech.LabelShort);
+ string disabledReason = "";
+
+ // 检查条件
+ bool canBoard = CanPawnBoardMech(pawn, mech, comp, ref disabledReason);
+
+ if (canBoard)
+ {
+ return new FloatMenuOption(label, () =>
+ {
+ // 创建登机工作
+ Job job = JobMaker.MakeJob(Wula_JobDefOf.WULA_BoardMech, mech);
+ pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
+
+ // 播放音效
+ FleckMaker.Static(mech.DrawPos, mech.MapHeld, FleckDefOf.FeedbackEquip);
+ }, MenuOptionPriority.High);
+ }
+ else
+ {
+ return new FloatMenuOption(
+ label + ": " + disabledReason,
+ null,
+ MenuOptionPriority.DisabledOption);
+ }
+ }
+
+ // 检查是否可以登机(带原因)
+ private bool CanPawnBoardMech(Pawn pawn, Thing mech, CompMechCrewHolder comp, ref string disabledReason)
+ {
+ // 检查机甲是否已满
+ if (comp.IsFull)
+ {
+ disabledReason = "WULA_MechCrewFull".Translate();
+ return false;
+ }
+
+ // 检查Pawn是否可以成为乘员
+ if (!comp.CanAddCrew(pawn))
+ {
+ disabledReason = "WULA_CannotBecomeCrew".Translate();
+ return false;
+ }
+
+ // 检查Pawn是否已经在机甲内
+ if (IsPawnInMech(pawn, mech))
+ {
+ disabledReason = "AlreadyInMech".Translate();
+ return false;
+ }
+
+ // 检查距离
+ if (!pawn.CanReach(mech, PathEndMode.Touch, Danger.Deadly))
+ {
+ disabledReason = "NoPath".Translate();
+ return false;
+ }
+
+ // 检查Pawn状态
+ 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 is Pawn mechPawn && mechPawn.Downed)
+ {
+ disabledReason = "Downed".Translate();
+ return false;
+ }
+
+ if (mech is Pawn mechPawn2 && mechPawn2.Dead)
+ {
+ disabledReason = "Dead".Translate();
+ return false;
+ }
+
+ // 检查是否被征召(乘员不能是征召状态)
+ if (pawn.Drafted)
+ {
+ disabledReason = "Drafted".Translate();
+ return false;
+ }
+
+ return true;
+ }
+
+ // 检查是否可以登机(简化版)
+ private bool CanPawnBoardMech(Pawn pawn, Thing mech, CompMechCrewHolder comp)
+ {
+ string disabledReason = "";
+ return CanPawnBoardMech(pawn, mech, comp, ref disabledReason);
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Work/BoardMech/JobDriver_BoardMech.cs b/Source/WulaFallenEmpire/Work/BoardMech/JobDriver_BoardMech.cs
new file mode 100644
index 00000000..bc02b470
--- /dev/null
+++ b/Source/WulaFallenEmpire/Work/BoardMech/JobDriver_BoardMech.cs
@@ -0,0 +1,67 @@
+using System.Collections.Generic;
+using Verse;
+using Verse.AI;
+using RimWorld;
+
+namespace WulaFallenEmpire
+{
+ public class JobDriver_BoardMech : JobDriver
+ {
+ private const TargetIndex MechIndex = TargetIndex.A;
+
+ private CompMechCrewHolder CrewComp => job.targetA.Thing?.TryGetComp();
+
+ public override bool TryMakePreToilReservations(bool errorOnFailed)
+ {
+ // 预留目标机甲
+ if (!pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ protected override IEnumerable MakeNewToils()
+ {
+ // 第0步:添加失败条件
+ AddFailCondition(() =>
+ {
+ var mech = TargetThingA as Pawn;
+ if (mech == null || mech.Destroyed || mech.Dead)
+ return true;
+
+ var comp = CrewComp;
+ if (comp == null || comp.IsFull || !comp.CanAddCrew(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 boardToil = new Toil();
+ boardToil.initAction = () =>
+ {
+ var mech = TargetThingA as Pawn;
+ if (mech == null)
+ return;
+
+ var comp = CrewComp;
+ if (comp != null && comp.CanAddCrew(pawn))
+ {
+ comp.AddCrew(pawn);
+ }
+ };
+ boardToil.defaultCompleteMode = ToilCompleteMode.Instant;
+ yield return boardToil;
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Work/EnterMech/FloatMenuOptionProvider_EnterMech.cs b/Source/WulaFallenEmpire/Work/EnterMech/FloatMenuOptionProvider_EnterMech.cs
index ec8039bd..1114a1a3 100644
--- a/Source/WulaFallenEmpire/Work/EnterMech/FloatMenuOptionProvider_EnterMech.cs
+++ b/Source/WulaFallenEmpire/Work/EnterMech/FloatMenuOptionProvider_EnterMech.cs
@@ -1,6 +1,7 @@
-// File: FloatMenuOptionProvider_EnterMech.cs
using RimWorld;
+using System;
using System.Collections.Generic;
+using System.Linq;
using Verse;
using Verse.AI;
@@ -8,6 +9,7 @@ namespace WulaFallenEmpire
{
public class FloatMenuOptionProvider_EnterMech : FloatMenuOptionProvider
{
+ private static readonly List tmpPawns = new List();
// 检查Thing是否为机甲
private bool IsMech(Thing thing)
@@ -15,9 +17,9 @@ namespace WulaFallenEmpire
return thing is Wulamechunit || thing?.GetType()?.IsSubclassOf(typeof(Wulamechunit)) == true;
}
- protected override bool Drafted => true; // 征召状态下不能进入机甲
+ protected override bool Drafted => false; // 征召状态下不能进入机甲
protected override bool Undrafted => true; // 非征召状态下可以进入
- protected override bool Multiselect => true; // 不支持多选
+ protected override bool Multiselect => true; // 支持多选
// 检查是否适用于当前上下文
protected override bool AppliesInt(FloatMenuContext context)
@@ -50,40 +52,97 @@ namespace WulaFallenEmpire
if (comp == null)
return false;
- // 检查殖民者是否已经在机甲内
- // 由于CompMechPilotHolder没有ContainsPilot方法,我们需要通过其他方式检查
- if (IsPawnInMech(context.FirstSelectedPawn, mech))
- return false;
-
return true;
}
- // 检查殖民者是否已经在机甲内(替代ContainsPilot)
- private bool IsPawnInMech(Pawn pawn, Thing mech)
+ // 重写:获取选项
+ public override IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context)
{
- var comp = mech.TryGetComp();
- if (comp == null)
- return false;
-
- // 尝试通过内部容器检查
- var holder = comp as IThingHolder;
- if (holder != null)
+ if (!AppliesInt(context))
+ yield break;
+
+ if (context.IsMultiselect)
{
- var things = holder.GetDirectlyHeldThings();
- if (things != null && things.Contains(pawn))
- return true;
+ var option = GetMultiselectEnterMechOption(clickedThing, context);
+ if (option != null)
+ yield return option;
+ yield break;
}
- // 或者尝试通过其他属性检查
- // 这里假设CompMechPilotHolder有HasPilots属性
- if (comp.HasPilots)
+ 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)
{
- // 如果有必要,可以通过反射或其他方式检查具体驾驶员
- // 暂时返回false,假设不在机甲内
- return false;
+ if (CanPawnEnterMech(pawn, mech, comp))
+ {
+ tmpPawns.Add(pawn);
+ }
}
- return false;
+ 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);
}
// 获取单个选项
@@ -111,6 +170,25 @@ namespace WulaFallenEmpire
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)
{
@@ -118,7 +196,7 @@ namespace WulaFallenEmpire
string disabledReason = "";
// 检查条件是否允许进入
- bool canEnter = CanEnterMech(mech, pawn, comp, ref disabledReason);
+ bool canEnter = CanPawnEnterMech(pawn, mech, comp, ref disabledReason);
// 如果条件允许,创建可点击的选项
if (canEnter)
@@ -129,7 +207,7 @@ namespace WulaFallenEmpire
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);
}
@@ -143,8 +221,8 @@ namespace WulaFallenEmpire
}
}
- // 检查殖民者是否可以进入机甲
- private bool CanEnterMech(Wulamechunit mech, Pawn pawn, CompMechPilotHolder comp, ref string disabledReason)
+ // 检查殖民者是否可以进入机甲(带原因)
+ private bool CanPawnEnterMech(Pawn pawn, Wulamechunit mech, CompMechPilotHolder comp, ref string disabledReason)
{
// 检查机甲是否已满
if (comp.IsFull)
@@ -160,6 +238,13 @@ namespace WulaFallenEmpire
return false;
}
+ // 检查殖民者是否已经在机甲内
+ if (IsPawnInMech(pawn, mech))
+ {
+ disabledReason = "AlreadyInMech".Translate();
+ return false;
+ }
+
// 检查距离
if (!pawn.CanReach(mech, PathEndMode.Touch, Danger.Deadly))
{
@@ -207,7 +292,21 @@ namespace WulaFallenEmpire
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);
+ }
}
}
diff --git a/Source/WulaFallenEmpire/WulaDefOf.cs b/Source/WulaFallenEmpire/WulaDefOf.cs
index d98eeede..1b5149dc 100644
--- a/Source/WulaFallenEmpire/WulaDefOf.cs
+++ b/Source/WulaFallenEmpire/WulaDefOf.cs
@@ -31,7 +31,7 @@ namespace WulaFallenEmpire
public static JobDef WULA_ForceEjectPilot;
public static JobDef WULA_CarryToMech;
public static JobDef WULA_TransformPawn;
-
+ public static JobDef WULA_BoardMech;
static Wula_JobDefOf()
{
DefOfHelper.EnsureInitializedInCtor(typeof(Wula_JobDefOf));
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 681553e3..a0596e88 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -102,8 +102,11 @@
+
+
+
diff --git a/美术与文本源文件/Wula/UI/Commands/WULA_FlightToggle.sai2 b/美术与文本源文件/Wula/UI/Commands/WULA_FlightToggle.sai2
new file mode 100644
index 00000000..ad76a8a2
Binary files /dev/null and b/美术与文本源文件/Wula/UI/Commands/WULA_FlightToggle.sai2 differ