Merge branch 'main' of https://git.ra3battle.cn/Kalospacer/WulaFallenEmpireRW
This commit is contained in:
@@ -5,14 +5,7 @@
|
||||
"path": "../.."
|
||||
},
|
||||
{
|
||||
"name": "Data",
|
||||
"path": "../../../../Data"
|
||||
},
|
||||
{
|
||||
"path": "../../../../../../workshop/content/294100/3534748687"
|
||||
},
|
||||
{
|
||||
"path": "../../../../../../workshop/content/294100/3550544871"
|
||||
"path": "../../../../../../workshop/content/294100/3551234893/1.6/Assemblies/ShelterShuttle"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
146
Source/WulaFallenEmpire/WULA_Shuttle/Building_PocketMapExit.cs
Normal file
146
Source/WulaFallenEmpire/WULA_Shuttle/Building_PocketMapExit.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
/// <summary>
|
||||
/// 口袋空间退出点建筑 - 继承自MapPortal以获得完整的双向传送功能
|
||||
/// </summary>
|
||||
public class Building_PocketMapExit : MapPortal
|
||||
{
|
||||
/// <summary>目标地图</summary>
|
||||
public Map targetMap;
|
||||
|
||||
/// <summary>目标位置</summary>
|
||||
public IntVec3 targetPos;
|
||||
|
||||
/// <summary>父穿梭机</summary>
|
||||
public Building_ArmedShuttleWithPocket parentShuttle;
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_References.Look(ref targetMap, "targetMap");
|
||||
Scribe_Values.Look(ref targetPos, "targetPos");
|
||||
Scribe_References.Look(ref parentShuttle, "parentShuttle");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写获取其他地图,返回主地图(模仿原版MapPortal.GetOtherMap)
|
||||
/// </summary>
|
||||
public override Map GetOtherMap()
|
||||
{
|
||||
// 动态更新目标地图,处理穿梭机移动的情况
|
||||
UpdateTargetFromParentShuttle();
|
||||
return targetMap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写获取目标位置,返回主地图上的穿梭机位置(模仿原版MapPortal.GetDestinationLocation)
|
||||
/// </summary>
|
||||
public override IntVec3 GetDestinationLocation()
|
||||
{
|
||||
// 动态更新目标位置,处理穿梭机移动的情况
|
||||
UpdateTargetFromParentShuttle();
|
||||
return targetPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从父穿梭机动态更新目标位置,处理穿梭机移动的情况
|
||||
/// </summary>
|
||||
private void UpdateTargetFromParentShuttle()
|
||||
{
|
||||
if (parentShuttle != null && parentShuttle.Spawned)
|
||||
{
|
||||
// 如果穿梭机还在地图上,更新目标位置
|
||||
if (targetMap != parentShuttle.Map || targetPos != parentShuttle.Position)
|
||||
{
|
||||
targetMap = parentShuttle.Map;
|
||||
targetPos = parentShuttle.Position;
|
||||
Log.Message($"[WULA] Updated exit target to shuttle location: {targetMap?.uniqueID} at {targetPos}");
|
||||
}
|
||||
}
|
||||
else if (parentShuttle != null && !parentShuttle.Spawned)
|
||||
{
|
||||
// 穿梭机不在地图上(可能在飞行中)
|
||||
// 保持原有目标,但记录警告
|
||||
if (this.IsHashIntervalTick(2500)) // 每隔一段时间检查一次
|
||||
{
|
||||
Log.Warning($"[WULA] Parent shuttle is not spawned, exit target may be outdated. Last known: {targetMap?.uniqueID} at {targetPos}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写是否可进入,检查目标地图是否存在(模仿原版MapPortal.IsEnterable)
|
||||
/// </summary>
|
||||
public override bool IsEnterable(out string reason)
|
||||
{
|
||||
if (targetMap == null)
|
||||
{
|
||||
reason = "WULA.PocketSpace.NoTargetMap".Translate();
|
||||
return false;
|
||||
}
|
||||
reason = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写进入事件,处理从口袋空间退出到主地图(模仿原版MapPortal.OnEntered)
|
||||
/// </summary>
|
||||
public override void OnEntered(Pawn pawn)
|
||||
{
|
||||
// 不调用 base.OnEntered,因为我们不需要原版的通知机制
|
||||
// 直接处理退出逻辑
|
||||
if (targetMap != null && pawn.Spawned)
|
||||
{
|
||||
ExitPocketSpace(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写进入按钮文本
|
||||
/// </summary>
|
||||
public override string EnterString => "WULA.PocketSpace.ExitToMainMap".Translate();
|
||||
|
||||
/// <summary>
|
||||
/// 重写进入按钮图标,使用原版的ViewCave图标
|
||||
/// </summary>
|
||||
protected override Texture2D EnterTex => ContentFinder<Texture2D>.Get("UI/Commands/ViewCave");
|
||||
|
||||
/// <summary>
|
||||
/// 单个人员退出口袋空间(简化版本,利用MapPortal功能)
|
||||
/// </summary>
|
||||
private void ExitPocketSpace(Pawn pawn)
|
||||
{
|
||||
if (targetMap == null || !pawn.Spawned) return;
|
||||
|
||||
try
|
||||
{
|
||||
// 在目标地图找一个安全位置
|
||||
IntVec3 exitPos = CellFinder.RandomClosewalkCellNear(targetPos, targetMap, 3, p => p.Standable(targetMap));
|
||||
|
||||
// 传送人员
|
||||
pawn.DeSpawn();
|
||||
GenPlace.TryPlaceThing(pawn, exitPos, targetMap, ThingPlaceMode.Near);
|
||||
|
||||
// 切换到主地图
|
||||
if (pawn.IsColonistPlayerControlled)
|
||||
{
|
||||
Current.Game.CurrentMap = targetMap;
|
||||
Find.CameraDriver.JumpToCurrentMapLoc(exitPos);
|
||||
}
|
||||
|
||||
Messages.Message("WULA.PocketSpace.ExitSuccess".Translate(pawn.LabelShort), MessageTypeDefOf.PositiveEvent);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Error($"[WULA] Error exiting pocket space: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
/// <summary>
|
||||
/// 13x13小型口袋空间生成器
|
||||
/// 创建一个简单的13x13空间,边缘是墙,中间是空地,适合作为穿梭机内部空间
|
||||
/// </summary>
|
||||
public class GenStep_WulaPocketSpaceSmall : GenStep
|
||||
{
|
||||
public override int SeedPart => 928735; // 不同于AncientStockpile的种子
|
||||
|
||||
public override void Generate(Map map, GenStepParams parms)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Message($"[WULA] Generating WULA pocket space, map size: {map.Size}");
|
||||
|
||||
// 获取地图边界
|
||||
IntVec3 mapSize = map.Size;
|
||||
|
||||
// 生成外围岩石墙壁
|
||||
GenerateWalls(map);
|
||||
|
||||
// 生成内部地板
|
||||
GenerateFloor(map);
|
||||
|
||||
// 生成一些基础设施(照明等)
|
||||
GenerateBasicInfrastructure(map);
|
||||
|
||||
Log.Message("[WULA] WULA pocket space generation completed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"[WULA] Error generating WULA pocket space: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成外围墙壁
|
||||
/// </summary>
|
||||
private void GenerateWalls(Map map)
|
||||
{
|
||||
IntVec3 mapSize = map.Size;
|
||||
|
||||
// 获取地形和物品定义
|
||||
TerrainDef roughTerrain = DefDatabase<TerrainDef>.GetNamed("Granite_Rough", false) ??
|
||||
DefDatabase<TerrainDef>.GetNamed("Granite_Smooth", false) ??
|
||||
DefDatabase<TerrainDef>.GetNamed("Sandstone_Rough", false);
|
||||
|
||||
ThingDef rockWallDef = DefDatabase<ThingDef>.GetNamed("Wall_Rock", false) ??
|
||||
DefDatabase<ThingDef>.GetNamed("Wall", false);
|
||||
|
||||
// 遍历地图边缘,放置WulaWall
|
||||
for (int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for (int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
// 如果是边缘位置,放置WulaWall
|
||||
if (x == 0 || x == mapSize.x - 1 || z == 0 || z == mapSize.z - 1)
|
||||
{
|
||||
IntVec3 pos = new IntVec3(x, 0, z);
|
||||
|
||||
// 设置地形为岩石基础
|
||||
if (roughTerrain != null)
|
||||
{
|
||||
map.terrainGrid.SetTerrain(pos, roughTerrain);
|
||||
}
|
||||
|
||||
// 放置WulaWall
|
||||
ThingDef wallDef = DefDatabase<ThingDef>.GetNamed("WulaWall", false);
|
||||
if (wallDef != null)
|
||||
{
|
||||
Thing wall = ThingMaker.MakeThing(wallDef);
|
||||
wall.SetFaction(null);
|
||||
GenPlace.TryPlaceThing(wall, pos, map, ThingPlaceMode.Direct);
|
||||
}
|
||||
else if (rockWallDef != null)
|
||||
{
|
||||
// 如果WulaWall不存在,使用原版岩石墙作为备选
|
||||
Thing wall = ThingMaker.MakeThing(rockWallDef);
|
||||
wall.SetFaction(null);
|
||||
GenPlace.TryPlaceThing(wall, pos, map, ThingPlaceMode.Direct);
|
||||
Log.Warning("[WULA] WulaWall not found, using fallback wall");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成内部地板
|
||||
/// </summary>
|
||||
private void GenerateFloor(Map map)
|
||||
{
|
||||
IntVec3 mapSize = map.Size;
|
||||
|
||||
// 为内部区域设置WulaFloor
|
||||
TerrainDef floorDef = DefDatabase<TerrainDef>.GetNamed("WulaFloor", false);
|
||||
TerrainDef fallbackFloor = floorDef ??
|
||||
DefDatabase<TerrainDef>.GetNamed("Steel", false) ??
|
||||
DefDatabase<TerrainDef>.GetNamed("MetalTile", false) ??
|
||||
DefDatabase<TerrainDef>.GetNamed("Concrete", false);
|
||||
|
||||
if (floorDef == null)
|
||||
{
|
||||
Log.Warning("[WULA] WulaFloor not found, using fallback floor");
|
||||
}
|
||||
|
||||
// 清理内部区域并设置正确的地板
|
||||
for (int x = 1; x < mapSize.x - 1; x++)
|
||||
{
|
||||
for (int z = 1; z < mapSize.z - 1; z++)
|
||||
{
|
||||
IntVec3 pos = new IntVec3(x, 0, z);
|
||||
|
||||
// 清理该位置的所有岩石和阻挡物
|
||||
ClearCellAndSetFloor(map, pos, fallbackFloor);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Message($"[WULA] Set floor for internal area ({mapSize.x-2}x{mapSize.z-2}) to {(floorDef?.defName ?? fallbackFloor?.defName)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理单元格并设置地板
|
||||
/// </summary>
|
||||
private void ClearCellAndSetFloor(Map map, IntVec3 pos, TerrainDef floorDef)
|
||||
{
|
||||
if (!pos.InBounds(map)) return;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取该位置的所有物品
|
||||
List<Thing> thingsAtPos = pos.GetThingList(map).ToList(); // 创建副本避免修改时出错
|
||||
|
||||
// 清理所有建筑物和岩石(强力清理,确保地板可以放置)
|
||||
foreach (Thing thing in thingsAtPos)
|
||||
{
|
||||
bool shouldRemove = false;
|
||||
|
||||
// 检查是否为建筑物
|
||||
if (thing.def.category == ThingCategory.Building)
|
||||
{
|
||||
// 如果是自然岩石
|
||||
if (thing.def.building?.isNaturalRock == true)
|
||||
{
|
||||
shouldRemove = true;
|
||||
}
|
||||
// 或者是岩石相关的建筑
|
||||
else if (thing.def.defName.Contains("Rock") ||
|
||||
thing.def.defName.Contains("Slate") ||
|
||||
thing.def.defName.Contains("Granite") ||
|
||||
thing.def.defName.Contains("Sandstone") ||
|
||||
thing.def.defName.Contains("Limestone") ||
|
||||
thing.def.defName.Contains("Marble") ||
|
||||
thing.def.defName.Contains("Quartzite") ||
|
||||
thing.def.defName.Contains("Jade"))
|
||||
{
|
||||
shouldRemove = true;
|
||||
}
|
||||
// 或者是其他阻挡的建筑物(除了我们的乌拉墙)
|
||||
else if (!thing.def.defName.Contains("Wula") && thing.def.Fillage == FillCategory.Full)
|
||||
{
|
||||
shouldRemove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRemove)
|
||||
{
|
||||
if (Prefs.DevMode) // 只在开发模式下输出详细日志
|
||||
{
|
||||
Log.Message($"[WULA] Removing {thing.def.defName} at {pos} to make space for floor");
|
||||
}
|
||||
thing.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
}
|
||||
|
||||
// 在清理后稍微延迟,再检查一次(确保彻底清理)
|
||||
thingsAtPos = pos.GetThingList(map).ToList();
|
||||
foreach (Thing thing in thingsAtPos)
|
||||
{
|
||||
if (thing.def.category == ThingCategory.Building && thing.def.Fillage == FillCategory.Full)
|
||||
{
|
||||
Log.Warning($"[WULA] Force removing remaining building {thing.def.defName} at {pos}");
|
||||
thing.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置地板地形
|
||||
if (floorDef != null)
|
||||
{
|
||||
map.terrainGrid.SetTerrain(pos, floorDef);
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[WULA] Set terrain at {pos} to {floorDef.defName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"[WULA] Error clearing cell at {pos}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成基础设施
|
||||
/// </summary>
|
||||
private void GenerateBasicInfrastructure(Map map)
|
||||
{
|
||||
IntVec3 mapSize = map.Size;
|
||||
IntVec3 center = map.Center;
|
||||
|
||||
// 获取灯具定义
|
||||
ThingDef lampDef = DefDatabase<ThingDef>.GetNamed("StandingLamp", false) ??
|
||||
DefDatabase<ThingDef>.GetNamed("TorchLamp", false) ??
|
||||
DefDatabase<ThingDef>.GetNamed("Campfire", false);
|
||||
|
||||
if (lampDef == null)
|
||||
{
|
||||
Log.Warning("[WULA] No lamp definition found, skipping lighting generation");
|
||||
return;
|
||||
}
|
||||
|
||||
// 在四个角落放置照明设备
|
||||
var lightPositions = new List<IntVec3>
|
||||
{
|
||||
new IntVec3(2, 0, 2), // 左下角
|
||||
new IntVec3(mapSize.x - 3, 0, 2), // 右下角
|
||||
new IntVec3(2, 0, mapSize.z - 3), // 左上角
|
||||
new IntVec3(mapSize.x - 3, 0, mapSize.z - 3) // 右上角
|
||||
};
|
||||
|
||||
foreach (IntVec3 pos in lightPositions)
|
||||
{
|
||||
if (pos.InBounds(map) && pos.Standable(map))
|
||||
{
|
||||
// 放置立式灯
|
||||
Thing lamp = ThingMaker.MakeThing(lampDef);
|
||||
lamp.SetFaction(null);
|
||||
GenPlace.TryPlaceThing(lamp, pos, map, ThingPlaceMode.Direct);
|
||||
}
|
||||
}
|
||||
|
||||
// 在中心区域留出空间,这里将放置退出点
|
||||
// 不在这里放置退出点,因为这会由Building_ArmedShuttleWithPocket来处理
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,9 @@
|
||||
<Compile Include="Projectiles\BulletWithTrail.cs" />
|
||||
<Compile Include="WULA_Shuttle\ArmedShuttleIncoming.cs" />
|
||||
<Compile Include="WULA_Shuttle\Building_ArmedShuttle.cs" />
|
||||
<Compile Include="WULA_Shuttle\Building_ArmedShuttleWithPocket.cs" />
|
||||
<Compile Include="WULA_Shuttle\Building_PocketMapExit.cs" />
|
||||
<Compile Include="WULA_Shuttle\GenStep_WulaPocketSpaceSmall.cs" />
|
||||
<Compile Include="HarmonyPatches\Patch_DropCellFinder_SkyfallerCanLandAt.cs" />
|
||||
<Compile Include="MechWeapon\FloatMenuProvider_Mech.cs" />
|
||||
<Compile Include="MechWeapon\Patch_MissingWeapon.cs" />
|
||||
|
||||
Reference in New Issue
Block a user