diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 95a68173..f21d300e 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml index 04ae65f4..ccf8586f 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Misc_Buildings.xml @@ -5,7 +5,7 @@ WULA_AreaTeleportBeacon 负责协调殖民地与轨道上的乌拉帝国舰队进行材料输送的信标,空投建筑会优先从信标覆盖区域吸纳资源完成空投。 - Building_OrbitalTradeBeacon + Building
  • BuildingsMisc
  • @@ -32,12 +32,13 @@ 40 1 + Normal BuildingDestroyed_Metal_Small
  • - 7 + (13, 13) 120 WULA_Colony_License_LV1_Technology
  • @@ -1029,4 +1030,6 @@
    + + \ No newline at end of file diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Prefab_Beacons.xml b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Prefab_Beacons.xml index 84b81cea..e4eb405d 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Prefab_Beacons.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/WULA_Prefab_Beacons.xml @@ -1,5 +1,27 @@ + + + WULA_TeleportLandingMarker + + 用于标记传送降落位置。 + WulaFallenEmpire.WULA_TeleportLandingMarker + + Wula/Building/WULA_Dropping_Building_Cleanzone_Plus + Graphic_Multi + (13,13) + + false + + + Building + false + true + true + RealtimeOnly + true + + WULA_Prefab_Cleanzone_NewColonyBase_Beacon diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml index e369a522..c4ce1f45 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml @@ -113,5 +113,33 @@ 请先选择一个分类 正在收集材料 已暂停 + + 取消传送 + 取消当前的传送预热。 + 启动传送 + 启动区域传送程序,将信标周围的物体传送到指定位置。 + 需要研究:{0} + 缺少必要的研究:{0} + 无法生成目标地图。 + 传送预热已开始。 + 传送已取消。 + 无效的目标位置。 + 无法获取目标地图。 + 传送成功。 + 选择降落点 + 选择传送到达的具体位置。 + 超出地图边界。 + 位于不可建造区域。 + 目标位置被迷雾覆盖。 + 被不可破坏的物体阻挡:{0} + 目标地形不可通过。 + 被厚岩顶阻挡。 + 必须选择一个降落点。 + 确认传送 + 确认当前位置并开始传送。 + 移动标记 + 重新选择降落位置。 + 由于传送取消,生成的临时地图已被清理。 + 燃料不足。 \ No newline at end of file diff --git a/Source/WulaFallenEmpire/3516260226.code-workspace b/Source/WulaFallenEmpire/3516260226.code-workspace index a2433624..aef43a98 100644 --- a/Source/WulaFallenEmpire/3516260226.code-workspace +++ b/Source/WulaFallenEmpire/3516260226.code-workspace @@ -13,6 +13,7 @@ "path": "../../../../Data" }, { + "name": "dll1.6", "path": "../../../../dll1.6" } ], diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompMapTeleporter.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompMapTeleporter.cs index e4484265..9d47fb02 100644 --- a/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompMapTeleporter.cs +++ b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompMapTeleporter.cs @@ -17,6 +17,7 @@ namespace WulaFallenEmpire private bool isWarmingUp = false; private int warmupTicksLeft = 0; private GlobalTargetInfo target; + private WULA_TeleportLandingMarker activeMarker; public override void PostExposeData() { @@ -24,6 +25,13 @@ namespace WulaFallenEmpire Scribe_Values.Look(ref isWarmingUp, "isWarmingUp", false); Scribe_Values.Look(ref warmupTicksLeft, "warmupTicksLeft", 0); Scribe_TargetInfo.Look(ref target, "target"); + Scribe_References.Look(ref activeMarker, "activeMarker"); + } + + public override void PostDrawExtraSelectionOverlays() + { + base.PostDrawExtraSelectionOverlays(); + GenDraw.DrawFieldEdges(CellRect.CenteredOn(parent.Position, Props.areaSize.x, Props.areaSize.z).Cells.ToList()); } public override void CompTick() @@ -32,15 +40,18 @@ namespace WulaFallenEmpire if (isWarmingUp) { warmupTicksLeft--; + if (warmupTicksLeft % 60 == 0) + { + Log.Message($"[WULA] Teleport warmup: {warmupTicksLeft} ticks left."); + Props.warmupEffecter?.Spawn(parent, parent.Map).Cleanup(); + } + if (warmupTicksLeft <= 0) { + Log.Message("[WULA] Warmup finished. Attempting teleport..."); TryTeleport(); isWarmingUp = false; } - else if (warmupTicksLeft % 60 == 0) - { - Props.warmupEffecter?.Spawn(parent, parent.Map).Cleanup(); - } } } @@ -64,6 +75,16 @@ namespace WulaFallenEmpire action = CancelTeleport }; } + else if (activeMarker != null && !activeMarker.Destroyed) + { + yield return new Command_Action + { + defaultLabel = "WULA_CancelTeleport".Translate(), + defaultDesc = "WULA_CancelTeleportDesc".Translate(), + icon = ContentFinder.Get("UI/Designators/Cancel"), + action = CancelTeleport + }; + } else { string reason = GetDisabledReason(); @@ -122,15 +143,44 @@ namespace WulaFallenEmpire this.target = targetInfo; MapParent mapParent = Find.WorldObjects.MapParentAt(targetInfo.Tile); - if (mapParent != null && mapParent.HasMap) + + if (mapParent == null) { - CameraJumper.TryJump(mapParent.Map.Center, mapParent.Map); - Find.DesignatorManager.Select(new Designator_TeleportArrival(this, mapParent.Map)); - return true; + SettleUtility.AddNewHome(targetInfo.Tile, Faction.OfPlayer); + mapParent = Find.WorldObjects.MapParentAt(targetInfo.Tile); + } + + if (mapParent != null) + { + if (!mapParent.HasMap) + { + IntVec3 mapSize = Find.World.info.initialMapSize; + GetOrGenerateMapUtility.GetOrGenerateMap(targetInfo.Tile, mapSize, null); + } + + if (mapParent.HasMap) + { + CameraJumper.TryJump(mapParent.Map.Center, mapParent.Map); + + if (activeMarker != null && !activeMarker.Destroyed) + { + activeMarker.Destroy(); + } + + activeMarker = (WULA_TeleportLandingMarker)ThingMaker.MakeThing(DefDatabase.GetNamed("WULA_TeleportLandingMarker")); + activeMarker.sourceThing = parent; + GenSpawn.Spawn(activeMarker, mapParent.Map.Center, mapParent.Map); + + Find.Selector.ClearSelection(); + Find.Selector.Select(activeMarker); + Find.DesignatorManager.Select(new Designator_TeleportArrival(this, mapParent.Map, activeMarker)); + + return true; + } } - StartWarmup(); - return true; + Messages.Message("WULA_TeleportFailed_MapGeneration".Translate(), MessageTypeDefOf.RejectInput); + return false; } public void ConfirmArrival(IntVec3 cell, Map map) @@ -151,13 +201,23 @@ namespace WulaFallenEmpire { isWarmingUp = false; warmupTicksLeft = 0; + + if (activeMarker != null && !activeMarker.Destroyed) + { + activeMarker.Destroy(); + activeMarker = null; + } + Messages.Message("WULA_TeleportCancelled".Translate(), parent, MessageTypeDefOf.NeutralEvent); } private void TryTeleport() { + Log.Message($"[WULA] TryTeleport called. Target valid: {target.IsValid}, Tile: {target.Tile}, Cell: {target.Cell}"); + if (!target.IsValid) { + Messages.Message("WULA_TeleportFailed_InvalidTarget".Translate(), parent, MessageTypeDefOf.RejectInput); CancelTeleport(); return; } @@ -167,16 +227,18 @@ namespace WulaFallenEmpire if (targetMap == null) { + Log.Message($"[WULA] Target map is null. Generating map for tile {target.Tile}..."); targetMap = GetOrGenerateTargetMap(target.Tile); if (targetMap == null) { - Log.Error("Failed to get or generate target map."); + Messages.Message("WULA_TeleportFailed_NoMap".Translate(), parent, MessageTypeDefOf.RejectInput); CancelTeleport(); return; } targetCell = targetMap.Center; } + Log.Message($"[WULA] Teleporting to map {targetMap.Index}, cell {targetCell}"); TeleportContents(targetMap, targetCell); } @@ -203,85 +265,90 @@ namespace WulaFallenEmpire return null; } - private struct CellData - { - public IntVec3 relativePos; - public TerrainDef terrain; - public List things; - } - private void TeleportContents(Map targetMap, IntVec3 targetCenter) { - IEnumerable cells = GenRadial.RadialCellsAround(parent.Position, Props.radius, true); - List dataToTeleport = new List(); + CellRect rect = CellRect.CenteredOn(parent.Position, Props.areaSize.x, Props.areaSize.z); IntVec3 center = parent.Position; + + List thingsToTeleport = new List(); + List> terrainToTeleport = new List>(); + + Log.Message($"[WULA] Collecting data from {rect.Area} cells around {center} with size {Props.areaSize}"); // 1. 收集数据 - foreach (IntVec3 cell in cells) + HashSet collectedThings = new HashSet(); + foreach (IntVec3 cell in rect) { if (!cell.InBounds(parent.Map)) continue; - CellData data = new CellData - { - relativePos = cell - center, - terrain = cell.GetTerrain(parent.Map), - things = new List() - }; + terrainToTeleport.Add(new Pair(cell - center, cell.GetTerrain(parent.Map))); List thingList = parent.Map.thingGrid.ThingsListAt(cell); for (int i = thingList.Count - 1; i >= 0; i--) { Thing t = thingList[i]; - if (t.def.category == ThingCategory.Item || - t.def.category == ThingCategory.Pawn || - t.def.category == ThingCategory.Building) + if (t != parent && !collectedThings.Contains(t) && + (t.def.category == ThingCategory.Item || + t.def.category == ThingCategory.Pawn || + t.def.category == ThingCategory.Building)) { - if (t != parent && !t.def.destroyable) continue; - if (t != parent) data.things.Add(t); + if (!t.def.destroyable) continue; + + collectedThings.Add(t); + thingsToTeleport.Add(t); } } - dataToTeleport.Add(data); } - // 2. 执行传送 - foreach (CellData data in dataToTeleport) + // 2. 准备传送 (PreSwapMap) + foreach (Thing t in thingsToTeleport) t.PreSwapMap(); + parent.PreSwapMap(); + + // 3. 从源地图移除 (DeSpawn) + foreach (Thing t in thingsToTeleport) { - IntVec3 newPos = targetCenter + data.relativePos; + if (t.Spawned) t.DeSpawn(DestroyMode.WillReplace); + } + if (parent.Spawned) parent.DeSpawn(DestroyMode.WillReplace); + + // 4. 修改地形 + foreach (var pair in terrainToTeleport) + { + IntVec3 newPos = targetCenter + pair.First; newPos = newPos.ClampInsideMap(targetMap); - // 2.1 传送地形 - if (data.terrain != null) + List targetThings = targetMap.thingGrid.ThingsListAt(newPos); + for (int i = targetThings.Count - 1; i >= 0; i--) { - List targetThings = targetMap.thingGrid.ThingsListAt(newPos); - for (int i = targetThings.Count - 1; i >= 0; i--) - { - if (targetThings[i].def.destroyable) targetThings[i].Destroy(); - } - - targetMap.terrainGrid.SetTerrain(newPos, data.terrain); - parent.Map.terrainGrid.SetTerrain(center + data.relativePos, TerrainDefOf.Soil); + if (targetThings[i].def.destroyable) targetThings[i].Destroy(); } - // 2.2 传送物体 - foreach (Thing t in data.things) + if (pair.Second != null) { - if (t.Destroyed) continue; - - if (t.Spawned) t.DeSpawn(); - GenSpawn.Spawn(t, newPos, targetMap, t.Rotation); - - if (t is Pawn p) - { - p.jobs.StopAll(); - } + targetMap.terrainGrid.SetTerrain(newPos, pair.Second); + parent.Map.terrainGrid.SetTerrain(center + pair.First, TerrainDefOf.Soil); } } - // 3. 传送自身 - if (parent.Spawned) parent.DeSpawn(); + // 5. 放置到新地图 (Spawn) + foreach (Thing t in thingsToTeleport) + { + if (t.Destroyed) continue; + IntVec3 relativePos = t.Position - center; + IntVec3 newPos = targetCenter + relativePos; + newPos = newPos.ClampInsideMap(targetMap); + GenSpawn.Spawn(t, newPos, targetMap, t.Rotation); + } GenSpawn.Spawn(parent, targetCenter, targetMap, parent.Rotation); - // 4. 完成 + // 6. 传送后处理 (PostSwapMap) + foreach (Thing t in thingsToTeleport) + { + if (!t.Destroyed) t.PostSwapMap(); + } + parent.PostSwapMap(); + + // 7. 完成 CameraJumper.TryJump(targetCenter, targetMap); Props.teleportSound?.PlayOneShot(new TargetInfo(targetCenter, targetMap, false)); Messages.Message("WULA_TeleportSuccessful".Translate(), new TargetInfo(targetCenter, targetMap, false), MessageTypeDefOf.PositiveEvent); diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompProperties_MapTeleporter.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompProperties_MapTeleporter.cs index ed62f535..55b52901 100644 --- a/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompProperties_MapTeleporter.cs +++ b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/CompProperties_MapTeleporter.cs @@ -5,7 +5,7 @@ namespace WulaFallenEmpire { public class CompProperties_MapTeleporter : CompProperties { - public float radius = 5f; + public IntVec2 areaSize = new IntVec2(13, 13); public int warmupTicks = 120; public EffecterDef warmupEffecter; public SoundDef warmupSound; diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/WULA_TeleportLandingMarker.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/WULA_TeleportLandingMarker.cs new file mode 100644 index 00000000..0787d2f3 --- /dev/null +++ b/Source/WulaFallenEmpire/BuildingComp/WULA_Teleporter/WULA_TeleportLandingMarker.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + public class WULA_TeleportLandingMarker : Thing + { + public Thing sourceThing; + + public CompMapTeleporter SourceTeleporter => sourceThing?.TryGetComp(); + + public override CellRect? CustomRectForSelector + { + get + { + if (SourceTeleporter != null) + { + return CellRect.CenteredOn(Position, SourceTeleporter.Props.areaSize.x, SourceTeleporter.Props.areaSize.z); + } + return null; + } + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_References.Look(ref sourceThing, "sourceThing"); + } + + public override IEnumerable GetGizmos() + { + foreach (var gizmo in base.GetGizmos()) + { + yield return gizmo; + } + + yield return new Command_Action + { + defaultLabel = "WULA_ConfirmTeleport".Translate(), + defaultDesc = "WULA_ConfirmTeleportDesc".Translate(), + icon = ContentFinder.Get("UI/Commands/LaunchShip"), + action = Confirm + }; + + yield return new Command_Action + { + defaultLabel = "WULA_MoveMarker".Translate(), + defaultDesc = "WULA_MoveMarkerDesc".Translate(), + icon = ContentFinder.Get("UI/Commands/Install"), + action = StartMove + }; + } + + private void StartMove() + { + if (SourceTeleporter != null) + { + Find.DesignatorManager.Select(new Designator_TeleportArrival(SourceTeleporter, Map, this)); + } + } + + private void Confirm() + { + if (SourceTeleporter != null) + { + SourceTeleporter.ConfirmArrival(Position, Map); + } + Destroy(); + } + + protected override void DrawAt(Vector3 drawLoc, bool flip = false) + { + base.DrawAt(drawLoc, flip); + if (SourceTeleporter != null) + { + GenDraw.DrawFieldEdges(CellRect.CenteredOn(Position, SourceTeleporter.Props.areaSize.x, SourceTeleporter.Props.areaSize.z).Cells.ToList()); + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Damage/202512031732.xml b/Source/WulaFallenEmpire/Damage/202512031732.xml deleted file mode 100644 index e9f71f0e..00000000 --- a/Source/WulaFallenEmpire/Damage/202512031732.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - Damage_WithExtraEffects - - WulaFallenEmpire.DamageWorker_ExtraDamage - - -
  • - 电击效果 - true - - -
  • - EMP - 15 - false - 25 - EMP_Small - ElectricArc - 5 - - -
  • - Mechanoid - 0,1 -
  • - - - - -
    -
    - - - - Damage_WithBurn - - WulaFallenEmpire.DamageWorker_ExtraDamage - - -
  • - 燃烧效果 - - -
  • - Burn - true - 0.3 - SparkHit - 10 - - -
  • - Pawn - 0.3,1 - -
  • Flammable
  • - - - - - - -
    -
    - - - - Damage_MultiEffect - - WulaFallenEmpire.DamageWorker_ExtraDamage - - -
  • - 组合效果 - - - -
  • - Cut - 5 - false - Torso - - -
  • - Animal -
  • -
  • - Humanlike -
  • - - - - -
  • - EMP - true - 0.5 - false - - -
  • - Mechanoid -
  • - - - - -
  • - Blunt - 20 - false - - -
  • - Building -
  • - - - - -
    -
    - - - - Gun_AdvancedRifle - - - -
  • - Verb_Shoot - Bullet_Advanced -
  • -
    -
    - - - - Bullet_Advanced - - - Damage_MultiEffect - 25 - - diff --git a/Source/WulaFallenEmpire/Designator/Designator_TeleportArrival.cs b/Source/WulaFallenEmpire/Designator/Designator_TeleportArrival.cs index 490d3f1c..815e4363 100644 --- a/Source/WulaFallenEmpire/Designator/Designator_TeleportArrival.cs +++ b/Source/WulaFallenEmpire/Designator/Designator_TeleportArrival.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using RimWorld; using UnityEngine; using Verse; @@ -9,14 +10,18 @@ namespace WulaFallenEmpire { private CompMapTeleporter teleporter; private Map targetMap; + private WULA_TeleportLandingMarker marker; + private List thingsToTeleport = new List(); + private IntVec3 sourceCenter; public override string Label => "WULA_SelectArrivalPoint".Translate(); public override string Desc => "WULA_SelectArrivalPointDesc".Translate(); - public Designator_TeleportArrival(CompMapTeleporter teleporter, Map targetMap) + public Designator_TeleportArrival(CompMapTeleporter teleporter, Map targetMap, WULA_TeleportLandingMarker marker = null) { this.teleporter = teleporter; this.targetMap = targetMap; + this.marker = marker; this.useMouseIcon = true; this.soundDragSustain = SoundDefOf.Designate_DragStandard; this.soundDragChanged = SoundDefOf.Designate_DragStandard_Changed; @@ -27,9 +32,9 @@ namespace WulaFallenEmpire { if (!loc.InBounds(targetMap)) return false; - // 检查半径区域是否有效 - float radius = teleporter.Props.radius; - foreach (IntVec3 cell in GenRadial.RadialCellsAround(loc, radius, true)) + // 检查区域是否有效 + CellRect rect = CellRect.CenteredOn(loc, teleporter.Props.areaSize.x, teleporter.Props.areaSize.z); + foreach (IntVec3 cell in rect) { if (!cell.InBounds(targetMap)) return "WULA_OutOfBounds".Translate(); @@ -71,19 +76,92 @@ namespace WulaFallenEmpire public override void DesignateSingleCell(IntVec3 c) { - teleporter.ConfirmArrival(c, targetMap); - Find.DesignatorManager.Deselect(); + if (marker != null) + { + marker.Position = c; + Find.DesignatorManager.Deselect(); + Find.Selector.ClearSelection(); + Find.Selector.Select(marker); + } + else + { + teleporter.ConfirmArrival(c, targetMap); + Find.DesignatorManager.Deselect(); + } } public override void Selected() { - GenDraw.DrawRadiusRing(UI.MouseCell(), teleporter.Props.radius); + CacheThings(); + DrawRect(); + } + + public override void SelectedUpdate() + { + DrawRect(); + DrawGhosts(); } public override void DrawMouseAttachments() { base.DrawMouseAttachments(); - GenDraw.DrawRadiusRing(UI.MouseCell(), teleporter.Props.radius); + DrawRect(); + } + + private void DrawRect() + { + GenDraw.DrawFieldEdges(CellRect.CenteredOn(UI.MouseCell(), teleporter.Props.areaSize.x, teleporter.Props.areaSize.z).Cells.ToList()); + } + + private void CacheThings() + { + thingsToTeleport.Clear(); + if (teleporter.parent == null || teleporter.parent.Map == null) return; + + sourceCenter = teleporter.parent.Position; + Map sourceMap = teleporter.parent.Map; + CellRect rect = CellRect.CenteredOn(sourceCenter, teleporter.Props.areaSize.x, teleporter.Props.areaSize.z); + + foreach (IntVec3 cell in rect) + { + if (!cell.InBounds(sourceMap)) continue; + foreach (Thing t in sourceMap.thingGrid.ThingsListAt(cell)) + { + if (t.def.category == ThingCategory.Building || t.def.category == ThingCategory.Item || t.def.category == ThingCategory.Pawn) + { + if (t != teleporter.parent) thingsToTeleport.Add(t); + } + } + } + // 添加自身 + thingsToTeleport.Add(teleporter.parent); + } + + private void DrawGhosts() + { + IntVec3 mouseCell = UI.MouseCell(); + if (!mouseCell.InBounds(targetMap)) return; + + foreach (Thing t in thingsToTeleport) + { + if (t == null || t.Destroyed) continue; + if (t.Graphic == null) continue; + + IntVec3 relativePos = t.Position - sourceCenter; + IntVec3 drawPos = mouseCell + relativePos; + + if (drawPos.InBounds(targetMap)) + { + try + { + GhostUtility.GhostGraphicFor(t.Graphic, t.def, Color.white).DrawFromDef(drawPos.ToVector3ShiftedWithAltitude(AltitudeLayer.Blueprint), t.Rotation, t.def); + } + catch + { + // 忽略绘制错误,防止UI崩溃 + } + } + } } } } \ No newline at end of file