暂存
This commit is contained in:
@@ -209,7 +209,6 @@
|
||||
<Compile Include="ARAFoodDispenserProperties.cs" />
|
||||
<Compile Include="Patch_DispenserFoodSearch.cs" />
|
||||
<Compile Include="Buildings\Building_CatastropheMissileSilo.cs" />
|
||||
<Compile Include="Verbs\Verb_LaunchCatastropheMissile.cs" />
|
||||
<Compile Include="World\WorldObject_CatastropheMissile.cs" />
|
||||
<Compile Include="HarmonyPatches\Patch_ForceTargetable.cs" />
|
||||
<Compile Include="Comps\CompForceTargetable.cs" />
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
@@ -15,18 +14,12 @@ namespace ArachnaeSwarm
|
||||
[StaticConstructorOnStartup]
|
||||
public class Building_CatastropheMissileSilo : Building_TurretGun
|
||||
{
|
||||
// Reflection to access the private 'holdFire' field in the base class, as there is no public accessor.
|
||||
private static readonly FieldInfo holdFireField =
|
||||
typeof(Building_TurretGun).GetField("holdFire", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public GlobalTargetInfo longTarget;
|
||||
public static readonly Texture2D FireMissionTex = ContentFinder<Texture2D>.Get("UI/Commands/Attack", true);
|
||||
|
||||
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||
{
|
||||
base.SpawnSetup(map, respawningAfterLoad);
|
||||
// This is the definitive fix for the default target issue on spawn.
|
||||
// It runs only once when the building is first created, not on game load.
|
||||
if (!respawningAfterLoad)
|
||||
{
|
||||
this.longTarget = GlobalTargetInfo.Invalid;
|
||||
@@ -41,49 +34,36 @@ namespace ArachnaeSwarm
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
// Always run base.Tick() first. This handles all local targeting, aiming, warmup,
|
||||
// cooldowns, and calling the Verb for local shots. This is the key to fixing the bug.
|
||||
// Base tick handles all local targeting, cooldowns, and fuel consumption via XML.
|
||||
base.Tick();
|
||||
|
||||
// --- Mutual Exclusivity: Prioritize Local Target ---
|
||||
// If a local target is set (either by player or automatically), clear the remote target.
|
||||
// If a local target is active, prevent remote targeting.
|
||||
if (this.forcedTarget.IsValid && this.longTarget.IsValid)
|
||||
{
|
||||
this.longTarget = GlobalTargetInfo.Invalid;
|
||||
}
|
||||
|
||||
// --- Debug Logging (every 120 ticks, approx 2 seconds) ---
|
||||
if (Find.TickManager.TicksGame % 120 == 0)
|
||||
{
|
||||
bool isHoldingFireForLog = (bool)holdFireField.GetValue(this);
|
||||
string reason;
|
||||
CanFireGlobal(out reason); // To get the reason string
|
||||
Log.Message($"[Silo Debug] Tick: {Find.TickManager.TicksGame}\n" +
|
||||
$"- Cooldown: {this.burstCooldownTicksLeft}\n" +
|
||||
$"- Active (Power): {base.Active}\n" +
|
||||
$"- HoldFire: {isHoldingFireForLog}\n" +
|
||||
$"- CanFireGlobal (Fuel?): {CanFireGlobal(out reason)} (Reason: {reason})\n" +
|
||||
$"- Local Target: {this.forcedTarget.ToString()}\n" +
|
||||
$"- Remote Target: {this.longTarget.ToString()}");
|
||||
}
|
||||
|
||||
// --- Remote Firing Logic ---
|
||||
bool isHoldingFire = (bool)holdFireField.GetValue(this);
|
||||
if (this.longTarget.IsValid && !isHoldingFire && this.burstCooldownTicksLeft <= 0 && base.Active && CanFireGlobal(out _))
|
||||
// If a remote target is set and the turret is ready, fire.
|
||||
// The base.Tick() cooldown handling prevents this from running if a local shot was just fired.
|
||||
if (this.longTarget.IsValid && this.burstCooldownTicksLeft <= 0 && base.Active && CanFireGlobal(out _))
|
||||
{
|
||||
if (!this.forcedTarget.IsValid)
|
||||
{
|
||||
this.FireMission(this.longTarget);
|
||||
}
|
||||
this.FireMission(this.longTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetInspectString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(base.GetInspectString());
|
||||
|
||||
if (burstCooldownTicksLeft > 0)
|
||||
{
|
||||
if (sb.Length > 0) sb.AppendLine();
|
||||
sb.Append("Cooldown".Translate() + ": " + this.burstCooldownTicksLeft.ToStringTicksToPeriod());
|
||||
}
|
||||
|
||||
if (this.longTarget.IsValid)
|
||||
{
|
||||
sb.AppendLine();
|
||||
if (sb.Length > 0) sb.AppendLine();
|
||||
sb.Append("RemoteTargetSet".Translate(this.longTarget.Label));
|
||||
}
|
||||
return sb.ToString();
|
||||
@@ -91,13 +71,11 @@ namespace ArachnaeSwarm
|
||||
|
||||
public override IEnumerable<Gizmo> GetGizmos()
|
||||
{
|
||||
// Yield base gizmos first, which includes "Set forced target" and other standard buttons.
|
||||
foreach (var g in base.GetGizmos())
|
||||
{
|
||||
yield return g;
|
||||
}
|
||||
|
||||
// Then add our custom "Global Strike" gizmo
|
||||
Command_Action fireGlobal = new Command_Action
|
||||
{
|
||||
defaultLabel = "CommandFireGlobal".Translate(),
|
||||
@@ -110,14 +88,12 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
fireGlobal.Disable(reason);
|
||||
}
|
||||
// Global Strike button is disabled if a forced target is already set, to ensure mutual exclusivity.
|
||||
if (this.forcedTarget.IsValid)
|
||||
{
|
||||
fireGlobal.Disable("LocalTargetForced".Translate());
|
||||
}
|
||||
yield return fireGlobal;
|
||||
|
||||
// Add a specific button to clear the remote target
|
||||
if (this.longTarget.IsValid)
|
||||
{
|
||||
Command_Action clearRemote = new Command_Action
|
||||
@@ -147,7 +123,6 @@ namespace ArachnaeSwarm
|
||||
missile.Projectile = DefDatabase<ThingDef>.GetNamed("Projectile_CatastropheMissile");
|
||||
Find.WorldObjects.Add(missile);
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -161,14 +136,13 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
SoundDef.Named("RocketLaunch").PlayOneShot(new TargetInfo(this.Position, this.Map));
|
||||
|
||||
// Manually reset cooldown.
|
||||
this.BurstComplete();
|
||||
}
|
||||
|
||||
private bool CanFireGlobal(out string reason)
|
||||
{
|
||||
var refuelableComp = this.TryGetComp<CompRefuelable>();
|
||||
if (refuelableComp != null && !this.refuelableComp.HasFuel)
|
||||
if (refuelableComp != null && !refuelableComp.HasFuel)
|
||||
{
|
||||
reason = "NoFuel".Translate().CapitalizeFirst();
|
||||
return false;
|
||||
@@ -214,12 +188,11 @@ namespace ArachnaeSwarm
|
||||
Find.Targeter.BeginTargeting(new TargetingParameters
|
||||
{
|
||||
canTargetLocations = true,
|
||||
canTargetPawns = true, // Allow targeting pawns
|
||||
canTargetBuildings = true // Allow targeting buildings
|
||||
canTargetPawns = true,
|
||||
canTargetBuildings = true
|
||||
},
|
||||
(LocalTargetInfo localTarget) =>
|
||||
{
|
||||
// Convert LocalTargetInfo to GlobalTargetInfo, handling Thing targets.
|
||||
if (localTarget.HasThing)
|
||||
{
|
||||
this.longTarget = new GlobalTargetInfo(localTarget.Thing);
|
||||
@@ -228,7 +201,7 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
this.longTarget = new GlobalTargetInfo(localTarget.Cell, mapParent.Map);
|
||||
}
|
||||
this.forcedTarget = LocalTargetInfo.Invalid; // Clear local target when setting remote
|
||||
this.forcedTarget = LocalTargetInfo.Invalid;
|
||||
},
|
||||
null, onFinished, FireMissionTex, true);
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Verb_LaunchCatastropheMissile : Verb_Shoot
|
||||
{
|
||||
// This verb is now only for local defense. The global launch is handled by the Building.
|
||||
protected override bool TryCastShot()
|
||||
{
|
||||
return base.TryCastShot();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user