Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs
2025-11-11 12:00:02 +08:00

242 lines
8.2 KiB
C#

using RimWorld.Planet;
using UnityEngine;
using Verse;
using RimWorld;
using System.Collections.Generic;
namespace WulaFallenEmpire
{
public class WorldObject_FlyOverCarrier : WorldObject
{
public int destinationTile = -1;
public FlyOverConfig flyOverConfig;
public Building_FlyOverBeacon sourceBeacon;
private int initialTile = -1;
private float traveledPct;
private const float TravelSpeed = 0.0001f; // 比导弹慢,适合侦察
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref destinationTile, "destinationTile", -1);
Scribe_Deep.Look(ref flyOverConfig, "flyOverConfig");
Scribe_References.Look(ref sourceBeacon, "sourceBeacon");
Scribe_Values.Look(ref initialTile, "initialTile", -1);
Scribe_Values.Look(ref traveledPct, "traveledPct", 0f);
}
public override void PostAdd()
{
base.PostAdd();
this.initialTile = this.Tile;
Log.Message($"[FlyOverCarrier] Launched from tile {initialTile} to {destinationTile}");
}
private Vector3 StartPos => Find.WorldGrid.GetTileCenter(this.initialTile);
private Vector3 EndPos => Find.WorldGrid.GetTileCenter(this.destinationTile);
public override Vector3 DrawPos => Vector3.Slerp(StartPos, EndPos, traveledPct);
protected override void Tick()
{
base.Tick();
if (this.destinationTile < 0)
{
Log.Error("FlyOverCarrier has invalid destination tile");
Find.WorldObjects.Remove(this);
return;
}
float distance = GenMath.SphericalDistance(StartPos.normalized, EndPos.normalized);
if (distance > 0)
{
traveledPct += TravelSpeed / distance;
}
else
{
traveledPct = 1;
}
// 更新世界图标位置
if (Find.WorldRenderer != null)
{
Find.WorldRenderer.Notify_WorldObjectPosChanged(this);
}
if (traveledPct >= 1f)
{
Arrived();
}
}
private void Arrived()
{
Log.Message($"[FlyOverCarrier] Arrived at destination tile {destinationTile}");
Map targetMap = GetTargetMap();
if (targetMap != null)
{
CreateFlyOverInTargetMap(targetMap);
}
else
{
Log.Warning($"[FlyOverCarrier] Could not find or generate map for tile {destinationTile}");
}
// 通知源信标任务完成
if (sourceBeacon != null && !sourceBeacon.Destroyed)
{
Messages.Message($"飞越单位已到达 {flyOverConfig.targetMap?.Parent?.Label ?? ""}",
sourceBeacon, MessageTypeDefOf.PositiveEvent);
}
Find.WorldObjects.Remove(this);
}
private Map GetTargetMap()
{
// 优先使用配置中的目标地图
if (flyOverConfig.targetMap != null && !flyOverConfig.targetMap.Destroyed)
{
return flyOverConfig.targetMap;
}
// 生成临时地图
return GetOrGenerateMapUtility.GetOrGenerateMap(destinationTile, Find.World.info.initialMapSize, null);
}
private void CreateFlyOverInTargetMap(Map targetMap)
{
if (flyOverConfig.flyOverDef == null)
{
Log.Warning("[FlyOverCarrier] No fly over def specified, using default");
flyOverConfig.flyOverDef = DefDatabase<ThingDef>.GetNamedSilentFail("ARA_HiveScout");
}
// 确保目标地图有视野
targetMap.fogGrid.ClearAllFog();
// 验证并调整飞越路径
IntVec3 startPos = ValidateAndAdjustPosition(flyOverConfig.startPos, targetMap);
IntVec3 endPos = ValidateAndAdjustPosition(flyOverConfig.endPos, targetMap);
Log.Message($"[FlyOverCarrier] Creating flyover: {startPos} -> {endPos} in {targetMap}");
// 创建飞越物体
FlyOver flyOver = FlyOver.MakeFlyOver(
flyOverConfig.flyOverDef,
startPos,
endPos,
targetMap,
flyOverConfig.flightSpeed,
flyOverConfig.altitude,
casterPawn: null
);
// 配置飞越属性
flyOver.spawnContentsOnImpact = flyOverConfig.dropContentsOnImpact;
flyOver.playFlyOverSound = true;
flyOver.faction = sourceBeacon?.Faction;
// 配置特殊组件
ConfigureFlyOverComponents(flyOver);
// 创建到达视觉效果
CreateArrivalEffects(targetMap, startPos);
}
private IntVec3 ValidateAndAdjustPosition(IntVec3 pos, Map map)
{
if (pos.IsValid && pos.InBounds(map))
return pos;
// 如果位置无效,使用地图边缘位置
return CellFinder.RandomEdgeCell(Rand.Range(0, 4), map);
}
private void ConfigureFlyOverComponents(FlyOver flyOver)
{
// 地面扫射配置
if (flyOverConfig.enableStrafing)
{
CompGroundStrafing strafingComp = flyOver.GetComp<CompGroundStrafing>();
if (strafingComp != null)
{
// 计算扫射区域
Vector3 flightDirection = (flyOverConfig.endPos.ToVector3() - flyOverConfig.startPos.ToVector3()).normalized;
List<IntVec3> impactCells = CalculateStrafingImpactCells(flyOverConfig.targetCell, flightDirection);
List<IntVec3> confirmedTargets = PreprocessStrafingTargets(impactCells, 0.7f);
strafingComp.SetConfirmedTargets(confirmedTargets);
}
}
// 监视功能配置
if (flyOverConfig.enableSurveillance)
{
// 可以在这里添加监视组件的配置
Log.Message("[FlyOverCarrier] Surveillance mode configured");
}
}
private List<IntVec3> CalculateStrafingImpactCells(IntVec3 targetCell, Vector3 flightDirection)
{
// 简化的扫射区域计算
List<IntVec3> cells = new List<IntVec3>();
Map map = Find.CurrentMap;
if (map != null)
{
Vector3 perpendicular = new Vector3(-flightDirection.z, 0f, flightDirection.x).normalized;
for (int i = -2; i <= 2; i++)
{
for (int j = -5; j <= 5; j++)
{
Vector3 offset = perpendicular * i + flightDirection * j;
IntVec3 cell = targetCell + new IntVec3((int)offset.x, 0, (int)offset.z);
if (cell.InBounds(map))
{
cells.Add(cell);
}
}
}
}
return cells;
}
private List<IntVec3> PreprocessStrafingTargets(List<IntVec3> potentialTargets, float fireChance)
{
List<IntVec3> confirmedTargets = new List<IntVec3>();
foreach (IntVec3 cell in potentialTargets)
{
if (Rand.Value <= fireChance)
{
confirmedTargets.Add(cell);
}
}
return confirmedTargets;
}
private void CreateArrivalEffects(Map targetMap, IntVec3 entryPos)
{
// 进入视觉效果
MoteMaker.MakeStaticMote(entryPos.ToVector3Shifted(), targetMap, ThingDefOf.Mote_PsycastAreaEffect, 2f);
for (int i = 0; i < 5; i++)
{
FleckMaker.ThrowAirPuffUp(entryPos.ToVector3Shifted(), targetMap);
}
// 进入音效
SoundDefOf.PsychicPulse.PlayOneShot(new TargetInfo(entryPos, targetMap));
}
}
}