diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index f50252aa..27287dba 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_Races/Races_Wulaspecies.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
index d4ceae68..560f0f3e 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies.xml
@@ -970,6 +970,270 @@
+
+
+ Wula_Mech_Mobile_Factory
+
+ 乌拉帝国的大型战争机械,简直就是一座移动堡垒——它不仅装甲厚实、火炮林立,还能在战场上生产大量的辅助战争机械以形成坚实的弹性阵线,生来就是为了粉碎坚固的堡垒和顽强的抵抗。
+
+ 1
+ 1.5
+ 5
+
+
+ Mech_Warqueen
+ 30
+
+
+ MechanoidFullyFormed
+ 0
+ Pawn_Mech_Warqueen_Wounded
+ Pawn_Mech_Warqueen_Death
+ Pawn_Mech_Warqueen_Call
+
+
+ 25
+
+
+
+
+
+
+ Blunt
+
+ 360
+ 8
+ Torso
+ true
+
+
+
+
+ 0
+ Wula_CR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (-1, 0, -1.45)
+ true
+ -5
+
+
+ 90
+ -5
+ (2.15, 0, -1)
+
+
+ -90
+ (1, 0, -1.45)
+
+
+ 90
+ (-2.15, 0, -1)
+
+
+
+
+
+
+ 1
+ Wula_CR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (1, 0, -1.45)
+ -5
+
+
+ -90
+ (2.15, 0, -1)
+
+
+ -90
+ (-1, 0, -1.45)
+
+
+ 90
+ (-2.15, 0, -1)
+ -5
+
+
+
+
+
+
+ 2
+ Wula_MR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (-1.3, 0, -0.45)
+ true
+ -5
+
+
+ 90
+ -5
+ (1.4, 0, -0.35)
+
+
+ -90
+ (1.3, 0, -0.45)
+
+
+ 90
+ (-1.4, 0, -0.35)
+
+
+
+
+
+
+ 3
+ Wula_MR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (1.3, 0, -0.45)
+ true
+ -5
+
+
+ -90
+ (1.4, 0, -0.35)
+
+
+ -90
+ (-1.3, 0, -0.45)
+
+
+ 90
+ -5
+ (-1.4, 0, -0.35)
+
+
+
+
+
+
+ 4
+ Wula_LR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (1.25, 0, 0.45)
+ true
+ -5
+
+
+ 90
+ -5
+ (0.6, 0, 0.15)
+
+
+ -90
+ (-1.25, 0, 0.65)
+
+
+ 90
+ (-0.6, 0, 0.15)
+
+
+
+
+
+
+ 5
+ Wula_LR_Mobile_Factory_Turret
+
+
+
+ PawnRenderNode_TurretGun
+ PawnRenderNodeWorker_TurretGun
+ Body
+ (1, 1)
+ 20
+ Any
+
+
+ -90
+ (-1.25, 0, 0.45)
+ true
+ -5
+
+
+ -90
+ (0.6, 0, 0.15)
+
+
+ -90
+ (1.25, 0, 0.65)
+
+
+ 90
+ -5
+ (-0.6, 0, 0.15)
+
+
+
+
+
+
+ 36000
+ 8.2
+ 8.4
+ 0.01
+ 4.0
+ false
+
+
+
+
Wula_AI_Heavy_Panzer
@@ -1355,6 +1619,7 @@
+
WULA_Fxxk_Goose
diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
index a5f51bdd..60649d75 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
@@ -175,362 +175,6 @@
WULA_Mech_Flyer_Melta_Slow
-
- Wula_Mech_Mobile_Factory
-
- 乌拉帝国图书馆的陆行战舰——火力强大,装甲厚重,不仅拥有各种各样的副炮和威力巨大的主炮,还能生产海量的小型机械体掩护行动,是乌拉帝国图书馆战术的典型代表。
-
- 14
- 1.5
- 5
-
-
- Mech_Warqueen
- 30
-
-
- MechanoidFullyFormed
- 0
- Pawn_Mech_Warqueen_Wounded
- Pawn_Mech_Warqueen_Death
- Pawn_Mech_Warqueen_Call
-
-
- 25
-
-
-
-
-
-
- Blunt
-
- 360
- 8
- Torso
- true
-
-
-
-
-
-
-
- true
- 30
- MechanoidsWakeUp
-
-
- Wula_CR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (-1, 0, -1.45)
- true
- -5
-
-
- 90
- -5
- (2.15, 0, -1)
-
-
- -90
- (1, 0, -1.45)
-
-
- 90
- (-2.15, 0, -1)
-
-
-
-
-
-
- Wula_CR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (1, 0, -1.45)
- -5
-
-
- -90
- (2.15, 0, -1)
-
-
- -90
- (-1, 0, -1.45)
-
-
- 90
- (-2.15, 0, -1)
- -5
-
-
-
-
-
-
- Wula_MR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (-1.3, 0, -0.45)
- true
- -5
-
-
- 90
- -5
- (1.4, 0, -0.35)
-
-
- -90
- (1.3, 0, -0.45)
-
-
- 90
- (-1.4, 0, -0.35)
-
-
-
-
-
-
- Wula_MR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (1.3, 0, -0.45)
- true
- -5
-
-
- -90
- (1.4, 0, -0.35)
-
-
- -90
- (-1.3, 0, -0.45)
-
-
- 90
- -5
- (-1.4, 0, -0.35)
-
-
-
-
-
-
- Wula_LR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (1.25, 0, 0.45)
- true
- -5
-
-
- 90
- -5
- (0.6, 0, 0.15)
-
-
- -90
- (-1.25, 0, 0.65)
-
-
- 90
- (-0.6, 0, 0.15)
-
-
-
-
-
-
- Wula_LR_Mobile_Factory_Turret
-
-
-
- PawnRenderNode_TurretGun
- PawnRenderNodeWorker_TurretGun
- Body
- (1, 1)
- 20
- Any
-
-
- -90
- (-1.25, 0, 0.45)
- true
- -5
-
-
- -90
- (0.6, 0, 0.15)
-
-
- -90
- (1.25, 0, 0.65)
-
-
- 90
- -5
- (-0.6, 0, 0.15)
-
-
-
-
-
-
- 36000
- 4.2
- 4.4
- 0.01
- 4.0
- false
-
-
- true
- WULA_MechCarrierSwitchHediff
- Steel
- 500
- 500
- 999
- 9999
-
-
- WULA_Mech_Flyer
- 1
- 50
-
-
- WULA_Mech_Flyer_Slow
- 4
- 600
-
-
- WarqueenWarUrchinsSpawned
- WarUrchinSpawned
-
-
- true
- WULA_MechCarrierSwitchHediff
- Steel
- 500
- 500
- 999
- 9999
-
-
- WULA_Mech_Flyer
- 1
- 50
-
-
- WULA_Mech_Flyer_Slow
- 4
- 600
-
-
- WarqueenWarUrchinsSpawned
- WarUrchinSpawned
-
-
- true
- WULA_MechCarrierSwitchHediff
- Steel
- 500
- 500
- 999
- 9999
-
-
- WULA_Mech_Flyer
- 1
- 50
-
-
- WULA_Mech_Flyer_Slow
- 4
- 600
-
-
- WarqueenWarUrchinsSpawned
- WarUrchinSpawned
-
-
- true
- WULA_MechCarrierSwitchHediff
- Steel
- 500
- 500
- 999
- 9999
-
-
- WULA_Mech_Flyer
- 1
- 50
-
-
- WULA_Mech_Flyer_Slow
- 4
- 600
-
-
- WarqueenWarUrchinsSpawned
- WarUrchinSpawned
-
-
-
Wula_Mech_Mobile_Factory
diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs
deleted file mode 100644
index db52a936..00000000
--- a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/Building_FlyOverBeacon.cs
+++ /dev/null
@@ -1,480 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using UnityEngine;
-using Verse;
-using Verse.AI;
-using Verse.Sound;
-using RimWorld;
-using RimWorld.Planet;
-
-namespace WulaFallenEmpire
-{
- [StaticConstructorOnStartup]
- public class Building_FlyOverBeacon : Building
- {
- public GlobalTargetInfo flyOverTarget;
- public FlyOverConfig flyOverConfig;
- public static readonly Texture2D CallFlyOverTex = ContentFinder.Get("UI/Commands/CallFlyOver", true);
-
- private CompPowerTrader powerComp;
- private CompRefuelable refuelableComp;
- private int cooldownTicksLeft;
-
- public bool IsReady => (powerComp == null || powerComp.PowerOn) &&
- (refuelableComp == null || refuelableComp.HasFuel) &&
- cooldownTicksLeft <= 0;
-
- public override void SpawnSetup(Map map, bool respawningAfterLoad)
- {
- base.SpawnSetup(map, respawningAfterLoad);
- powerComp = this.TryGetComp();
- refuelableComp = this.TryGetComp();
-
- if (!respawningAfterLoad)
- {
- flyOverTarget = GlobalTargetInfo.Invalid;
- flyOverConfig = new FlyOverConfig();
- }
- }
-
- public override void ExposeData()
- {
- base.ExposeData();
- Scribe_TargetInfo.Look(ref flyOverTarget, "flyOverTarget");
- Scribe_Deep.Look(ref flyOverConfig, "flyOverConfig");
- Scribe_Values.Look(ref cooldownTicksLeft, "cooldownTicksLeft", 0);
- }
-
- protected override void Tick()
- {
- base.Tick();
-
- // 冷却计时
- if (cooldownTicksLeft > 0)
- cooldownTicksLeft--;
-
- // 自动执行已设定的飞越任务
- if (flyOverTarget.IsValid && IsReady)
- {
- ExecuteFlyOverMission();
- }
- }
-
- public override string GetInspectString()
- {
- StringBuilder sb = new StringBuilder(base.GetInspectString());
-
- if (cooldownTicksLeft > 0)
- {
- if (sb.Length > 0) sb.AppendLine();
- sb.Append("飞越信标冷却中: ".Translate() + cooldownTicksLeft.ToStringTicksToPeriod());
- }
-
- if (flyOverTarget.IsValid)
- {
- if (sb.Length > 0) sb.AppendLine();
- sb.Append("已锁定目标: ".Translate() + flyOverTarget.Label);
- }
-
- if (!IsReady)
- {
- if (sb.Length > 0) sb.AppendLine();
- if (powerComp != null && !powerComp.PowerOn)
- sb.Append("需要电力".Translate());
- else if (refuelableComp != null && !refuelableComp.HasFuel)
- sb.Append("需要燃料".Translate());
- else if (cooldownTicksLeft > 0)
- sb.Append("冷却中".Translate());
- }
-
- return sb.ToString();
- }
-
- public override IEnumerable GetGizmos()
- {
- foreach (var g in base.GetGizmos())
- {
- yield return g;
- }
-
- // 召唤飞越命令
- Command_Action callFlyOver = new Command_Action
- {
- defaultLabel = "召唤跨图飞越",
- defaultDesc = "在世界地图上选择目标位置召唤飞越单位",
- icon = CallFlyOverTex,
- action = StartChoosingFlyOverTarget
- };
-
- if (!IsReady)
- {
- callFlyOver.Disable(GetDisabledReason());
- }
- yield return callFlyOver;
-
- // 配置飞越参数命令
- if (flyOverTarget.IsValid)
- {
- Command_Action configureFlyOver = new Command_Action
- {
- defaultLabel = "配置飞越参数",
- defaultDesc = "调整飞越单位的类型和行为",
- icon = ContentFinder.Get("UI/Commands/Configure", true),
- action = OpenConfigurationDialog
- };
- yield return configureFlyOver;
-
- // 清除目标命令
- Command_Action clearTarget = new Command_Action
- {
- defaultLabel = "清除目标",
- defaultDesc = "清除已锁定的飞越目标",
- icon = ContentFinder.Get("UI/Designators/Cancel", true),
- action = () => flyOverTarget = GlobalTargetInfo.Invalid
- };
- yield return clearTarget;
- }
- }
-
- private string GetDisabledReason()
- {
- if (powerComp != null && !powerComp.PowerOn)
- return "需要电力";
- if (refuelableComp != null && !refuelableComp.HasFuel)
- return "需要燃料";
- if (cooldownTicksLeft > 0)
- return "冷却中";
- return "无法使用";
- }
-
- private void StartChoosingFlyOverTarget()
- {
- CameraJumper.TryJump(CameraJumper.GetWorldTarget(this));
- Find.WorldSelector.ClearSelection();
-
- Find.WorldTargeter.BeginTargeting(
- ChooseWorldTarget,
- canTargetTiles: true,
- targeterMouseAttachment: CallFlyOverTex,
- extraLabelGetter: GetExtraTargetingLabel
- );
- }
-
- private string GetExtraTargetingLabel(GlobalTargetInfo target)
- {
- if (target.IsValid)
- {
- return "召唤飞越至: " + target.Label;
- }
- return "选择飞越目标位置";
- }
-
- private bool ChooseWorldTarget(GlobalTargetInfo target)
- {
- if (!target.IsValid)
- {
- Messages.Message("无效的目标位置", MessageTypeDefOf.RejectInput);
- return false;
- }
-
- if (target.Tile == this.Map.Tile)
- {
- Messages.Message("无法在同一地图召唤飞越", MessageTypeDefOf.RejectInput);
- return false;
- }
-
- // 处理不同类型的目标
- if (target.WorldObject is MapParent mapParent && mapParent.HasMap)
- {
- // 切换到目标地图选择具体飞越路径
- var originalMap = this.Map;
- Action onFinished = () => {
- if (Current.Game.CurrentMap != originalMap)
- Current.Game.CurrentMap = originalMap;
- };
-
- Current.Game.CurrentMap = mapParent.Map;
- Find.Targeter.BeginTargeting(
- new TargetingParameters
- {
- canTargetLocations = true,
- canTargetPawns = false,
- canTargetBuildings = false,
- mapObjectTargetsMustBeAutoAttackable = false
- },
- (LocalTargetInfo localTarget) =>
- {
- // 设置飞越配置
- flyOverTarget = new GlobalTargetInfo(localTarget.Cell, mapParent.Map);
- flyOverConfig.targetCell = localTarget.Cell;
- flyOverConfig.targetMap = mapParent.Map;
-
- // 自动计算飞越路径
- CalculateFlyOverPath(mapParent.Map, localTarget.Cell);
- },
- null, onFinished, CallFlyOverTex, true);
- }
- else
- {
- // 空地目标,生成临时地图
- flyOverTarget = target;
- flyOverConfig.targetTile = target.Tile;
- CalculateFlyOverPathForTile(target.Tile);
- }
-
- return true;
- }
-
- private void CalculateFlyOverPath(Map targetMap, IntVec3 targetCell)
- {
- // 计算从地图边缘到目标点的飞越路径
- Vector3 targetPos = targetCell.ToVector3();
-
- // 随机选择进入方向
- Vector3[] approachDirections = {
- new Vector3(1, 0, 0), // 从右边进入
- new Vector3(-1, 0, 0), // 从左边进入
- new Vector3(0, 0, 1), // 从上边进入
- new Vector3(0, 0, -1) // 从下边进入
- };
-
- Vector3 approachDir = approachDirections.RandomElement();
- Vector3 startPos = FindMapEdgePosition(targetMap, approachDir);
- Vector3 endPos = FindMapEdgePosition(targetMap, -approachDir); // 从对面飞出
-
- flyOverConfig.startPos = startPos.ToIntVec3();
- flyOverConfig.endPos = endPos.ToIntVec3();
- flyOverConfig.approachType = FlyOverApproachType.StraightLine;
-
- Log.Message($"Calculated flyover path: {flyOverConfig.startPos} -> {targetCell} -> {flyOverConfig.endPos}");
- }
-
- private void CalculateFlyOverPathForTile(int tile)
- {
- // 为地图瓦片计算默认飞越路径(穿越地图中心)
- Map targetMap = GetOrGenerateMapUtility.GetOrGenerateMap(tile, Find.World.info.initialMapSize, null);
- if (targetMap != null)
- {
- targetMap.fogGrid.ClearAllFog(); // 获得视野
-
- IntVec3 center = targetMap.Center;
- CalculateFlyOverPath(targetMap, center);
- }
- }
-
- private IntVec3 FindMapEdgePosition(Map map, Vector3 direction)
- {
- // 找到地图边缘位置
- Vector3 center = map.Center.ToVector3();
- Vector3 edgePos = center;
- float maxDistance = Mathf.Max(map.Size.x, map.Size.z) * 0.6f;
-
- for (int i = 1; i <= maxDistance; i++)
- {
- Vector3 testPos = center + direction.normalized * i;
- IntVec3 testCell = new IntVec3((int)testPos.x, 0, (int)testPos.z);
-
- if (!testCell.InBounds(map))
- {
- // 找到最近的边界内单元格
- return FindClosestValidPosition(testCell, map);
- }
- }
-
- return map.Center;
- }
-
- private IntVec3 FindClosestValidPosition(IntVec3 invalidPos, Map map)
- {
- for (int radius = 1; radius <= 10; radius++)
- {
- foreach (IntVec3 offset in GenRadial.RadialPatternInRadius(radius))
- {
- IntVec3 testPos = invalidPos + offset;
- if (testPos.InBounds(map))
- return testPos;
- }
- }
- return map.Center;
- }
-
- private void OpenConfigurationDialog()
- {
- // 打开飞越配置对话框
- List options = new List
- {
- new FloatMenuOption("标准侦察飞越", () => ConfigureStandardRecon()),
- new FloatMenuOption("地面扫射飞越", () => ConfigureGroundStrafing()),
- new FloatMenuOption("监视巡逻飞越", () => ConfigureSurveillance()),
- new FloatMenuOption("货运投送飞越", () => ConfigureCargoDrop())
- };
-
- Find.WindowStack.Add(new FloatMenu(options));
- }
-
- private void ConfigureStandardRecon()
- {
- flyOverConfig.flyOverType = FlyOverType.Standard;
- flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveScout");
- flyOverConfig.altitude = 20f;
- flyOverConfig.flightSpeed = 1.2f;
- Messages.Message("已配置为标准侦察飞越", MessageTypeDefOf.TaskCompletion);
- }
-
- private void ConfigureGroundStrafing()
- {
- flyOverConfig.flyOverType = FlyOverType.GroundStrafing;
- flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveGunship");
- flyOverConfig.altitude = 10f;
- flyOverConfig.flightSpeed = 0.8f;
- flyOverConfig.enableStrafing = true;
- Messages.Message("已配置为地面扫射飞越", MessageTypeDefOf.TaskCompletion);
- }
-
- private void ConfigureSurveillance()
- {
- flyOverConfig.flyOverType = FlyOverType.Surveillance;
- flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveObserver");
- flyOverConfig.altitude = 25f;
- flyOverConfig.flightSpeed = 0.6f;
- flyOverConfig.enableSurveillance = true;
- Messages.Message("已配置为监视巡逻飞越", MessageTypeDefOf.TaskCompletion);
- }
-
- private void ConfigureCargoDrop()
- {
- flyOverConfig.flyOverType = FlyOverType.CargoDrop;
- flyOverConfig.flyOverDef = DefDatabase.GetNamedSilentFail("ARA_HiveTransport");
- flyOverConfig.altitude = 15f;
- flyOverConfig.flightSpeed = 1.0f;
- flyOverConfig.dropContentsOnImpact = true;
- Messages.Message("已配置为货运投送飞越", MessageTypeDefOf.TaskCompletion);
- }
-
- public void ExecuteFlyOverMission()
- {
- if (!IsReady) return;
-
- try
- {
- Log.Message($"[FlyOverBeacon] Executing flyover mission to {flyOverTarget.Label}");
-
- // 创建世界飞越载体
- WorldObject_FlyOverCarrier carrier = (WorldObject_FlyOverCarrier)WorldObjectMaker.MakeWorldObject(
- DefDatabase.GetNamed("FlyOverCarrier")
- );
-
- carrier.Tile = this.Map.Tile;
- carrier.destinationTile = flyOverTarget.Tile;
- carrier.flyOverConfig = flyOverConfig.Clone();
- carrier.sourceBeacon = this;
-
- Find.WorldObjects.Add(carrier);
-
- // 本地视觉效果
- CreateLocalLaunchEffects();
-
- // 资源消耗
- if (refuelableComp != null)
- refuelableComp.ConsumeFuel(1);
-
- // 进入冷却
- cooldownTicksLeft = 6000; // 1分钟冷却
-
- Messages.Message($"飞越单位已派遣至 {flyOverTarget.Label}", MessageTypeDefOf.PositiveEvent);
-
- }
- catch (Exception ex)
- {
- Log.Error($"Error executing flyover mission: {ex}");
- Messages.Message("飞越任务执行失败", MessageTypeDefOf.NegativeEvent);
- }
- }
-
- private void CreateLocalLaunchEffects()
- {
- // 发射视觉效果
- MoteMaker.MakeStaticMote(this.DrawPos, this.Map, ThingDefOf.Mote_ExplosionFlash, 3f);
-
- for (int i = 0; i < 3; i++)
- {
- FleckMaker.ThrowSmoke(this.DrawPos, this.Map, 2f);
- FleckMaker.ThrowLightningGlow(this.DrawPos, this.Map, 1.5f);
- }
-
- // 发射音效
- SoundDefOf.PsychicPulseGlobal.PlayOneShot(new TargetInfo(this.Position, this.Map));
- }
- }
-
- // 飞越配置类
- public class FlyOverConfig : IExposable
- {
- public ThingDef flyOverDef;
- public FlyOverType flyOverType = FlyOverType.Standard;
- public IntVec3 startPos;
- public IntVec3 endPos;
- public IntVec3 targetCell;
- public Map targetMap;
- public int targetTile = -1;
- public float flightSpeed = 1f;
- public float altitude = 15f;
- public bool dropContentsOnImpact = false;
- public bool enableStrafing = false;
- public bool enableSurveillance = false;
- public FlyOverApproachType approachType = FlyOverApproachType.StraightLine;
-
- public void ExposeData()
- {
- Scribe_Defs.Look(ref flyOverDef, "flyOverDef");
- Scribe_Values.Look(ref flyOverType, "flyOverType", FlyOverType.Standard);
- Scribe_Values.Look(ref startPos, "startPos");
- Scribe_Values.Look(ref endPos, "endPos");
- Scribe_Values.Look(ref targetCell, "targetCell");
- Scribe_References.Look(ref targetMap, "targetMap");
- Scribe_Values.Look(ref targetTile, "targetTile", -1);
- Scribe_Values.Look(ref flightSpeed, "flightSpeed", 1f);
- Scribe_Values.Look(ref altitude, "altitude", 15f);
- Scribe_Values.Look(ref dropContentsOnImpact, "dropContentsOnImpact", false);
- Scribe_Values.Look(ref enableStrafing, "enableStrafing", false);
- Scribe_Values.Look(ref enableSurveillance, "enableSurveillance", false);
- Scribe_Values.Look(ref approachType, "approachType", FlyOverApproachType.StraightLine);
- }
-
- public FlyOverConfig Clone()
- {
- return new FlyOverConfig
- {
- flyOverDef = this.flyOverDef,
- flyOverType = this.flyOverType,
- startPos = this.startPos,
- endPos = this.endPos,
- targetCell = this.targetCell,
- targetMap = this.targetMap,
- targetTile = this.targetTile,
- flightSpeed = this.flightSpeed,
- altitude = this.altitude,
- dropContentsOnImpact = this.dropContentsOnImpact,
- enableStrafing = this.enableStrafing,
- enableSurveillance = this.enableSurveillance,
- approachType = this.approachType
- };
- }
- }
-
- public enum FlyOverType
- {
- Standard,
- GroundStrafing,
- Surveillance,
- CargoDrop
- }
-
- public enum FlyOverApproachType
- {
- StraightLine,
- CirclePattern,
- FigureEight
- }
-}
diff --git a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs b/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs
deleted file mode 100644
index 92a533b6..00000000
--- a/Source/WulaFallenEmpire/BuildingComp/WULA_FlyOverBeacon/WorldObject_FlyOverCarrier.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-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.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();
- if (strafingComp != null)
- {
- // 计算扫射区域
- Vector3 flightDirection = (flyOverConfig.endPos.ToVector3() - flyOverConfig.startPos.ToVector3()).normalized;
- List impactCells = CalculateStrafingImpactCells(flyOverConfig.targetCell, flightDirection);
- List confirmedTargets = PreprocessStrafingTargets(impactCells, 0.7f);
-
- strafingComp.SetConfirmedTargets(confirmedTargets);
- }
- }
-
- // 监视功能配置
- if (flyOverConfig.enableSurveillance)
- {
- // 可以在这里添加监视组件的配置
- Log.Message("[FlyOverCarrier] Surveillance mode configured");
- }
- }
-
- private List CalculateStrafingImpactCells(IntVec3 targetCell, Vector3 flightDirection)
- {
- // 简化的扫射区域计算
- List cells = new List();
- 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 PreprocessStrafingTargets(List potentialTargets, float fireChance)
- {
- List confirmedTargets = new List();
-
- 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));
- }
- }
-}
diff --git a/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs b/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs
new file mode 100644
index 00000000..2ad4d4bf
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/Comp_MultiTurretGun.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using Verse;
+using Verse.AI;
+using RimWorld;
+using UnityEngine;
+
+namespace WulaFallenEmpire
+{
+ public class CompProperties_MultiTurretGun : CompProperties_TurretGun
+ {
+ public int ID;
+ public CompProperties_MultiTurretGun()
+ {
+ compClass = typeof(Comp_MultiTurretGun);
+ }
+ }
+ public class Comp_MultiTurretGun : CompTurretGun
+ {
+ private bool fireAtWill = true;
+ public new CompProperties_MultiTurretGun Props => (CompProperties_MultiTurretGun)props;
+ public override void CompTick()
+ {
+ base.CompTick();
+ if (!currentTarget.IsValid && burstCooldownTicksLeft <= 0)
+ {
+ // 在其他情况下没有目标且冷却结束时也回正
+ curRotation = parent.Rotation.AsAngle + Props.angleOffset;
+ }
+ }
+ private void MakeGun()
+ {
+ gun = ThingMaker.MakeThing(Props.turretDef);
+ UpdateGunVerbs();
+ }
+ private void UpdateGunVerbs()
+ {
+ List allVerbs = gun.TryGetComp().AllVerbs;
+ for (int i = 0; i < allVerbs.Count; i++)
+ {
+ Verb verb = allVerbs[i];
+ verb.caster = parent;
+ verb.castCompleteCallback = delegate
+ {
+ burstCooldownTicksLeft = AttackVerb.verbProps.defaultCooldownTime.SecondsToTicks();
+ };
+ }
+ }
+ public override void PostExposeData()
+ {
+ Scribe_Values.Look(ref burstCooldownTicksLeft, "burstCooldownTicksLeft", 0);
+ Scribe_Values.Look(ref burstWarmupTicksLeft, "burstWarmupTicksLeft", 0);
+ Scribe_TargetInfo.Look(ref currentTarget, "currentTarget_" + Props.ID);
+ Scribe_Deep.Look(ref gun, "gun_" + Props.ID);
+ Scribe_Values.Look(ref fireAtWill, "fireAtWill", defaultValue: true);
+ if (Scribe.mode == LoadSaveMode.PostLoadInit)
+ {
+ if (gun == null)
+ {
+ Log.Error("CompTurrentGun had null gun after loading. Recreating.");
+ MakeGun();
+ }
+ else
+ {
+ UpdateGunVerbs();
+ }
+ }
+ }
+ }
+
+}
diff --git a/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs b/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs
new file mode 100644
index 00000000..59e9c278
--- /dev/null
+++ b/Source/WulaFallenEmpire/Pawn/Comp_PawnRenderExtra.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Reflection.Emit;
+using System.Runtime.Remoting.Messaging;
+using RimWorld;
+using UnityEngine;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class CompProperties_PawnRenderExtra : CompProperties
+ {
+ public CompProperties_PawnRenderExtra()
+ {
+ this.compClass = typeof(Comp_PawnRenderExtra);
+ }
+
+ public string path;
+
+ public Vector3 size;
+
+ public Color colorAlly;
+
+ public Color colorEnemy;
+
+ public ShaderTypeDef shader;
+
+ public DrawData drawData;
+ }
+ [StaticConstructorOnStartup]
+ public class Comp_PawnRenderExtra : ThingComp
+ {
+ public CompProperties_PawnRenderExtra Props
+ {
+ get
+ {
+ return this.props as CompProperties_PawnRenderExtra;
+ }
+ }
+
+ private Pawn ParentPawn
+ {
+ get
+ {
+ return this.parent as Pawn;
+ }
+ }
+
+ public override void PostDraw()
+ {
+ base.PostDraw();
+ if (!this.ParentPawn.Dead && !this.ParentPawn.Downed && this.ParentPawn.CurJobDef != JobDefOf.MechCharge && this.ParentPawn.CurJobDef != JobDefOf.SelfShutdown)
+ {
+ this.DrawPawnRenderExtra();
+ }
+ }
+
+ public void DrawPawnRenderExtra()
+ {
+ Vector3 pos = this.ParentPawn.DrawPos;
+ if (this.ParentPawn.Faction == Faction.OfPlayer || !this.ParentPawn.Faction.HostileTo(Faction.OfPlayer))
+ {
+ this.color = this.Props.colorAlly;
+ }
+ else
+ {
+ this.color = this.Props.colorEnemy;
+ }
+ string graphic = this.GetPawnRenderExtra();
+ Vector3 offset = GetOffsetByRot();
+ float layer = GetLayerByRot();
+ pos.y = AltitudeLayer.Pawn.AltitudeFor(layer);
+
+ Matrix4x4 matrix = default(Matrix4x4);
+ matrix.SetTRS(pos + offset, Quaternion.AngleAxis(0f, Vector3.up), this.Props.size);
+ Material material = MaterialPool.MatFrom(graphic, this.Props.shader.Shader, this.color);
+ Graphics.DrawMesh(MeshPool.plane10, matrix, material, (int)layer);
+ }
+
+ public Vector3 GetOffsetByRot()
+ {
+ Vector3 result;
+ if (this.Props.drawData != null)
+ {
+ result = this.Props.drawData.OffsetForRot(this.ParentPawn.Rotation);
+ }
+ else
+ {
+ result = Vector3.zero;
+ }
+ return result;
+ }
+ public float GetLayerByRot()
+ {
+ float result;
+ if (this.Props.drawData != null)
+ {
+ result = this.Props.drawData.LayerForRot(this.ParentPawn.Rotation, 0);
+ }
+ else
+ {
+ result = 0;
+ }
+ return result;
+ }
+
+ public string GetPawnRenderExtra()
+ {
+ if (this.ParentPawn.Rotation.AsInt == 0)
+ {
+ return this.Props.path + "_north";
+ }
+ if (this.ParentPawn.Rotation.AsInt == 1)
+ {
+ return this.Props.path + "_east";
+ }
+ if (this.ParentPawn.Rotation.AsInt == 2)
+ {
+ return this.Props.path + "_south";
+ }
+ if (this.ParentPawn.Rotation.AsInt == 3)
+ {
+ return this.Props.path + "_west";
+ }
+ return null;
+ }
+ public Color color;
+ }
+}
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index f4a472f1..7f48a92a 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -90,8 +90,6 @@
-
-
@@ -149,6 +147,8 @@
+
+
@@ -280,7 +280,9 @@
-
+
+
+