Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/ThingComp/WULA_Shuttle/Dialog_ArmedShuttleTransfer.cs
2025-10-31 09:57:45 +08:00

250 lines
9.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;
using Verse.Sound;
namespace WulaFallenEmpire
{
public class Dialog_ArmedShuttleTransfer : 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_ArmedShuttleWithPocket shuttle;
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_ArmedShuttleTransfer(Building_ArmedShuttleWithPocket shuttle)
{
this.shuttle = shuttle;
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);
using (new TextBlock(GameFont.Medium, TextAnchor.MiddleCenter))
{
Widgets.Label(rect, shuttle.EnterString);
}
tabsList.Clear();
tabsList.Add(new TabRecord("PawnsTab".Translate(), delegate
{
tab = Tab.Pawns;
}, tab == Tab.Pawns));
tabsList.Add(new TabRecord("ItemsTab".Translate(), delegate
{
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;
}
Widgets.EndGroup();
}
private void DoBottomButtons(Rect rect)
{
float buttonY = rect.height - BottomAreaHeight - 17f;
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()) && TryAccept())
{
SoundDefOf.Tick_High.PlayOneShotOnCamera();
Close(doCloseSound: false);
}
}
private bool TryAccept()
{
// 获取选中的Pawn和物品
List<Pawn> pawnsToTransfer = TransferableUtility.GetPawnsFromTransferables(transferables);
List<Thing> itemsToTransfer = new List<Thing>();
foreach (TransferableOneWay transferable in transferables)
{
if (transferable.ThingDef.category != ThingCategory.Pawn)
{
itemsToTransfer.AddRange(transferable.things.Take(transferable.CountToTransfer));
}
}
// 传送Pawn到口袋空间
int transferredPawnCount = 0;
foreach (Pawn pawn in pawnsToTransfer)
{
if (shuttle.TransferPawnToPocketSpace(pawn))
{
transferredPawnCount++;
}
}
int transferredItemCount = 0;
foreach (Thing item in itemsToTransfer)
{
// 从当前地图移除物品
item.DeSpawn();
// 尝试放置到口袋空间地上
IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(shuttle.PocketMap.Center, shuttle.PocketMap, 5); // 随机位置,避免重叠
if (dropPos.IsValid)
{
GenPlace.TryPlaceThing(item, dropPos, shuttle.PocketMap, ThingPlaceMode.Near);
transferredItemCount++;
}
else
{
Log.Error($"[WULA-ERROR] Could not find valid drop position for item {item.LabelShort} in pocket map.");
item.Destroy(); // 实在没地方放,就销毁
}
}
if (transferredPawnCount > 0 || transferredItemCount > 0)
{
Messages.Message("WULA.PocketSpace.TransferSuccess".Translate(transferredPawnCount + transferredItemCount), MessageTypeDefOf.PositiveEvent);
// 切换到口袋地图视角如果传送了Pawn
if (transferredPawnCount > 0)
{
Current.Game.CurrentMap = shuttle.PocketMap;
Find.CameraDriver.JumpToCurrentMapLoc(shuttle.PocketMap.Center);
}
}
else
{
Messages.Message("WULA.PocketSpace.NoPawnsOrItemsSelected".Translate(), MessageTypeDefOf.RejectInput);
return false;
}
return true;
}
private void CalculateAndRecacheTransferables()
{
transferables = new List<TransferableOneWay>();
// 根据需要添加现有物品到transferables如果穿梭机已有物品
// 目前我们从头开始构建列表只添加地图上的物品和Pawn
AddPawnsToTransferables();
AddItemsToTransferables();
// 重新创建TransferableOneWayWidget实例
pawnsTransfer = new TransferableOneWayWidget(null, null, null, "TransferMapPortalColonyThingCountTip".Translate(),
drawMass: true,
ignorePawnInventoryMass: IgnorePawnsInventoryMode.IgnoreIfAssignedToUnload,
includePawnsMassInMassUsage: true,
availableMassGetter: () => float.MaxValue,
extraHeaderSpace: 0f,
ignoreSpawnedCorpseGearAndInventoryMass: false,
tile: shuttle.Map.Tile,
drawMarketValue: false,
drawEquippedWeapon: true);
CaravanUIUtility.AddPawnsSections(pawnsTransfer, transferables);
itemsTransfer = new TransferableOneWayWidget(transferables.Where(x => x.ThingDef.category != ThingCategory.Pawn), null, null, "TransferMapPortalColonyThingCountTip".Translate(),
drawMass: true,
ignorePawnInventoryMass: IgnorePawnsInventoryMode.IgnoreIfAssignedToUnload,
includePawnsMassInMassUsage: true,
availableMassGetter: () => float.MaxValue,
extraHeaderSpace: 0f,
ignoreSpawnedCorpseGearAndInventoryMass: false,
tile: shuttle.Map.Tile);
}
private void AddToTransferables(Thing t)
{
TransferableOneWay transferableOneWay = TransferableUtility.TransferableMatching(t, transferables, TransferAsOneMode.PodsOrCaravanPacking);
if (transferableOneWay == null)
{
transferableOneWay = new TransferableOneWay();
transferables.Add(transferableOneWay);
}
if (transferableOneWay.things.Contains(t))
{
Log.Error("Tried to add the same thing twice to TransferableOneWay: " + t);
}
else
{
transferableOneWay.things.Add(t);
}
}
private void AddPawnsToTransferables()
{
foreach (Pawn item in CaravanFormingUtility.AllSendablePawns(shuttle.Map, allowEvenIfDowned: true, allowEvenIfInMentalState: false, allowEvenIfPrisonerNotSecure: false, allowCapturableDownedPawns: false, allowLodgers: true))
{
AddToTransferables(item);
}
}
private void AddItemsToTransferables()
{
// 考虑是否需要处理口袋地图中的物品
bool isPocketMap = shuttle.Map.IsPocketMap;
foreach (Thing item in CaravanFormingUtility.AllReachableColonyItems(shuttle.Map, isPocketMap, isPocketMap))
{
AddToTransferables(item);
}
}
public override void OnAcceptKeyPressed()
{
if (TryAccept())
{
SoundDefOf.Tick_High.PlayOneShotOnCamera();
Close(doCloseSound: false);
}
}
}
}