This commit is contained in:
2025-09-21 14:54:33 +08:00
parent 6000bb58f6
commit 182cb72cb0
8 changed files with 44 additions and 92 deletions

Binary file not shown.

View File

@@ -210,9 +210,6 @@
<Compile Include="Wormhole\Building_WormholePortal_B.cs" />
<Compile Include="Wormhole\CompLaunchableWormhole.cs" />
<Compile Include="Wormhole\Dialog_WormholeTransfer.cs" />
<Compile Include="HarmonyPatches\Patch_Site_ShouldRemoveMapNow.cs" />
<Compile Include="HarmonyPatches\Patch_SettlementDefeatUtility_CheckDefeated.cs" />
<Compile Include="HarmonyPatches\Patch_Game_DeinitAndRemoveMap.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 自定义清理任务删除obj文件夹中的临时文件 -->

View File

@@ -1,23 +0,0 @@
using HarmonyLib;
using Verse;
using System.Linq;
namespace ArachnaeSwarm
{
[HarmonyPatch(typeof(Game), "DeinitAndRemoveMap")]
public static class Patch_Game_DeinitAndRemoveMap
{
[HarmonyPrefix]
public static bool Prefix(Map map)
{
// 如果地图上存在B端传送门则阻止该地图被销毁
if (map != null && map.listerBuildings.AllBuildingsColonistOfClass<Building_WormholePortal_B>().Any())
{
return false; // 返回 false, 阻止原版方法执行
}
// 否则,正常执行原版方法
return true;
}
}
}

View File

@@ -1,25 +0,0 @@
using HarmonyLib;
using RimWorld;
using RimWorld.Planet;
using Verse;
using System.Linq;
namespace ArachnaeSwarm
{
[HarmonyPatch(typeof(SettlementDefeatUtility), "CheckDefeated")]
public static class Patch_SettlementDefeatUtility_CheckDefeated
{
[HarmonyPrefix]
public static bool Prefix(Settlement factionBase)
{
// 如果目标没有地图或者地图上存在B端传送门则跳过原版的失败检查
if (!factionBase.HasMap || factionBase.Map.listerBuildings.AllBuildingsColonistOfClass<Building_WormholePortal_B>().Any())
{
return false; // 返回 false, 阻止原版方法执行
}
// 否则,正常执行原版方法
return true;
}
}
}

View File

@@ -1,27 +0,0 @@
using HarmonyLib;
using RimWorld.Planet;
using Verse;
using System.Linq;
namespace ArachnaeSwarm
{
[HarmonyPatch(typeof(Site), "ShouldRemoveMapNow")]
public static class Patch_Site_ShouldRemoveMapNow
{
[HarmonyPostfix]
public static void Postfix(MapParent __instance, ref bool __result)
{
// 如果原方法已经决定不移除,我们就不需要干预
if (!__result)
{
return;
}
// 如果地图上存在B端传送门则推翻原方法的决定阻止地图被移除
if (__instance.HasMap && __instance.Map.listerBuildings.AllBuildingsColonistOfClass<Building_WormholePortal_B>().Any())
{
__result = false;
}
}
}
}

View File

@@ -35,6 +35,7 @@ namespace ArachnaeSwarm
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
Log.Message($"[ArachnaeSwarm] Portal A ({this.GetUniqueLoadID()}) is despawning. Notifying and destroying Portal B ({linkedPortalB?.GetUniqueLoadID() ?? "null"}).");
if (linkedPortalB != null && !linkedPortalB.Destroyed)
{
linkedPortalB.Notify_A_Destroyed();
@@ -50,6 +51,7 @@ namespace ArachnaeSwarm
Notify_B_Destroyed();
return;
}
Log.Message($"[ArachnaeSwarm] Portal A ({this.GetUniqueLoadID()}) is linking to Portal B ({portalB?.GetUniqueLoadID() ?? "null"}).");
linkedPortalB = portalB;
status = WormholePortalStatus.Linked;
Messages.Message("WormholePortalLinked".Translate(this.Label, portalB.Map.Parent.LabelCap), this, MessageTypeDefOf.PositiveEvent);
@@ -57,6 +59,7 @@ namespace ArachnaeSwarm
public void Notify_B_Destroyed()
{
Log.Warning($"[ArachnaeSwarm] Portal A ({this.GetUniqueLoadID()}) received notification that Portal B was destroyed. Resetting status to Idle.");
linkedPortalB = null;
status = WormholePortalStatus.Idle;
Messages.Message("WormholePortalB_Destroyed".Translate(this.Label), this, MessageTypeDefOf.NegativeEvent);

View File

@@ -19,6 +19,7 @@ namespace ArachnaeSwarm
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
// 如果B被摧毁通知A
Log.Warning($"[ArachnaeSwarm] Portal B ({this.GetUniqueLoadID()}) is despawning. Notifying Portal A ({linkedPortalA?.GetUniqueLoadID() ?? "null"}).");
if (linkedPortalA != null && !linkedPortalA.Destroyed)
{
linkedPortalA.Notify_B_Destroyed();
@@ -34,6 +35,7 @@ namespace ArachnaeSwarm
public void SetLinkedPortal(Building_WormholePortal_A portalA)
{
Log.Message($"[ArachnaeSwarm] Portal B ({this.GetUniqueLoadID()}) is linking to Portal A ({portalA?.GetUniqueLoadID() ?? "null"}).");
linkedPortalA = portalA;
}

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using Verse;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
@@ -27,8 +27,8 @@ namespace ArachnaeSwarm
}
Command_Action launchCommand = new Command_Action();
launchCommand.defaultLabel = "CommandDeployWormholePortalB".Translate();
launchCommand.defaultDesc = "CommandDeployWormholePortalBDesc".Translate();
launchCommand.defaultLabel = "CommandDeployWormholePortalB_Pilot".Translate();
launchCommand.defaultDesc = "CommandDeployWormholePortalB_PilotDesc".Translate();
launchCommand.icon = ContentFinder<Texture2D>.Get("UI/Commands/LaunchShip");
if (refuelableComp.Fuel < this.Props.fuelNeededToLaunch)
@@ -38,23 +38,42 @@ namespace ArachnaeSwarm
launchCommand.action = delegate
{
StartChoosingDestination();
var targetingParameters = new TargetingParameters
{
canTargetPawns = true,
canTargetBuildings = false,
mapObjectTargetsMustBeAutoAttackable = false,
validator = (TargetInfo target) =>
{
if (!target.HasThing) return false;
Pawn p = target.Thing as Pawn;
return p != null && p.IsColonistPlayerControlled && !p.Downed && !p.IsBurning();
}
};
Find.Targeter.BeginTargeting(targetingParameters, (LocalTargetInfo target) =>
{
Pawn pilot = target.Pawn;
if (pilot != null)
{
StartChoosingDestination(pilot);
}
});
};
yield return launchCommand;
}
public void StartChoosingDestination()
public void StartChoosingDestination(Pawn pilot)
{
CameraJumper.TryJump(CameraJumper.GetWorldTarget(this.parent));
Find.WorldSelector.ClearSelection();
int tile = this.parent.Map.Tile;
Find.WorldTargeter.BeginTargeting(ChoseWorldTarget, true, CompLaunchable.TargeterMouseAttachment, true, delegate
Find.WorldTargeter.BeginTargeting((GlobalTargetInfo t) => ChoseWorldTarget(t, pilot), true, CompLaunchable.TargeterMouseAttachment, true, delegate
{
GenDraw.DrawWorldRadiusRing(tile, this.Props.maxLaunchDistance);
}, (GlobalTargetInfo t) => "Select target tile");
}
private bool ChoseWorldTarget(GlobalTargetInfo t)
private bool ChoseWorldTarget(GlobalTargetInfo t, Pawn pilot)
{
if (!t.IsValid)
{
@@ -70,33 +89,39 @@ namespace ArachnaeSwarm
MapParent mapParent = Find.World.worldObjects.MapParentAt(t.Tile);
if (mapParent?.HasMap ?? false)
{
Deploy(mapParent, t);
Deploy(mapParent, pilot);
}
else
{
LongEventHandler.QueueLongEvent(delegate
{
var newMap = GetOrGenerateMapUtility.GetOrGenerateMap(t.Tile, WorldObjectDefOf.Camp);
Deploy(newMap.Parent, t);
Deploy(newMap.Parent, pilot);
}, "GeneratingMap", doAsynchronously: false, null);
}
return true;
}
private void Deploy(MapParent mapParent, GlobalTargetInfo t)
private void Deploy(MapParent mapParent, Pawn pilot)
{
refuelableComp.ConsumeFuel(this.Props.fuelNeededToLaunch);
// 传送驾驶员
pilot.DeSpawn();
EffecterDefOf.Skip_Entry.Spawn(this.parent.Position, this.parent.Map);
Building_WormholePortal_B portalB = (Building_WormholePortal_B)ThingMaker.MakeThing(ThingDef.Named("ARA_WormholePortal_B"));
IntVec3 cell = DropCellFinder.RandomDropSpot(mapParent.Map);
GenSpawn.Spawn(portalB, cell, mapParent.Map, WipeMode.Vanish);
EffecterDefOf.Skip_Exit.Spawn(cell, mapParent.Map);
// 在B端生成驾驶员
IntVec3 pilotSpawnCell = CellFinder.RandomSpawnCellForPawnNear(portalB.Position, mapParent.Map, 5);
GenSpawn.Spawn(pilot, pilotSpawnCell, mapParent.Map, WipeMode.Vanish);
EffecterDefOf.Skip_Exit.Spawn(cell, mapParent.Map);
PortalA.SetLinkedPortal(portalB);
portalB.SetLinkedPortal(PortalA);
}