feat: 添加区域传送功能,模仿逆重飞船机制
This commit is contained in:
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
<defName>WULA_AreaTeleportBeacon</defName>
|
<defName>WULA_AreaTeleportBeacon</defName>
|
||||||
<label>乌拉区域传送信标</label>
|
<label>乌拉区域传送信标</label>
|
||||||
<description>负责协调殖民地与轨道上的乌拉帝国舰队进行材料输送的信标,空投建筑会优先从信标覆盖区域吸纳资源完成空投。</description>
|
<description>负责协调殖民地与轨道上的乌拉帝国舰队进行材料输送的信标,空投建筑会优先从信标覆盖区域吸纳资源完成空投。</description>
|
||||||
<thingClass>Building_OrbitalTradeBeacon</thingClass>
|
<thingClass>Building</thingClass>
|
||||||
<thingCategories Inherit="False">
|
<thingCategories Inherit="False">
|
||||||
<li>BuildingsMisc</li>
|
<li>BuildingsMisc</li>
|
||||||
</thingCategories>
|
</thingCategories>
|
||||||
@@ -32,12 +32,13 @@
|
|||||||
<Steel>40</Steel>
|
<Steel>40</Steel>
|
||||||
<ComponentIndustrial>1</ComponentIndustrial>
|
<ComponentIndustrial>1</ComponentIndustrial>
|
||||||
</costList>
|
</costList>
|
||||||
|
<tickerType>Normal</tickerType>
|
||||||
<building>
|
<building>
|
||||||
<destroySound>BuildingDestroyed_Metal_Small</destroySound>
|
<destroySound>BuildingDestroyed_Metal_Small</destroySound>
|
||||||
</building>
|
</building>
|
||||||
<comps>
|
<comps>
|
||||||
<li Class="WulaFallenEmpire.CompProperties_MapTeleporter">
|
<li Class="WulaFallenEmpire.CompProperties_MapTeleporter">
|
||||||
<radius>7</radius>
|
<areaSize>(13, 13)</areaSize>
|
||||||
<warmupTicks>120</warmupTicks>
|
<warmupTicks>120</warmupTicks>
|
||||||
<requiredResearch>WULA_Colony_License_LV1_Technology</requiredResearch>
|
<requiredResearch>WULA_Colony_License_LV1_Technology</requiredResearch>
|
||||||
</li>
|
</li>
|
||||||
@@ -1029,4 +1030,6 @@
|
|||||||
</li>
|
</li>
|
||||||
</comps>
|
</comps>
|
||||||
</ThingDef>
|
</ThingDef>
|
||||||
|
|
||||||
|
|
||||||
</Defs>
|
</Defs>
|
||||||
@@ -1,5 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Defs>
|
<Defs>
|
||||||
|
|
||||||
|
<ThingDef ParentName="EtherealThingBase">
|
||||||
|
<defName>WULA_TeleportLandingMarker</defName>
|
||||||
|
<label>传送降落标记</label>
|
||||||
|
<description>用于标记传送降落位置。</description>
|
||||||
|
<thingClass>WulaFallenEmpire.WULA_TeleportLandingMarker</thingClass>
|
||||||
|
<graphicData>
|
||||||
|
<texPath>Wula/Building/WULA_Dropping_Building_Cleanzone_Plus</texPath>
|
||||||
|
<graphicClass>Graphic_Multi</graphicClass>
|
||||||
|
<drawSize>(13,13)</drawSize>
|
||||||
|
<damageData>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</damageData>
|
||||||
|
</graphicData>
|
||||||
|
<altitudeLayer>Building</altitudeLayer>
|
||||||
|
<rotatable>false</rotatable>
|
||||||
|
<selectable>true</selectable>
|
||||||
|
<hasCustomRectForSelector>true</hasCustomRectForSelector>
|
||||||
|
<drawerType>RealtimeOnly</drawerType>
|
||||||
|
<drawOffscreen>true</drawOffscreen>
|
||||||
|
</ThingDef>
|
||||||
|
|
||||||
<ThingDef ParentName="BuildingBase">
|
<ThingDef ParentName="BuildingBase">
|
||||||
<defName>WULA_Prefab_Cleanzone_NewColonyBase_Beacon</defName>
|
<defName>WULA_Prefab_Cleanzone_NewColonyBase_Beacon</defName>
|
||||||
<label>乌拉预制件空投信标-小型前哨站</label>
|
<label>乌拉预制件空投信标-小型前哨站</label>
|
||||||
|
|||||||
@@ -113,5 +113,33 @@
|
|||||||
<WULA_SelectCategoryFirst>请先选择一个分类</WULA_SelectCategoryFirst>
|
<WULA_SelectCategoryFirst>请先选择一个分类</WULA_SelectCategoryFirst>
|
||||||
<WULA_GatheringMaterials>正在收集材料</WULA_GatheringMaterials>
|
<WULA_GatheringMaterials>正在收集材料</WULA_GatheringMaterials>
|
||||||
<WULA_Paused>已暂停</WULA_Paused>
|
<WULA_Paused>已暂停</WULA_Paused>
|
||||||
|
<!-- Area Teleporter -->
|
||||||
|
<WULA_CancelTeleport>取消传送</WULA_CancelTeleport>
|
||||||
|
<WULA_CancelTeleportDesc>取消当前的传送预热。</WULA_CancelTeleportDesc>
|
||||||
|
<WULA_InitiateTeleport>启动传送</WULA_InitiateTeleport>
|
||||||
|
<WULA_InitiateTeleportDesc>启动区域传送程序,将信标周围的物体传送到指定位置。</WULA_InitiateTeleportDesc>
|
||||||
|
<WULA_RequiresResearch>需要研究:{0}</WULA_RequiresResearch>
|
||||||
|
<WULA_MissingResearch>缺少必要的研究:{0}</WULA_MissingResearch>
|
||||||
|
<WULA_TeleportFailed_MapGeneration>无法生成目标地图。</WULA_TeleportFailed_MapGeneration>
|
||||||
|
<WULA_TeleportWarmupStarted>传送预热已开始。</WULA_TeleportWarmupStarted>
|
||||||
|
<WULA_TeleportCancelled>传送已取消。</WULA_TeleportCancelled>
|
||||||
|
<WULA_TeleportFailed_InvalidTarget>无效的目标位置。</WULA_TeleportFailed_InvalidTarget>
|
||||||
|
<WULA_TeleportFailed_NoMap>无法获取目标地图。</WULA_TeleportFailed_NoMap>
|
||||||
|
<WULA_TeleportSuccessful>传送成功。</WULA_TeleportSuccessful>
|
||||||
|
<WULA_SelectArrivalPoint>选择降落点</WULA_SelectArrivalPoint>
|
||||||
|
<WULA_SelectArrivalPointDesc>选择传送到达的具体位置。</WULA_SelectArrivalPointDesc>
|
||||||
|
<WULA_OutOfBounds>超出地图边界。</WULA_OutOfBounds>
|
||||||
|
<WULA_InNoBuildArea>位于不可建造区域。</WULA_InNoBuildArea>
|
||||||
|
<WULA_BlockedByFog>目标位置被迷雾覆盖。</WULA_BlockedByFog>
|
||||||
|
<WULA_BlockedByIndestructible>被不可破坏的物体阻挡:{0}</WULA_BlockedByIndestructible>
|
||||||
|
<WULA_TerrainImpassable>目标地形不可通过。</WULA_TerrainImpassable>
|
||||||
|
<WULA_BlockedByThickRoof>被厚岩顶阻挡。</WULA_BlockedByThickRoof>
|
||||||
|
<WULA_MustSelectLandingSpot>必须选择一个降落点。</WULA_MustSelectLandingSpot>
|
||||||
|
<WULA_ConfirmTeleport>确认传送</WULA_ConfirmTeleport>
|
||||||
|
<WULA_ConfirmTeleportDesc>确认当前位置并开始传送。</WULA_ConfirmTeleportDesc>
|
||||||
|
<WULA_MoveMarker>移动标记</WULA_MoveMarker>
|
||||||
|
<WULA_MoveMarkerDesc>重新选择降落位置。</WULA_MoveMarkerDesc>
|
||||||
|
<WULA_GeneratedMapCleanedUp>由于传送取消,生成的临时地图已被清理。</WULA_GeneratedMapCleanedUp>
|
||||||
|
<WULA_InsufficientFuel>燃料不足。</WULA_InsufficientFuel>
|
||||||
|
|
||||||
</LanguageData>
|
</LanguageData>
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"path": "../../../../Data"
|
"path": "../../../../Data"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "dll1.6",
|
||||||
"path": "../../../../dll1.6"
|
"path": "../../../../dll1.6"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace WulaFallenEmpire
|
|||||||
private bool isWarmingUp = false;
|
private bool isWarmingUp = false;
|
||||||
private int warmupTicksLeft = 0;
|
private int warmupTicksLeft = 0;
|
||||||
private GlobalTargetInfo target;
|
private GlobalTargetInfo target;
|
||||||
|
private WULA_TeleportLandingMarker activeMarker;
|
||||||
|
|
||||||
public override void PostExposeData()
|
public override void PostExposeData()
|
||||||
{
|
{
|
||||||
@@ -24,6 +25,13 @@ namespace WulaFallenEmpire
|
|||||||
Scribe_Values.Look(ref isWarmingUp, "isWarmingUp", false);
|
Scribe_Values.Look(ref isWarmingUp, "isWarmingUp", false);
|
||||||
Scribe_Values.Look(ref warmupTicksLeft, "warmupTicksLeft", 0);
|
Scribe_Values.Look(ref warmupTicksLeft, "warmupTicksLeft", 0);
|
||||||
Scribe_TargetInfo.Look(ref target, "target");
|
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()
|
public override void CompTick()
|
||||||
@@ -32,15 +40,18 @@ namespace WulaFallenEmpire
|
|||||||
if (isWarmingUp)
|
if (isWarmingUp)
|
||||||
{
|
{
|
||||||
warmupTicksLeft--;
|
warmupTicksLeft--;
|
||||||
|
if (warmupTicksLeft % 60 == 0)
|
||||||
|
{
|
||||||
|
Log.Message($"[WULA] Teleport warmup: {warmupTicksLeft} ticks left.");
|
||||||
|
Props.warmupEffecter?.Spawn(parent, parent.Map).Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
if (warmupTicksLeft <= 0)
|
if (warmupTicksLeft <= 0)
|
||||||
{
|
{
|
||||||
|
Log.Message("[WULA] Warmup finished. Attempting teleport...");
|
||||||
TryTeleport();
|
TryTeleport();
|
||||||
isWarmingUp = false;
|
isWarmingUp = false;
|
||||||
}
|
}
|
||||||
else if (warmupTicksLeft % 60 == 0)
|
|
||||||
{
|
|
||||||
Props.warmupEffecter?.Spawn(parent, parent.Map).Cleanup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +75,16 @@ namespace WulaFallenEmpire
|
|||||||
action = CancelTeleport
|
action = CancelTeleport
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if (activeMarker != null && !activeMarker.Destroyed)
|
||||||
|
{
|
||||||
|
yield return new Command_Action
|
||||||
|
{
|
||||||
|
defaultLabel = "WULA_CancelTeleport".Translate(),
|
||||||
|
defaultDesc = "WULA_CancelTeleportDesc".Translate(),
|
||||||
|
icon = ContentFinder<Texture2D>.Get("UI/Designators/Cancel"),
|
||||||
|
action = CancelTeleport
|
||||||
|
};
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string reason = GetDisabledReason();
|
string reason = GetDisabledReason();
|
||||||
@@ -122,15 +143,44 @@ namespace WulaFallenEmpire
|
|||||||
this.target = targetInfo;
|
this.target = targetInfo;
|
||||||
|
|
||||||
MapParent mapParent = Find.WorldObjects.MapParentAt(targetInfo.Tile);
|
MapParent mapParent = Find.WorldObjects.MapParentAt(targetInfo.Tile);
|
||||||
if (mapParent != null && mapParent.HasMap)
|
|
||||||
|
if (mapParent == null)
|
||||||
{
|
{
|
||||||
CameraJumper.TryJump(mapParent.Map.Center, mapParent.Map);
|
SettleUtility.AddNewHome(targetInfo.Tile, Faction.OfPlayer);
|
||||||
Find.DesignatorManager.Select(new Designator_TeleportArrival(this, mapParent.Map));
|
mapParent = Find.WorldObjects.MapParentAt(targetInfo.Tile);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StartWarmup();
|
if (mapParent != null)
|
||||||
return true;
|
{
|
||||||
|
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<ThingDef>.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Messages.Message("WULA_TeleportFailed_MapGeneration".Translate(), MessageTypeDefOf.RejectInput);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConfirmArrival(IntVec3 cell, Map map)
|
public void ConfirmArrival(IntVec3 cell, Map map)
|
||||||
@@ -151,13 +201,23 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
isWarmingUp = false;
|
isWarmingUp = false;
|
||||||
warmupTicksLeft = 0;
|
warmupTicksLeft = 0;
|
||||||
|
|
||||||
|
if (activeMarker != null && !activeMarker.Destroyed)
|
||||||
|
{
|
||||||
|
activeMarker.Destroy();
|
||||||
|
activeMarker = null;
|
||||||
|
}
|
||||||
|
|
||||||
Messages.Message("WULA_TeleportCancelled".Translate(), parent, MessageTypeDefOf.NeutralEvent);
|
Messages.Message("WULA_TeleportCancelled".Translate(), parent, MessageTypeDefOf.NeutralEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryTeleport()
|
private void TryTeleport()
|
||||||
{
|
{
|
||||||
|
Log.Message($"[WULA] TryTeleport called. Target valid: {target.IsValid}, Tile: {target.Tile}, Cell: {target.Cell}");
|
||||||
|
|
||||||
if (!target.IsValid)
|
if (!target.IsValid)
|
||||||
{
|
{
|
||||||
|
Messages.Message("WULA_TeleportFailed_InvalidTarget".Translate(), parent, MessageTypeDefOf.RejectInput);
|
||||||
CancelTeleport();
|
CancelTeleport();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -167,16 +227,18 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
if (targetMap == null)
|
if (targetMap == null)
|
||||||
{
|
{
|
||||||
|
Log.Message($"[WULA] Target map is null. Generating map for tile {target.Tile}...");
|
||||||
targetMap = GetOrGenerateTargetMap(target.Tile);
|
targetMap = GetOrGenerateTargetMap(target.Tile);
|
||||||
if (targetMap == null)
|
if (targetMap == null)
|
||||||
{
|
{
|
||||||
Log.Error("Failed to get or generate target map.");
|
Messages.Message("WULA_TeleportFailed_NoMap".Translate(), parent, MessageTypeDefOf.RejectInput);
|
||||||
CancelTeleport();
|
CancelTeleport();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
targetCell = targetMap.Center;
|
targetCell = targetMap.Center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.Message($"[WULA] Teleporting to map {targetMap.Index}, cell {targetCell}");
|
||||||
TeleportContents(targetMap, targetCell);
|
TeleportContents(targetMap, targetCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,85 +265,90 @@ namespace WulaFallenEmpire
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct CellData
|
|
||||||
{
|
|
||||||
public IntVec3 relativePos;
|
|
||||||
public TerrainDef terrain;
|
|
||||||
public List<Thing> things;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TeleportContents(Map targetMap, IntVec3 targetCenter)
|
private void TeleportContents(Map targetMap, IntVec3 targetCenter)
|
||||||
{
|
{
|
||||||
IEnumerable<IntVec3> cells = GenRadial.RadialCellsAround(parent.Position, Props.radius, true);
|
CellRect rect = CellRect.CenteredOn(parent.Position, Props.areaSize.x, Props.areaSize.z);
|
||||||
List<CellData> dataToTeleport = new List<CellData>();
|
|
||||||
IntVec3 center = parent.Position;
|
IntVec3 center = parent.Position;
|
||||||
|
|
||||||
|
List<Thing> thingsToTeleport = new List<Thing>();
|
||||||
|
List<Pair<IntVec3, TerrainDef>> terrainToTeleport = new List<Pair<IntVec3, TerrainDef>>();
|
||||||
|
|
||||||
|
Log.Message($"[WULA] Collecting data from {rect.Area} cells around {center} with size {Props.areaSize}");
|
||||||
|
|
||||||
// 1. 收集数据
|
// 1. 收集数据
|
||||||
foreach (IntVec3 cell in cells)
|
HashSet<Thing> collectedThings = new HashSet<Thing>();
|
||||||
|
foreach (IntVec3 cell in rect)
|
||||||
{
|
{
|
||||||
if (!cell.InBounds(parent.Map)) continue;
|
if (!cell.InBounds(parent.Map)) continue;
|
||||||
|
|
||||||
CellData data = new CellData
|
terrainToTeleport.Add(new Pair<IntVec3, TerrainDef>(cell - center, cell.GetTerrain(parent.Map)));
|
||||||
{
|
|
||||||
relativePos = cell - center,
|
|
||||||
terrain = cell.GetTerrain(parent.Map),
|
|
||||||
things = new List<Thing>()
|
|
||||||
};
|
|
||||||
|
|
||||||
List<Thing> thingList = parent.Map.thingGrid.ThingsListAt(cell);
|
List<Thing> thingList = parent.Map.thingGrid.ThingsListAt(cell);
|
||||||
for (int i = thingList.Count - 1; i >= 0; i--)
|
for (int i = thingList.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Thing t = thingList[i];
|
Thing t = thingList[i];
|
||||||
if (t.def.category == ThingCategory.Item ||
|
if (t != parent && !collectedThings.Contains(t) &&
|
||||||
t.def.category == ThingCategory.Pawn ||
|
(t.def.category == ThingCategory.Item ||
|
||||||
t.def.category == ThingCategory.Building)
|
t.def.category == ThingCategory.Pawn ||
|
||||||
|
t.def.category == ThingCategory.Building))
|
||||||
{
|
{
|
||||||
if (t != parent && !t.def.destroyable) continue;
|
if (!t.def.destroyable) continue;
|
||||||
if (t != parent) data.things.Add(t);
|
|
||||||
|
collectedThings.Add(t);
|
||||||
|
thingsToTeleport.Add(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataToTeleport.Add(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 执行传送
|
// 2. 准备传送 (PreSwapMap)
|
||||||
foreach (CellData data in dataToTeleport)
|
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);
|
newPos = newPos.ClampInsideMap(targetMap);
|
||||||
|
|
||||||
// 2.1 传送地形
|
List<Thing> targetThings = targetMap.thingGrid.ThingsListAt(newPos);
|
||||||
if (data.terrain != null)
|
for (int i = targetThings.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
List<Thing> targetThings = targetMap.thingGrid.ThingsListAt(newPos);
|
if (targetThings[i].def.destroyable) targetThings[i].Destroy();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.2 传送物体
|
if (pair.Second != null)
|
||||||
foreach (Thing t in data.things)
|
|
||||||
{
|
{
|
||||||
if (t.Destroyed) continue;
|
targetMap.terrainGrid.SetTerrain(newPos, pair.Second);
|
||||||
|
parent.Map.terrainGrid.SetTerrain(center + pair.First, TerrainDefOf.Soil);
|
||||||
if (t.Spawned) t.DeSpawn();
|
|
||||||
GenSpawn.Spawn(t, newPos, targetMap, t.Rotation);
|
|
||||||
|
|
||||||
if (t is Pawn p)
|
|
||||||
{
|
|
||||||
p.jobs.StopAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 传送自身
|
// 5. 放置到新地图 (Spawn)
|
||||||
if (parent.Spawned) parent.DeSpawn();
|
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);
|
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);
|
CameraJumper.TryJump(targetCenter, targetMap);
|
||||||
Props.teleportSound?.PlayOneShot(new TargetInfo(targetCenter, targetMap, false));
|
Props.teleportSound?.PlayOneShot(new TargetInfo(targetCenter, targetMap, false));
|
||||||
Messages.Message("WULA_TeleportSuccessful".Translate(), new TargetInfo(targetCenter, targetMap, false), MessageTypeDefOf.PositiveEvent);
|
Messages.Message("WULA_TeleportSuccessful".Translate(), new TargetInfo(targetCenter, targetMap, false), MessageTypeDefOf.PositiveEvent);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
public class CompProperties_MapTeleporter : CompProperties
|
public class CompProperties_MapTeleporter : CompProperties
|
||||||
{
|
{
|
||||||
public float radius = 5f;
|
public IntVec2 areaSize = new IntVec2(13, 13);
|
||||||
public int warmupTicks = 120;
|
public int warmupTicks = 120;
|
||||||
public EffecterDef warmupEffecter;
|
public EffecterDef warmupEffecter;
|
||||||
public SoundDef warmupSound;
|
public SoundDef warmupSound;
|
||||||
|
|||||||
@@ -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<CompMapTeleporter>();
|
||||||
|
|
||||||
|
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<Gizmo> 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<Texture2D>.Get("UI/Commands/LaunchShip"),
|
||||||
|
action = Confirm
|
||||||
|
};
|
||||||
|
|
||||||
|
yield return new Command_Action
|
||||||
|
{
|
||||||
|
defaultLabel = "WULA_MoveMarker".Translate(),
|
||||||
|
defaultDesc = "WULA_MoveMarkerDesc".Translate(),
|
||||||
|
icon = ContentFinder<Texture2D>.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
<!-- 1. 基本额外伤害配置 -->
|
|
||||||
<DamageDef>
|
|
||||||
<defName>Damage_WithExtraEffects</defName>
|
|
||||||
<label>带电击伤害</label>
|
|
||||||
<workerClass>WulaFallenEmpire.DamageWorker_ExtraDamage</workerClass>
|
|
||||||
|
|
||||||
<modExtensions>
|
|
||||||
<li Class="WulaFallenEmpire.DamageDef_ExtraDamageExtension">
|
|
||||||
<extraLabel>电击效果</extraLabel>
|
|
||||||
<showExtraLog>true</showExtraLog>
|
|
||||||
|
|
||||||
<extraDamages>
|
|
||||||
<li>
|
|
||||||
<damageDef>EMP</damageDef>
|
|
||||||
<amount>15</amount>
|
|
||||||
<isPercentage>false</isPercentage>
|
|
||||||
<armorPenetration>25</armorPenetration>
|
|
||||||
<soundDef>EMP_Small</soundDef>
|
|
||||||
<fleckDef>ElectricArc</fleckDef>
|
|
||||||
<minTriggerDamage>5</minTriggerDamage>
|
|
||||||
|
|
||||||
<conditions>
|
|
||||||
<li>
|
|
||||||
<targetType>Mechanoid</targetType>
|
|
||||||
<healthPercentRange>0,1</healthPercentRange>
|
|
||||||
</li>
|
|
||||||
</conditions>
|
|
||||||
</li>
|
|
||||||
</extraDamages>
|
|
||||||
</li>
|
|
||||||
</modExtensions>
|
|
||||||
</DamageDef>
|
|
||||||
|
|
||||||
<!-- 2. 百分比额外伤害 -->
|
|
||||||
<DamageDef>
|
|
||||||
<defName>Damage_WithBurn</defName>
|
|
||||||
<label>带燃烧伤害</label>
|
|
||||||
<workerClass>WulaFallenEmpire.DamageWorker_ExtraDamage</workerClass>
|
|
||||||
|
|
||||||
<modExtensions>
|
|
||||||
<li Class="WulaFallenEmpire.DamageDef_ExtraDamageExtension">
|
|
||||||
<extraLabel>燃烧效果</extraLabel>
|
|
||||||
|
|
||||||
<extraDamages>
|
|
||||||
<li>
|
|
||||||
<damageDef>Burn</damageDef>
|
|
||||||
<isPercentage>true</isPercentage>
|
|
||||||
<percentageMultiplier>0.3</percentageMultiplier>
|
|
||||||
<effecterDef>SparkHit</effecterDef>
|
|
||||||
<minTriggerDamage>10</minTriggerDamage>
|
|
||||||
|
|
||||||
<conditions>
|
|
||||||
<li>
|
|
||||||
<targetType>Pawn</targetType>
|
|
||||||
<healthPercentRange>0.3,1</healthPercentRange>
|
|
||||||
<requiredTags>
|
|
||||||
<li>Flammable</li>
|
|
||||||
</requiredTags>
|
|
||||||
</li>
|
|
||||||
</conditions>
|
|
||||||
</li>
|
|
||||||
</extraDamages>
|
|
||||||
</li>
|
|
||||||
</modExtensions>
|
|
||||||
</DamageDef>
|
|
||||||
|
|
||||||
<!-- 3. 多种额外伤害 -->
|
|
||||||
<DamageDef>
|
|
||||||
<defName>Damage_MultiEffect</defName>
|
|
||||||
<label>多重效果伤害</label>
|
|
||||||
<workerClass>WulaFallenEmpire.DamageWorker_ExtraDamage</workerClass>
|
|
||||||
|
|
||||||
<modExtensions>
|
|
||||||
<li Class="WulaFallenEmpire.DamageDef_ExtraDamageExtension">
|
|
||||||
<extraLabel>组合效果</extraLabel>
|
|
||||||
|
|
||||||
<extraDamages>
|
|
||||||
<!-- 对生物造成流血 -->
|
|
||||||
<li>
|
|
||||||
<damageDef>Cut</damageDef>
|
|
||||||
<amount>5</amount>
|
|
||||||
<isPercentage>false</isPercentage>
|
|
||||||
<targetBodyPart>Torso</targetBodyPart>
|
|
||||||
|
|
||||||
<conditions>
|
|
||||||
<li>
|
|
||||||
<targetType>Animal</targetType>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<targetType>Humanlike</targetType>
|
|
||||||
</li>
|
|
||||||
</conditions>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- 对机械造成EMP -->
|
|
||||||
<li>
|
|
||||||
<damageDef>EMP</damageDef>
|
|
||||||
<isPercentage>true</isPercentage>
|
|
||||||
<percentageMultiplier>0.5</percentageMultiplier>
|
|
||||||
<canBeBlockedByArmor>false</canBeBlockedByArmor>
|
|
||||||
|
|
||||||
<conditions>
|
|
||||||
<li>
|
|
||||||
<targetType>Mechanoid</targetType>
|
|
||||||
</li>
|
|
||||||
</conditions>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- 对建筑造成额外伤害 -->
|
|
||||||
<li>
|
|
||||||
<damageDef>Blunt</damageDef>
|
|
||||||
<amount>20</amount>
|
|
||||||
<isPercentage>false</isPercentage>
|
|
||||||
|
|
||||||
<conditions>
|
|
||||||
<li>
|
|
||||||
<targetType>Building</targetType>
|
|
||||||
</li>
|
|
||||||
</conditions>
|
|
||||||
</li>
|
|
||||||
</extraDamages>
|
|
||||||
</li>
|
|
||||||
</modExtensions>
|
|
||||||
</DamageDef>
|
|
||||||
|
|
||||||
<!-- 4. 武器使用这个伤害类型 -->
|
|
||||||
<ThingDef>
|
|
||||||
<defName>Gun_AdvancedRifle</defName>
|
|
||||||
<label>先进步枪</label>
|
|
||||||
|
|
||||||
<verbs>
|
|
||||||
<li>
|
|
||||||
<verbClass>Verb_Shoot</verbClass>
|
|
||||||
<defaultProjectile>Bullet_Advanced</defaultProjectile>
|
|
||||||
</li>
|
|
||||||
</verbs>
|
|
||||||
</ThingDef>
|
|
||||||
|
|
||||||
<!-- 5. 抛射体定义 -->
|
|
||||||
<ThingDef>
|
|
||||||
<defName>Bullet_Advanced</defName>
|
|
||||||
<label>先进子弹</label>
|
|
||||||
<projectile>
|
|
||||||
<damageDef>Damage_MultiEffect</damageDef>
|
|
||||||
<damageAmountBase>25</damageAmountBase>
|
|
||||||
</projectile>
|
|
||||||
</ThingDef>
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using RimWorld;
|
using RimWorld;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Verse;
|
using Verse;
|
||||||
@@ -9,14 +10,18 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
private CompMapTeleporter teleporter;
|
private CompMapTeleporter teleporter;
|
||||||
private Map targetMap;
|
private Map targetMap;
|
||||||
|
private WULA_TeleportLandingMarker marker;
|
||||||
|
private List<Thing> thingsToTeleport = new List<Thing>();
|
||||||
|
private IntVec3 sourceCenter;
|
||||||
|
|
||||||
public override string Label => "WULA_SelectArrivalPoint".Translate();
|
public override string Label => "WULA_SelectArrivalPoint".Translate();
|
||||||
public override string Desc => "WULA_SelectArrivalPointDesc".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.teleporter = teleporter;
|
||||||
this.targetMap = targetMap;
|
this.targetMap = targetMap;
|
||||||
|
this.marker = marker;
|
||||||
this.useMouseIcon = true;
|
this.useMouseIcon = true;
|
||||||
this.soundDragSustain = SoundDefOf.Designate_DragStandard;
|
this.soundDragSustain = SoundDefOf.Designate_DragStandard;
|
||||||
this.soundDragChanged = SoundDefOf.Designate_DragStandard_Changed;
|
this.soundDragChanged = SoundDefOf.Designate_DragStandard_Changed;
|
||||||
@@ -27,9 +32,9 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
if (!loc.InBounds(targetMap)) return false;
|
if (!loc.InBounds(targetMap)) return false;
|
||||||
|
|
||||||
// 检查半径区域是否有效
|
// 检查区域是否有效
|
||||||
float radius = teleporter.Props.radius;
|
CellRect rect = CellRect.CenteredOn(loc, teleporter.Props.areaSize.x, teleporter.Props.areaSize.z);
|
||||||
foreach (IntVec3 cell in GenRadial.RadialCellsAround(loc, radius, true))
|
foreach (IntVec3 cell in rect)
|
||||||
{
|
{
|
||||||
if (!cell.InBounds(targetMap)) return "WULA_OutOfBounds".Translate();
|
if (!cell.InBounds(targetMap)) return "WULA_OutOfBounds".Translate();
|
||||||
|
|
||||||
@@ -71,19 +76,92 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
public override void DesignateSingleCell(IntVec3 c)
|
public override void DesignateSingleCell(IntVec3 c)
|
||||||
{
|
{
|
||||||
teleporter.ConfirmArrival(c, targetMap);
|
if (marker != null)
|
||||||
Find.DesignatorManager.Deselect();
|
{
|
||||||
|
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()
|
public override void Selected()
|
||||||
{
|
{
|
||||||
GenDraw.DrawRadiusRing(UI.MouseCell(), teleporter.Props.radius);
|
CacheThings();
|
||||||
|
DrawRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SelectedUpdate()
|
||||||
|
{
|
||||||
|
DrawRect();
|
||||||
|
DrawGhosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawMouseAttachments()
|
public override void DrawMouseAttachments()
|
||||||
{
|
{
|
||||||
base.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崩溃
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user