暂存
This commit is contained in:
Binary file not shown.
@@ -23,7 +23,6 @@
|
||||
<tickerType>Normal</tickerType>
|
||||
<category>Building</category>
|
||||
<pathCost>50</pathCost>
|
||||
<fillPercent>0.5</fillPercent>
|
||||
<statBases>
|
||||
<MaxHitPoints>250</MaxHitPoints>
|
||||
<WorkToBuild>8000</WorkToBuild>
|
||||
@@ -61,6 +60,9 @@
|
||||
<building>
|
||||
<ai_chillDestination>false</ai_chillDestination>
|
||||
</building>
|
||||
<portal>
|
||||
<traverseSound>Message_FleshbeastsDiscovered</traverseSound>
|
||||
</portal>
|
||||
</ThingDef>
|
||||
|
||||
<!-- ==================== B端传送门 ==================== -->
|
||||
@@ -90,6 +92,9 @@
|
||||
<li Class="CompProperties_Flickable"/>
|
||||
</comps>
|
||||
<tradeability>None</tradeability>
|
||||
<portal>
|
||||
<traverseSound>Message_FleshbeastsDiscovered</traverseSound>
|
||||
</portal>
|
||||
</ThingDef>
|
||||
|
||||
<!-- CompProperties for our custom launchable -->
|
||||
|
||||
@@ -209,7 +209,6 @@
|
||||
<Compile Include="Wormhole\Building_WormholePortal_A.cs" />
|
||||
<Compile Include="Wormhole\Building_WormholePortal_B.cs" />
|
||||
<Compile Include="Wormhole\CompLaunchableWormhole.cs" />
|
||||
<Compile Include="Wormhole\Dialog_WormholeTransfer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 自定义清理任务,删除obj文件夹中的临时文件 -->
|
||||
|
||||
@@ -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<CompRefuelable>();
|
||||
}
|
||||
|
||||
// --- 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<Pawn> pawnsInPortal = new List<Pawn>();
|
||||
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<Gizmo> 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<UnityEngine.Texture2D>.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Gizmo> 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<Pawn> pawnsInPortal = new List<Pawn>();
|
||||
foreach (Thing item in GetDirectlyHeldThings())
|
||||
{
|
||||
defaultLabel = "EnterWormhole".Translate(),
|
||||
defaultDesc = "EnterWormholeDesc".Translate(),
|
||||
icon = ContentFinder<UnityEngine.Texture2D>.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<TransferableOneWay> transferables;
|
||||
private TransferableOneWayWidget pawnsTransfer;
|
||||
private TransferableOneWayWidget itemsTransfer;
|
||||
private Tab tab;
|
||||
|
||||
private static List<TabRecord> tabsList = new List<TabRecord>();
|
||||
|
||||
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<TransferableOneWay> 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<TransferableOneWay>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Source/ArachnaeSwarm/build.ps1
Normal file
38
Source/ArachnaeSwarm/build.ps1
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user