diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index 0811d107..0b0ef4d8 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/Assemblies/WulaFallenEmpire.pdb b/1.6/1.6/Assemblies/WulaFallenEmpire.pdb
index 1144fdc1..59c3f600 100644
Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.pdb and b/1.6/1.6/Assemblies/WulaFallenEmpire.pdb differ
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 cab90bf5..b3a867fc 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml
@@ -186,5 +186,6 @@
[P.I.A 轨道监视] 对敌方({0} 个目标)发射链炮扫射。
[P.I.A 轨道监视] 帝国舰队已抵达轨道。
[P.I.A 轨道监视] 航道已净空。
+ [P.I.A 轨道监视] 对敌方建筑/炮台发射炮击。
diff --git a/Source/WulaFallenEmpire/EventSystem/AI/CompAbilityEffect_EnableOverwatch.cs b/Source/WulaFallenEmpire/EventSystem/AI/CompAbilityEffect_EnableOverwatch.cs
index f4a09294..9d140f3f 100644
--- a/Source/WulaFallenEmpire/EventSystem/AI/CompAbilityEffect_EnableOverwatch.cs
+++ b/Source/WulaFallenEmpire/EventSystem/AI/CompAbilityEffect_EnableOverwatch.cs
@@ -8,6 +8,7 @@ namespace WulaFallenEmpire
public class CompProperties_AbilityEnableOverwatch : CompProperties_AbilityEffect
{
public int durationSeconds = 180; // Default 3 minutes
+ public bool useArtilleryVersion = false; // Both use normal mothership by default
public CompProperties_AbilityEnableOverwatch()
{
@@ -37,7 +38,7 @@ namespace WulaFallenEmpire
map.components.Add(overwatch);
}
- overwatch.EnableOverwatch(Props.durationSeconds);
+ overwatch.EnableOverwatch(Props.durationSeconds, Props.useArtilleryVersion);
}
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
diff --git a/Source/WulaFallenEmpire/EventSystem/AI/MapComponent_AIOverwatch.cs b/Source/WulaFallenEmpire/EventSystem/AI/MapComponent_AIOverwatch.cs
index 9e811e5e..07d929a2 100644
--- a/Source/WulaFallenEmpire/EventSystem/AI/MapComponent_AIOverwatch.cs
+++ b/Source/WulaFallenEmpire/EventSystem/AI/MapComponent_AIOverwatch.cs
@@ -26,7 +26,8 @@ namespace WulaFallenEmpire.EventSystem.AI
{
}
- public void EnableOverwatch(int durationSeconds)
+ // useArtilleryVersion: false = WULA_MotherShip (normal), true = WULA_MotherShip_Planet_Interdiction (artillery)
+ public void EnableOverwatch(int durationSeconds, bool useArtilleryVersion = false)
{
if (this.enabled)
{
@@ -43,7 +44,7 @@ namespace WulaFallenEmpire.EventSystem.AI
this.globalCooldownTicks = 0;
// Call fleet when overwatch starts
- TryCallFleet();
+ TryCallFleet(useArtilleryVersion);
Messages.Message("WULA_AIOverwatch_Engaged".Translate(clampedDuration), MessageTypeDefOf.PositiveEvent);
}
@@ -59,14 +60,16 @@ namespace WulaFallenEmpire.EventSystem.AI
Messages.Message("WULA_AIOverwatch_Disengaged".Translate(), MessageTypeDefOf.NeutralEvent);
}
- private void TryCallFleet()
+ private void TryCallFleet(bool useArtilleryVersion)
{
try
{
- var flyOverDef = DefDatabase.GetNamedSilentFail("WULA_MotherShip_Planet_Interdiction");
+ // Choose mothership version based on parameter
+ string defName = useArtilleryVersion ? "WULA_MotherShip_Planet_Interdiction" : "WULA_MotherShip";
+ var flyOverDef = DefDatabase.GetNamedSilentFail(defName);
if (flyOverDef == null)
{
- WulaLog.Debug("[AI Overwatch] Could not find WULA_MotherShip_Planet_Interdiction ThingDef.");
+ WulaLog.Debug($"[AI Overwatch] Could not find {defName} ThingDef.");
return;
}
@@ -80,14 +83,14 @@ namespace WulaFallenEmpire.EventSystem.AI
startPos,
endPos,
map,
- speed: 0.02f, // Slower for mothership
+ speed: useArtilleryVersion ? 0.02f : 0.01f, // Artillery version slower
height: 20f
);
if (flyOver != null)
{
Messages.Message("WULA_AIOverwatch_FleetCalled".Translate(), MessageTypeDefOf.PositiveEvent);
- WulaLog.Debug($"[AI Overwatch] Called fleet: WULA_MotherShip_Planet_Interdiction spawned from {startPos} to {endPos}.");
+ WulaLog.Debug($"[AI Overwatch] Called fleet: {defName} spawned from {startPos} to {endPos}.");
}
}
catch (Exception ex)
@@ -206,26 +209,65 @@ namespace WulaFallenEmpire.EventSystem.AI
private void PerformScanAndStrike()
{
- // Gather all valid hostile targets
- List hostiles = map.mapPawns.AllPawnsSpawned
+ // Gather all valid hostile pawn targets
+ List hostilePawns = map.mapPawns.AllPawnsSpawned
.Where(p => !p.Dead && !p.Downed && p.HostileTo(Faction.OfPlayer) && !p.IsPrisoner)
.ToList();
- if (hostiles.Count == 0) return;
+ // Gather all hostile buildings (turrets, etc.)
+ List hostileBuildings = map.listerBuildings.allBuildingsColonist
+ .Concat(map.listerThings.ThingsInGroup(ThingRequestGroup.BuildingArtificial).OfType())
+ .Where(b => b != null && !b.Destroyed && b.Faction != null && b.Faction.HostileTo(Faction.OfPlayer))
+ .Distinct()
+ .ToList();
- // Simple clustering: Group hostiles that are close to each other
- var clusters = ClusterPawns(hostiles, 12f); // 12 tile radius for a cluster
+ // Convert building positions to "virtual targets" for processing
+ List buildingTargets = hostileBuildings.Select(b => b.Position).ToList();
- // Prioritize larger clusters
- clusters.Sort((a, b) => b.Count.CompareTo(a.Count)); // Descending order
-
- // Process clusters
_strikesThisScan = 0;
- foreach (var cluster in clusters)
+ // Process hostile pawns first (clustered)
+ if (hostilePawns.Count > 0)
{
- if (globalCooldownTicks > 0) break;
- ProcessCluster(cluster);
+ var clusters = ClusterPawns(hostilePawns, 12f);
+ clusters.Sort((a, b) => b.Count.CompareTo(a.Count));
+
+ foreach (var cluster in clusters)
+ {
+ if (globalCooldownTicks > 0) break;
+ if (_strikesThisScan >= 3) break;
+ ProcessCluster(cluster);
+ }
+ }
+
+ // Process hostile buildings (each as individual target)
+ foreach (var buildingPos in buildingTargets)
+ {
+ if (globalCooldownTicks > 0) break;
+ if (_strikesThisScan >= 3) break;
+ ProcessBuildingTarget(buildingPos);
+ }
+ }
+
+ private void ProcessBuildingTarget(IntVec3 target)
+ {
+ if (!target.InBounds(map)) return;
+
+ float safetyRadius = 9.9f; // Medium safety for building strikes
+ if (IsFriendlyFireRisk(target, safetyRadius))
+ {
+ Messages.Message("WULA_AIOverwatch_FriendlyFireAbort".Translate(target.ToString()), new TargetInfo(target, map), MessageTypeDefOf.CautionInput);
+ return;
+ }
+
+ // Use cannon salvo for buildings (good balance of damage and precision)
+ var cannonDef = DefDatabase.GetNamedSilentFail("WULA_Firepower_Cannon_Salvo");
+ if (cannonDef != null)
+ {
+ Messages.Message("WULA_AIOverwatch_EngagingBuilding".Translate(), new TargetInfo(target, map), MessageTypeDefOf.PositiveEvent);
+ WulaLog.Debug($"[AI Overwatch] Engaging hostile building at {target} with Cannon Salvo.");
+ FireAbility(cannonDef, target, Rand.Range(0, 360));
+ _strikesThisScan++;
}
}