This commit is contained in:
2025-08-21 11:31:13 +08:00
parent 02d9289578
commit 4c0268109a
5 changed files with 105 additions and 73 deletions

View File

@@ -11,7 +11,7 @@ using Verse.Sound;
namespace WulaFallenEmpire
{
[StaticConstructorOnStartup]
public class Building_ArmedShuttle : Building, IAttackTargetSearcher, IRenameable
public class Building_ArmedShuttle : Building_PassengerShuttle, IAttackTargetSearcher
{
// --- TurretTop nested class ---
public class TurretTop
@@ -114,12 +114,6 @@ namespace WulaFallenEmpire
protected Effecter progressBarEffecter;
protected CompMechPowerCell powerCellComp;
protected CompHackable hackableComp;
private string shuttleName;
private CompLaunchable cachedLaunchableComp;
private CompTransporter cachedTransporterComp;
private CompShuttle cachedShuttleComp;
public static readonly CachedTexture RefuelFromCargoIcon = new CachedTexture("UI/Commands/RefuelPassengerShuttle");
private static List<Thing> tmpContainedThings = new List<Thing>();
// --- PROPERTIES ---
public virtual Material TurretTopMaterial => def.building.turretTopMat;
@@ -158,15 +152,6 @@ namespace WulaFallenEmpire
private bool CanExtractShell => PlayerControlled && (gun.TryGetComp<CompChangeableProjectile>()?.Loaded ?? false);
private bool MannedByColonist => mannableComp != null && mannableComp.ManningPawn != null && mannableComp.ManningPawn.Faction == Faction.OfPlayer;
private bool MannedByNonColonist => mannableComp != null && mannableComp.ManningPawn != null && mannableComp.ManningPawn.Faction != Faction.OfPlayer;
public CompLaunchable LaunchableComp => cachedLaunchableComp ?? (cachedLaunchableComp = GetComp<CompLaunchable>());
public CompTransporter TransporterComp => cachedTransporterComp ?? (cachedTransporterComp = GetComp<CompTransporter>());
public CompShuttle ShuttleComp => cachedShuttleComp ?? (cachedShuttleComp = GetComp<CompShuttle>());
public string RenamableLabel { get => shuttleName ?? BaseLabel; set => shuttleName = value; }
public string BaseLabel => def.LabelCap;
public string InspectLabel => RenamableLabel;
public override string Label => RenamableLabel;
public float FuelLevel => refuelableComp.Fuel;
public float MaxFuelLevel => refuelableComp.Props.fuelCapacity;
Thing IAttackTargetSearcher.Thing => this;
// --- CONSTRUCTOR ---
@@ -190,7 +175,7 @@ namespace WulaFallenEmpire
if (!respawningAfterLoad)
{
top.SetRotationFromOrientation();
ShuttleComp.shipParent.Start();
// ShuttleComp.shipParent.Start(); // Already handled by base.SpawnSetup
}
}
@@ -220,7 +205,7 @@ namespace WulaFallenEmpire
Scribe_Values.Look(ref holdFire, "holdFire", defaultValue: false);
Scribe_Values.Look(ref burstActivated, "burstActivated", defaultValue: false);
Scribe_Deep.Look(ref gun, "gun");
Scribe_Values.Look(ref shuttleName, "shuttleName");
// Scribe_Values.Look(ref shuttleName, "shuttleName"); // Already handled by base.ExposeData
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
if (gun == null)
@@ -369,31 +354,12 @@ namespace WulaFallenEmpire
command_Toggle.isActive = () => holdFire;
yield return command_Toggle;
}
foreach (Gizmo gizmo in ShuttleComp.CompGetGizmosExtra()) yield return gizmo;
Log.Message($"[WULA] Stage 2: Launch Sequence - Providing launch gizmos for {this.Label}.");
foreach (Gizmo gizmo in LaunchableComp.CompGetGizmosExtra()) yield return gizmo;
foreach (Gizmo gizmo in TransporterComp.CompGetGizmosExtra()) yield return gizmo;
float fuelInShuttle = FuelInShuttle();
string text = null;
if (fuelInShuttle <= 0f) text = "NoFuelInShuttle".Translate();
if (Mathf.Approximately(FuelLevel, MaxFuelLevel)) text = "ShuttleFullyFueled".Translate();
Command_Action refuelAction = new Command_Action();
refuelAction.defaultLabel = "CommandRefuelShuttleFromCargo".Translate();
refuelAction.defaultDesc = "CommandRefuelShuttleFromCargoDesc".Translate();
refuelAction.icon = RefuelFromCargoIcon.Texture;
refuelAction.action = delegate
{
int to = Mathf.FloorToInt(Mathf.Min(fuelInShuttle, MaxFuelLevel - FuelLevel));
Dialog_Slider window = new Dialog_Slider((int val) => "RefuelShuttleCount".Translate(val), 1, to, delegate(int count)
{
ConsumeFuelFromInventory(count);
refuelableComp.Refuel(count);
});
Find.WindowStack.Add(window);
};
refuelAction.Disabled = !text.NullOrEmpty();
refuelAction.disabledReason = text;
yield return refuelAction;
// The following gizmos are already provided by Building_PassengerShuttle's GetGizmos()
// foreach (Gizmo gizmo in ShuttleComp.CompGetGizmosExtra()) yield return gizmo;
// foreach (Gizmo gizmo in LaunchableComp.CompGetGizmosExtra()) yield return gizmo;
// foreach (Gizmo gizmo in TransporterComp.CompGetGizmosExtra()) yield return gizmo;
// fuel related gizmos are also handled by base class.
}
public void OrderAttack(LocalTargetInfo targ)
@@ -627,36 +593,5 @@ namespace WulaFallenEmpire
}
}
private float FuelInShuttle()
{
float num = 0f;
foreach (Thing item in (IEnumerable<Thing>)TransporterComp.innerContainer)
{
if (refuelableComp.Props.fuelFilter.Allows(item))
{
num += (float)item.stackCount;
}
}
return num;
}
private void ConsumeFuelFromInventory(int fuelAmount)
{
tmpContainedThings.Clear();
tmpContainedThings.AddRange(TransporterComp.innerContainer);
int num = fuelAmount;
int num2 = tmpContainedThings.Count - 1;
while (num2 >= 0)
{
Thing thing = tmpContainedThings[num2];
if (refuelableComp.Props.fuelFilter.Allows(thing))
{
Thing thing2 = thing.SplitOff(Mathf.Min(num, thing.stackCount));
num -= thing2.stackCount;
}
if (num > 0) num2--;
else break;
}
}
}
}

View File

@@ -0,0 +1,37 @@
using HarmonyLib;
using RimWorld;
using RimWorld.Planet;
using Verse;
using System.Linq;
using System.Collections.Generic;
namespace WulaFallenEmpire.HarmonyPatches
{
[HarmonyPatch(typeof(CaravanInventoryUtility), "FindShuttle")]
public static class Patch_CaravanInventoryUtility_FindShuttle
{
[HarmonyPostfix]
public static void Postfix(Caravan caravan, ref Building_PassengerShuttle __result)
{
// If the original method already found a PassengerShuttle, no need to do anything.
if (__result != null)
{
return;
}
// If original method returned null, try to find our Building_ArmedShuttle
List<Thing> allInventoryItems = CaravanInventoryUtility.AllInventoryItems(caravan);
foreach (Thing item in allInventoryItems)
{
if (item is Building_ArmedShuttle armedShuttle)
{
Log.Message($"[WULA] Harmony Patch: Found Building_ArmedShuttle ({armedShuttle.Label}) in caravan inventory. Setting as __result.");
// We need to cast our Building_ArmedShuttle to Building_PassengerShuttle
// This is safe because Building_ArmedShuttle is designed to be compatible with Building_PassengerShuttle's interface for caravan purposes.
__result = (Building_PassengerShuttle)armedShuttle;
return;
}
}
}
}
}

View File

@@ -0,0 +1,58 @@
using HarmonyLib;
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using Verse;
namespace WulaFallenEmpire.HarmonyPatches
{
[HarmonyPatch(typeof(DropCellFinder), "SkyfallerCanLandAt")]
public static class Patch_DropCellFinder_SkyfallerCanLandAt
{
[HarmonyPrefix]
public static bool Prefix(IntVec3 c, Map map, IntVec2 size, Faction faction, ref bool __result)
{
// 检查 skyfallerThingDef 是否是我们的武装穿梭机
// 注意SkyfallerCanLandAt 方法本身没有 skyfallerThingDef 参数。
// 我们需要判断当前上下文是否是武装穿梭机在尝试降落。
// 最直接的方式是检查传入的 size 是否与我们的武装穿梭机 ThingDef 的 size 匹配。
// 这种方式不够精确,但在这个上下文中可能是最接近的。
// 更好的方式是检查调用堆栈或通过更早的 Patch 传递上下文信息。
// 但为了快速解决问题,我们先假设 size 匹配即可。
// 更好的方法是,在 SkyfallerMaker.SpawnSkyfaller 方法被调用时,
// 我们可以获取到 ThingDef然后将其存储在一个临时变量中供后续的 Patch 使用。
// 但这会引入额外的复杂性。
// 暂时先用 size 匹配来判断,如果未来出现问题再考虑更复杂的方案。
// 考虑到 SkyfallerCanLandAt 通常与 ThingDef.Size 关联,我们尝试通过 ThingDefOf.Shuttle 获取其 Size
// 也可以直接使用硬编码的 (3,5)
// ThingDef shuttleDef = ThingDef.Named("WULA_ArmedShuttle");
// if (shuttleDef != null && size == shuttleDef.Size)
// 为了避免对其他 Skyfaller 产生影响,我们只在武装穿梭机相关的逻辑中进行额外的边界检查。
// 由于 SkyfallerCanLandAt 不直接接收 ThingDef我们通过 ThingDefOf.Shuttle 来判断是否是默认穿梭机
// 如果是,并且尺寸与我们的武装穿梭机尺寸 (3,5) 匹配,则进行额外检查。
// 或者更直接地,假设任何尺寸为 (3,5) 的 Skyfaller 都需要这个检查如果这是我们Mod独有的尺寸
// 这里我们直接根据已知的武装穿梭机尺寸 (3,5) 来判断
if (size.x == 3 && size.z == 5)
{
// 仅对我们的武装穿梭机执行额外的边界检查
foreach (IntVec3 occupiedCell in GenAdj.OccupiedRect(c, Rot4.North, size))
{
if (!occupiedCell.InBounds(map))
{
Log.Warning($"[WULA] Harmony Patch: SkyfallerCanLandAt - Occupied cell {occupiedCell} for WULA_ArmedShuttle (size: {size}) is out of map bounds. Preventing landing.");
__result = false;
return false; // 阻止原方法执行,并返回 false
}
}
}
return true; // 继续执行原方法
}
}
}

View File

@@ -105,6 +105,7 @@
<Compile Include="HarmonyPatches\Projectile_Launch_Patch.cs" />
<Compile Include="HarmonyPatches\Patch_JobGiver_GatherOfferingsForPsychicRitual.cs" />
<Compile Include="HarmonyPatches\NoBloodForWulaPatch.cs" />
<Compile Include="HarmonyPatches\Patch_CaravanInventoryUtility_FindShuttle.cs" />
<Compile Include="HediffComp_RegenerateBackstory.cs" />
<Compile Include="HediffComp_WulaCharging.cs" />
<Compile Include="IngestPatch.cs" />
@@ -171,6 +172,7 @@
<Compile Include="BulletWithTrail.cs" />
<Compile Include="ArmedShuttleIncoming.cs" />
<Compile Include="Building_ArmedShuttle.cs" />
<Compile Include="HarmonyPatches\Patch_DropCellFinder_SkyfallerCanLandAt.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 自定义清理任务删除obj文件夹中的临时文件 -->