diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 5dd9f76f..4c0ec7b4 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs b/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs index dfc33ae7..a3cf1dbe 100644 --- a/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs +++ b/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs @@ -8,7 +8,7 @@ using UnityEngine; using Verse; using Verse.AI; using Verse.Sound; - +using WulaFallenEmpire; namespace WulaFallenEmpire { /// @@ -453,16 +453,12 @@ namespace WulaFallenEmpire /// protected virtual Map GeneratePocketMapInt() { - return PocketMapUtility.GeneratePocketMap(new IntVec3(pocketMapSize.x, 1, pocketMapSize.z), mapGenerator, GetExtraGenSteps(), this.Map); + return PocketMapUtility.GeneratePocketMap(new IntVec3(pocketMapSize.x, 1, pocketMapSize.z), mapGenerator, null, this.Map); } /// /// 获取额外的生成步骤(模仿 MapPortal.GetExtraGenSteps) /// - protected virtual IEnumerable GetExtraGenSteps() - { - return System.Linq.Enumerable.Empty(); - } /// /// 在口袋地图中创建退出点(模仿原版) @@ -512,7 +508,7 @@ namespace WulaFallenEmpire /// /// 将单个Pawn传送到口袋空间 /// - private bool TransferPawnToPocketSpace(Pawn pawn) + public bool TransferPawnToPocketSpace(Pawn pawn) { if (pawn == null || !pawn.Spawned || pocketMap == null) return false; @@ -803,49 +799,26 @@ namespace WulaFallenEmpire /// private void OpenPawnSelectionDialog() { - // 获取所有可用的殖民者 - List availablePawns = Map.mapPawns.AllPawnsSpawned - .Where(p => p.IsColonist && !p.Downed && p.CanReach(this, PathEndMode.Touch, Danger.Deadly)) - .ToList(); - - if (availablePawns.Count == 0) + if (!CanEnterPocketSpace()) { - Messages.Message("WULA.PocketSpace.NoPawnsAvailable".Translate(), this, MessageTypeDefOf.RejectInput); + Messages.Message("WULA.PocketSpace.CannotEnter".Translate(), this, MessageTypeDefOf.RejectInput); return; } - - // 创建选项列表 - List options = new List(); - - // 添加单个殖民者选项 - foreach (Pawn pawn in availablePawns) + + // 创建或获取口袋地图 + if (pocketMap == null && !pocketMapGenerated) { - FloatMenuOption option = new FloatMenuOption( - $"{pawn.LabelShort}", - delegate - { - EnterPocketSpace(new List { pawn }); - } - ); - options.Add(option); + CreatePocketMap(); } - - // 添加“全部殖民者”选项 - if (availablePawns.Count > 1) + + if (pocketMap == null) { - FloatMenuOption allOption = new FloatMenuOption( - "WULA.PocketSpace.AllColonists".Translate(availablePawns.Count), - delegate - { - EnterPocketSpace(availablePawns); - } - ); - options.Add(allOption); + Messages.Message("WULA.PocketSpace.CreationFailed".Translate(), this, MessageTypeDefOf.RejectInput); + return; } - - // 显示浮动菜单 - FloatMenu floatMenu = new FloatMenu(options); - Find.WindowStack.Add(floatMenu); + + // 打开新的穿梭机传输对话框 + Find.WindowStack.Add(new Dialog_ArmedShuttleTransfer(this)); } #endregion diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/Dialog_ArmedShuttleTransfer.cs b/Source/WulaFallenEmpire/WULA_Shuttle/Dialog_ArmedShuttleTransfer.cs new file mode 100644 index 00000000..dcfc8ec5 --- /dev/null +++ b/Source/WulaFallenEmpire/WULA_Shuttle/Dialog_ArmedShuttleTransfer.cs @@ -0,0 +1,266 @@ +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 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_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 pawnsToTransfer = TransferableUtility.GetPawnsFromTransferables(transferables); + List itemsToTransfer = new List(); + 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++; + } + } + + // 将物品添加到穿梭机的主容器 (CompTransporter.innerContainer) + CompTransporter transporter = shuttle.GetComp(); + if (transporter == null) + { + Log.Error("[WULA-ERROR] Dialog_ArmedShuttleTransfer: CompTransporter is missing on shuttle!"); + return false; + } + + int transferredItemCount = 0; + foreach (Thing item in itemsToTransfer) + { + // 从当前地图移除物品 + item.DeSpawn(); + + // 尝试添加到穿梭机主容器 + if (transporter.innerContainer.TryAdd(item)) + { + transferredItemCount++; + } + else + { + // 如果容器已满,尝试丢弃在穿梭机附近 + IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(shuttle.Position, shuttle.Map, 3); + if (dropPos.IsValid) + { + GenPlace.TryPlaceThing(item, dropPos, shuttle.Map, ThingPlaceMode.Near); + Messages.Message("容器已满:{0} 被放置在穿梭机附近".Translate(item.LabelShort), shuttle, MessageTypeDefOf.CautionInput); + } + else + { + Log.Error($"[WULA-ERROR] Could not find valid drop position for item {item.LabelShort}"); + // 实在没地方放,就让它消失吧,或者抛出异常 + 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(); + // 根据需要添加现有物品到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); + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index ebb33551..c3516ee6 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -171,6 +171,7 @@ +