diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index a631c51..3f3203c 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Defs/Thing_building/ARA_WormholeDefs.xml b/1.6/1.6/Defs/Thing_building/ARA_WormholeDefs.xml
index b48046f..699bcd6 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_WormholeDefs.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_WormholeDefs.xml
@@ -23,7 +23,6 @@
Normal
Building
50
- 0.5
250
8000
@@ -61,6 +60,9 @@
false
+
+ Message_FleshbeastsDiscovered
+
@@ -90,6 +92,9 @@
None
+
+ Message_FleshbeastsDiscovered
+
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index c4d3371..9f760d3 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -209,7 +209,6 @@
-
diff --git a/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_A.cs b/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_A.cs
index a126ad8..a753ca8 100644
--- a/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_A.cs
+++ b/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_A.cs
@@ -11,7 +11,7 @@ namespace ArachnaeSwarm
Linked
}
- public class Building_WormholePortal_A : Building
+ public class Building_WormholePortal_A : MapPortal
{
private Building_WormholePortal_B linkedPortalB;
public WormholePortalStatus status = WormholePortalStatus.Idle;
@@ -32,6 +32,68 @@ namespace ArachnaeSwarm
base.SpawnSetup(map, respawningAfterLoad);
refuelableComp = GetComp();
}
+
+ // --- MapPortal Overrides ---
+
+ public override bool IsEnterable(out string reason)
+ {
+ if (status != WormholePortalStatus.Linked)
+ {
+ reason = "WormholeNotLinked".Translate();
+ return false;
+ }
+ if (linkedPortalB == null || linkedPortalB.Destroyed)
+ {
+ reason = "WormholeLinkLost".Translate();
+ Notify_B_Destroyed();
+ return false;
+ }
+ reason = "";
+ return true;
+ }
+
+ public override Map GetOtherMap()
+ {
+ return linkedPortalB?.Map;
+ }
+
+ public override IntVec3 GetDestinationLocation()
+ {
+ return linkedPortalB.Position;
+ }
+
+ public override void OnEntered(Pawn pawn)
+ {
+ // The base class handles adding the pawn to the container.
+ base.OnEntered(pawn);
+
+ // Now, transfer everything in the container to the destination.
+ if (linkedPortalB != null && !linkedPortalB.Destroyed)
+ {
+ // Transfer pawns first
+ List pawnsInPortal = new List();
+ foreach (Thing item in GetDirectlyHeldThings())
+ {
+ if (item is Pawn p)
+ {
+ pawnsInPortal.Add(p);
+ }
+ }
+
+ foreach(Pawn p in pawnsInPortal)
+ {
+ p.DeSpawn();
+ GenSpawn.Spawn(p, CellFinder.RandomClosewalkCellNear(linkedPortalB.Position, linkedPortalB.Map, 5), linkedPortalB.Map, WipeMode.Vanish);
+ GetDirectlyHeldThings().Remove(p);
+ }
+
+ // Transfer items
+ GetDirectlyHeldThings().TryDropAll(linkedPortalB.Position, linkedPortalB.Map, ThingPlaceMode.Near);
+ }
+
+ // Custom sound/effect can be played here.
+ EffecterDefOf.Skip_Exit.Spawn(pawn.Position, pawn.Map);
+ }
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
@@ -67,29 +129,11 @@ namespace ArachnaeSwarm
public override IEnumerable GetGizmos()
{
+ // Use the base (MapPortal) gizmos, which include "Enter" and "Cancel Load"
foreach (Gizmo g in base.GetGizmos())
{
yield return g;
}
-
- if (status == WormholePortalStatus.Linked)
- {
- if (linkedPortalB == null || linkedPortalB.Destroyed)
- {
- // 安全检查,处理幽灵链接
- Notify_B_Destroyed();
- yield break;
- }
-
- Command_Action enterCommand = new Command_Action
- {
- defaultLabel = "EnterWormhole".Translate(),
- defaultDesc = "EnterWormholeDesc".Translate(),
- icon = ContentFinder.Get("UI/Commands/EnterCave"),
- action = BeginTeleportation
- };
- yield return enterCommand;
- }
}
public override string GetInspectString()
@@ -103,9 +147,5 @@ namespace ArachnaeSwarm
return text;
}
- private void BeginTeleportation()
- {
- Find.WindowStack.Add(new Dialog_WormholeTransfer(this, this.LinkedPortal));
- }
}
}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_B.cs b/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_B.cs
index 841707d..7117118 100644
--- a/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_B.cs
+++ b/Source/ArachnaeSwarm/Wormhole/Building_WormholePortal_B.cs
@@ -1,10 +1,11 @@
+using RimWorld;
using RimWorld.Planet;
using System.Collections.Generic;
using Verse;
namespace ArachnaeSwarm
{
- public class Building_WormholePortal_B : Building
+ public class Building_WormholePortal_B : MapPortal
{
private Building_WormholePortal_A linkedPortalA;
@@ -41,22 +42,66 @@ namespace ArachnaeSwarm
public override IEnumerable GetGizmos()
{
+ // Use the base (MapPortal) gizmos
foreach (Gizmo g in base.GetGizmos())
{
yield return g;
}
-
+ }
+
+ // --- MapPortal Overrides ---
+
+ public override bool IsEnterable(out string reason)
+ {
+ if (linkedPortalA == null || linkedPortalA.Destroyed)
+ {
+ reason = "WormholeLinkLost".Translate();
+ if (linkedPortalA != null) linkedPortalA.Notify_B_Destroyed();
+ this.Destroy(DestroyMode.Vanish);
+ return false;
+ }
+ reason = "";
+ return true;
+ }
+
+ public override Map GetOtherMap()
+ {
+ return linkedPortalA?.Map;
+ }
+
+ public override IntVec3 GetDestinationLocation()
+ {
+ return linkedPortalA.Position;
+ }
+
+ public override void OnEntered(Pawn pawn)
+ {
+ base.OnEntered(pawn);
+
if (linkedPortalA != null && !linkedPortalA.Destroyed)
{
- Command_Action enterCommand = new Command_Action
+ // Transfer pawns first
+ List pawnsInPortal = new List();
+ foreach (Thing item in GetDirectlyHeldThings())
{
- defaultLabel = "EnterWormhole".Translate(),
- defaultDesc = "EnterWormholeDesc".Translate(),
- icon = ContentFinder.Get("UI/Commands/EnterCave"),
- action = BeginTeleportation
- };
- yield return enterCommand;
+ if (item is Pawn p)
+ {
+ pawnsInPortal.Add(p);
+ }
+ }
+
+ foreach(Pawn p in pawnsInPortal)
+ {
+ p.DeSpawn();
+ GenSpawn.Spawn(p, CellFinder.RandomClosewalkCellNear(linkedPortalA.Position, linkedPortalA.Map, 5), linkedPortalA.Map, WipeMode.Vanish);
+ GetDirectlyHeldThings().Remove(p);
+ }
+
+ // Transfer items
+ GetDirectlyHeldThings().TryDropAll(linkedPortalA.Position, linkedPortalA.Map, ThingPlaceMode.Near);
}
+
+ EffecterDefOf.Skip_Exit.Spawn(pawn.Position, pawn.Map);
}
public override string GetInspectString()
@@ -73,9 +118,5 @@ namespace ArachnaeSwarm
return text;
}
- private void BeginTeleportation()
- {
- Find.WindowStack.Add(new Dialog_WormholeTransfer(this, this.LinkedPortal));
- }
}
}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Wormhole/Dialog_WormholeTransfer.cs b/Source/ArachnaeSwarm/Wormhole/Dialog_WormholeTransfer.cs
deleted file mode 100644
index 1eeeba8..0000000
--- a/Source/ArachnaeSwarm/Wormhole/Dialog_WormholeTransfer.cs
+++ /dev/null
@@ -1,214 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using RimWorld;
-using RimWorld.Planet;
-using UnityEngine;
-using Verse;
-using Verse.Sound;
-
-namespace ArachnaeSwarm
-{
- public class Dialog_WormholeTransfer : Window
- {
- private enum Tab
- {
- Pawns,
- Items
- }
-
- private const float TitleRectHeight = 35f;
- private const float BottomAreaHeight = 55f;
- private readonly Vector2 BottomButtonSize = new Vector2(160f, 40f);
-
- private Building sourcePortal; // 通用源传送门
- private Building destinationPortal; // 通用目标传送门
-
- private List transferables;
- private TransferableOneWayWidget pawnsTransfer;
- private TransferableOneWayWidget itemsTransfer;
- private Tab tab;
-
- private static List tabsList = new List();
-
- public override Vector2 InitialSize => new Vector2(1024f, UI.screenHeight);
- protected override float Margin => 0f;
-
- public Dialog_WormholeTransfer(Building sourcePortal, Building destinationPortal)
- {
- this.sourcePortal = sourcePortal;
- this.destinationPortal = destinationPortal;
- forcePause = true;
- absorbInputAroundWindow = true;
- }
-
- public override void PostOpen()
- {
- base.PostOpen();
- CalculateAndRecacheTransferables();
- }
-
- public override void DoWindowContents(Rect inRect)
- {
- Rect rect = new Rect(0f, 0f, inRect.width, TitleRectHeight);
- Text.Font = GameFont.Medium;
- Text.Anchor = TextAnchor.MiddleCenter;
- Widgets.Label(rect, "EnterWormhole".Translate());
- Text.Font = GameFont.Small;
- Text.Anchor = TextAnchor.UpperLeft;
-
- tabsList.Clear();
- tabsList.Add(new TabRecord("PawnsTab".Translate(), () => tab = Tab.Pawns, tab == Tab.Pawns));
- tabsList.Add(new TabRecord("ItemsTab".Translate(), () => tab = Tab.Items, tab == Tab.Items));
-
- inRect.yMin += 67f;
- Widgets.DrawMenuSection(inRect);
- TabDrawer.DrawTabs(inRect, tabsList);
- inRect = inRect.ContractedBy(17f);
-
- Widgets.BeginGroup(inRect);
- Rect rect2 = inRect.AtZero();
- DoBottomButtons(rect2);
- Rect inRect2 = rect2;
- inRect2.yMax -= 76f;
-
- bool anythingChanged = false;
- switch (tab)
- {
- case Tab.Pawns:
- pawnsTransfer.OnGUI(inRect2, out anythingChanged);
- break;
- case Tab.Items:
- itemsTransfer.OnGUI(inRect2, out anythingChanged);
- break;
- }
- if (anythingChanged)
- {
- // 可以添加一些计数或质量更新的逻辑
- }
- Widgets.EndGroup();
- }
-
- private void DoBottomButtons(Rect rect)
- {
- float buttonY = rect.height - BottomAreaHeight + 17;
-
- if (Widgets.ButtonText(new Rect(rect.width / 2f - BottomButtonSize.x / 2f, buttonY, BottomButtonSize.x, BottomButtonSize.y), "ResetButton".Translate()))
- {
- SoundDefOf.Tick_Low.PlayOneShotOnCamera();
- CalculateAndRecacheTransferables();
- }
- if (Widgets.ButtonText(new Rect(0f, buttonY, BottomButtonSize.x, BottomButtonSize.y), "CancelButton".Translate()))
- {
- Close();
- }
- if (Widgets.ButtonText(new Rect(rect.width - BottomButtonSize.x, buttonY, BottomButtonSize.x, BottomButtonSize.y), "AcceptButton".Translate()))
- {
- if (TryAccept())
- {
- SoundDefOf.Tick_High.PlayOneShotOnCamera();
- Close(doCloseSound: false);
- }
- }
- }
-
- private bool TryAccept()
- {
- List toTransfer = transferables.Where(x => x.CountToTransfer > 0).ToList();
- if (!toTransfer.Any())
- {
- Messages.Message("NothingToTransfer".Translate(), MessageTypeDefOf.RejectInput);
- return false;
- }
-
- foreach (var trans in toTransfer)
- {
- // 传送逻辑
- var things = trans.things.Take(trans.CountToTransfer).ToList();
- foreach (var thing in things)
- {
- Pawn pawn = thing as Pawn;
- if (pawn != null)
- {
- pawn.DeSpawn();
- GenSpawn.Spawn(pawn, CellFinder.RandomClosewalkCellNear(destinationPortal.Position, destinationPortal.Map, 5), destinationPortal.Map, WipeMode.Vanish);
- }
- else
- {
- thing.DeSpawn();
- GenSpawn.Spawn(thing, CellFinder.RandomClosewalkCellNear(destinationPortal.Position, destinationPortal.Map, 5), destinationPortal.Map, WipeMode.Vanish);
- }
- }
- }
-
- // 切换视角
- if (toTransfer.Any(x => x.ThingDef.category == ThingCategory.Pawn))
- {
- var firstPawn = toTransfer.First(x => x.ThingDef.category == ThingCategory.Pawn).AnyThing as Pawn;
- CameraJumper.TryJump(new GlobalTargetInfo(destinationPortal.Position, destinationPortal.Map));
- if (firstPawn != null)
- {
- CameraJumper.TrySelect(firstPawn);
- }
- }
-
- Messages.Message("WormholeTransferComplete".Translate(), MessageTypeDefOf.PositiveEvent);
- return true;
- }
-
- private void CalculateAndRecacheTransferables()
- {
- transferables = new List();
- AddPawnsToTransferables();
- AddItemsToTransferables();
-
- pawnsTransfer = new TransferableOneWayWidget(transferables.Where(x => x.ThingDef.category == ThingCategory.Pawn), null, null, "TransferableCount".Translate(),
- drawMass: true,
- ignorePawnInventoryMass: IgnorePawnsInventoryMode.Ignore,
- includePawnsMassInMassUsage: true,
- availableMassGetter: () => float.MaxValue, // 无质量限制
- extraHeaderSpace: 0f,
- ignoreSpawnedCorpseGearAndInventoryMass: false,
- tile: sourcePortal.Map.Tile,
- drawMarketValue: true,
- drawEquippedWeapon: true);
-
- itemsTransfer = new TransferableOneWayWidget(transferables.Where(x => x.ThingDef.category != ThingCategory.Pawn), null, null, "TransferableCount".Translate(),
- drawMass: true,
- ignorePawnInventoryMass: IgnorePawnsInventoryMode.Ignore,
- includePawnsMassInMassUsage: true,
- availableMassGetter: () => float.MaxValue,
- extraHeaderSpace: 0f,
- ignoreSpawnedCorpseGearAndInventoryMass: false,
- tile: sourcePortal.Map.Tile,
- drawMarketValue: true);
- }
-
- private void AddToTransferables(Thing t)
- {
- var transferable = TransferableUtility.TransferableMatching(t, transferables, TransferAsOneMode.PodsOrCaravanPacking);
- if (transferable == null)
- {
- transferable = new TransferableOneWay();
- transferables.Add(transferable);
- }
- transferable.things.Add(t);
- }
-
- private void AddPawnsToTransferables()
- {
- foreach (Pawn p in sourcePortal.Map.mapPawns.AllPawnsSpawned.Where(p => p.Faction == Faction.OfPlayer))
- {
- AddToTransferables(p);
- }
- }
-
- private void AddItemsToTransferables()
- {
- foreach (Thing t in sourcePortal.Map.listerThings.AllThings.Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Position.IsValid && !t.Position.Fogged(t.Map)))
- {
- AddToTransferables(t);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/build.ps1 b/Source/ArachnaeSwarm/build.ps1
new file mode 100644
index 0000000..4fca6f6
--- /dev/null
+++ b/Source/ArachnaeSwarm/build.ps1
@@ -0,0 +1,38 @@
+# Find the latest installed .NET SDK and build the project.
+try {
+ Write-Host "Finding latest .NET SDK..."
+ $sdkList = dotnet --list-sdks
+ $latestSdk = $sdkList.Split([Environment]::NewLine) | Select-Object -Last 1
+
+ if ($null -eq $latestSdk -or $latestSdk -eq "") {
+ Write-Host "No .NET SDKs found. Please install the .NET SDK."
+ exit 1
+ }
+
+ $sdkVersion = ($latestSdk.Split(' '))[0]
+ Write-Host "Using .NET SDK version: $sdkVersion"
+
+ # Since the project is .NET Framework 4.8, msbuild is more suitable.
+ # We need to find msbuild.exe location.
+ # A common path for Visual Studio's MSBuild:
+ $vsWherePath = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
+ if(Test-Path $vsWherePath) {
+ $vsPath = & $vsWherePath -latest -property installationPath
+ $msBuildPath = Join-Path $vsPath "MSBuild\Current\Bin\MSBuild.exe"
+ if(Test-Path $msBuildPath) {
+ Write-Host "Found MSBuild at: $msBuildPath"
+ & $msBuildPath "ArachnaeSwarm.sln" /t:Rebuild /p:Configuration=Debug
+ } else {
+ Write-Host "MSBuild.exe not found at the expected path. Falling back to dotnet build."
+ dotnet build "ArachnaeSwarm.sln"
+ }
+ } else {
+ Write-Host "vswhere.exe not found. Falling back to dotnet build."
+ dotnet build "ArachnaeSwarm.sln"
+ }
+
+} catch {
+ Write-Host "An error occurred during the build process."
+ Write-Host $_
+ exit 1
+}