diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 87f0f72..d171064 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/ThingDef_Building_CatastropheMissileSilo.xml b/1.6/1.6/Defs/ThingDefs_Buildings/ThingDef_Building_CatastropheMissileSilo.xml index e09d0ef..0919108 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/ThingDef_Building_CatastropheMissileSilo.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/ThingDef_Building_CatastropheMissileSilo.xml @@ -51,6 +51,7 @@
  • +
  • CatastropheMissile_Weapon diff --git a/Source/ArachnaeSwarm/Buildings/Building_CatastropheMissileSilo.cs b/Source/ArachnaeSwarm/Buildings/Building_CatastropheMissileSilo.cs index 591e1a5..23d082c 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_CatastropheMissileSilo.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_CatastropheMissileSilo.cs @@ -31,20 +31,13 @@ namespace ArachnaeSwarm public override void ExposeData() { base.ExposeData(); - // We no longer save/load longTarget here. It is only set by player action. - // Scribe_TargetInfo.Look(ref this.longTarget, "longTarget"); // REMOVED + Scribe_TargetInfo.Look(ref this.longTarget, "longTarget"); } protected override void Tick() { - // --- Attack Priority Logic --- - // Prio 1: Forced Local Target. Let the base class handle it. - if (this.forcedTarget.IsValid) - { - base.Tick(); - return; - } - // Prio 2: Remote Target + // --- Attack Priority Logic (Remote Target has higher priority) --- + // Prio 1: Remote Target if (this.longTarget.IsValid) { if (base.Active && this.burstCooldownTicksLeft <= 0 && CanFireGlobal(out _)) @@ -58,10 +51,15 @@ namespace ArachnaeSwarm this.top.TurretTopTick(); } } - // Prio 3: No manual target, fall back to base auto-targeting. + // Prio 2: Forced Local Target (Only if no remote target) + else if (this.forcedTarget.IsValid) + { + base.Tick(); // Let base class handle it + } + // Prio 3: Auto Target (if no manual targets) else { - base.Tick(); + base.Tick(); // Let base class handle it } } @@ -78,7 +76,7 @@ namespace ArachnaeSwarm public override IEnumerable GetGizmos() { - // Yield base gizmos first, which includes "Set forced target" + // Yield base gizmos first, which includes "Set forced target" and other standard buttons. foreach (var g in base.GetGizmos()) { yield return g; @@ -97,7 +95,7 @@ namespace ArachnaeSwarm { fireGlobal.Disable(reason); } - // Disable if a local forced target is already set + // Global Strike button is disabled if a forced target is already set, to ensure mutual exclusivity. if (this.forcedTarget.IsValid) { fireGlobal.Disable("LocalTargetForced".Translate()); @@ -134,11 +132,12 @@ namespace ArachnaeSwarm missile.Projectile = DefDatabase.GetNamed("Projectile_CatastropheMissile"); Find.WorldObjects.Add(missile); - if (CellFinder.TryFindRandomEdgeCellWith(c => this.Map.reachability.CanReach(this.Position, c, PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly)), this.Map, 0f, out IntVec3 edgeCell)) - { - Projectile_CruiseMissile dummy = (Projectile_CruiseMissile)GenSpawn.Spawn(DefDatabase.GetNamed("Projectile_CatastropheMissile_Fake"), this.Position, this.Map); - dummy?.Launch(this, this.DrawPos, new LocalTargetInfo(edgeCell), new LocalTargetInfo(edgeCell), ProjectileHitFlags.None); - } + // Rimatomics style: dummy projectile flies off-map in the direction the turret is facing. + Vector3 shellDirection = Vector3.forward.RotatedBy(this.top.CurRotation); + IntVec3 outcell = (this.DrawPos + shellDirection * 500f).ToIntVec3(); + + Projectile_CruiseMissile dummy = (Projectile_CruiseMissile)GenSpawn.Spawn(DefDatabase.GetNamed("Projectile_CatastropheMissile_Fake"), this.Position, this.Map); + dummy?.Launch(this, this.DrawPos, new LocalTargetInfo(outcell), new LocalTargetInfo(outcell), ProjectileHitFlags.None); var refuelableComp = this.TryGetComp(); if(refuelableComp != null) @@ -154,7 +153,7 @@ namespace ArachnaeSwarm private bool CanFireGlobal(out string reason) { var refuelableComp = this.TryGetComp(); - if (refuelableComp != null && !refuelableComp.HasFuel) + if (refuelableComp != null && !this.refuelableComp.HasFuel) { reason = "NoFuel".Translate().CapitalizeFirst(); return false; @@ -189,7 +188,6 @@ namespace ArachnaeSwarm return false; } - // Allow targeting Pawns and Buildings on the world map if (target.WorldObject is MapParent mapParent && mapParent.HasMap) { var originalMap = this.Map; @@ -215,6 +213,7 @@ namespace ArachnaeSwarm { this.longTarget = new GlobalTargetInfo(localTarget.Cell, mapParent.Map); } + this.forcedTarget = LocalTargetInfo.Invalid; // Clear local target when setting remote }, null, onFinished, FireMissionTex, true); diff --git a/Source/ArachnaeSwarm/World/WorldObject_CatastropheMissile.cs b/Source/ArachnaeSwarm/World/WorldObject_CatastropheMissile.cs index 4d5a3d0..c3169da 100644 --- a/Source/ArachnaeSwarm/World/WorldObject_CatastropheMissile.cs +++ b/Source/ArachnaeSwarm/World/WorldObject_CatastropheMissile.cs @@ -60,8 +60,8 @@ namespace ArachnaeSwarm Map targetMap = Current.Game.FindMap(this.destinationTile); if (targetMap != null) { - // Find a random entry point at the edge of the target map - IntVec3 entryCell = CellFinder.RandomEdgeCell(targetMap); + // Find a random entry point at the north edge of the target map + IntVec3 entryCell = CellFinder.RandomEdgeCell(Rot4.North, targetMap); // Spawn the final projectile (the cruise missile) at the entry point Projectile_CruiseMissile missile = (Projectile_CruiseMissile)GenSpawn.Spawn(this.Projectile, entryCell, targetMap, WipeMode.Vanish);