This commit is contained in:
2025-09-07 18:41:35 +08:00
parent b954781675
commit c43bc0f0bb
5 changed files with 22 additions and 22 deletions

Binary file not shown.

View File

@@ -39,8 +39,9 @@
<inertiaDistance>6</inertiaDistance>
<collisionDamageDef>Blunt</collisionDamageDef>
<flyerDef>ARA_Flyer_TrackingCharge</flyerDef>
<collisionRadius>2.5</collisionRadius> <!-- Larger collision radius -->
<collisionRadius>1.5</collisionRadius> <!-- Larger collision radius -->
<impactSound>Pawn_Melee_BigBash_HitPawn</impactSound>
<damageHostileOnly>true</damageHostileOnly> <!-- Set to false to damage everyone in the path -->
</li>
<li Class="CompProperties_AbilityEffecterOnCaster">
<effecterDef>WarTrumpet</effecterDef>

View File

@@ -13,6 +13,8 @@ namespace ArachnaeSwarm
public ThingDef flyerDef;
public float collisionRadius = 1.5f;
public SoundDef impactSound;
public bool damageHostileOnly = true;
public CompProperties_TrackingCharge()
{
this.compClass = typeof(CompAbilityEffect_TrackingCharge);

View File

@@ -18,9 +18,10 @@ namespace ArachnaeSwarm
public float inertiaDistance;
public DamageDef collisionDamageDef;
public LocalTargetInfo primaryTarget;
public int maxFlightTicks;
public float collisionRadius;
public SoundDef impactSound;
public bool damageHostileOnly;
public int maxFlightTicks;
// --- Internal state ---
private bool homing = true;
@@ -68,7 +69,7 @@ namespace ArachnaeSwarm
pawn.Destroy();
}
}
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
@@ -77,14 +78,14 @@ namespace ArachnaeSwarm
this.exactPosition = base.DrawPos;
}
}
protected override void Tick()
{
// --- THE CORRECT APPROACH ---
// Let the base class handle all flight mechanics (position, timing, etc.)
// We only intervene to do two things:
// 1. Continuously update the destination to "steer" the flyer.
// 2. Perform our own collision check.
// 2. Perform our own collision checks (for primary target and AOE).
if (homing && primaryTarget.HasThing && primaryTarget.Thing.Spawned)
{
@@ -92,10 +93,9 @@ namespace ArachnaeSwarm
DestCellInfo.SetValue(this, primaryTarget.Thing.Position);
}
// Perform our custom collision check.
// --- Primary Target Collision Check ---
if (!hasHitPrimaryTarget && primaryTarget.HasThing && primaryTarget.Thing.Spawned)
{
// Use DrawPos for accurate distance checking, not Position.
if ((this.DrawPos - primaryTarget.Thing.DrawPos).sqrMagnitude < this.collisionRadius * this.collisionRadius)
{
// --- Impact! ---
@@ -104,8 +104,6 @@ namespace ArachnaeSwarm
SoundStarter.PlayOneShot(this.impactSound, new TargetInfo(this.Position, this.Map));
}
// Calculate damage based on distance traveled so far.
// We need to get the distance from the base class now.
Vector3 startPosition = (Vector3)StartVecInfo.GetValue(this);
float distance = (this.DrawPos - startPosition).magnitude;
float calculatedDamage = this.initialDamage + (distance * this.damagePerTile);
@@ -114,11 +112,8 @@ namespace ArachnaeSwarm
primaryTarget.Thing.TakeDamage(dinfo);
hasHitPrimaryTarget = true;
// Stop homing. The flyer will now continue to its last set destination.
homing = false;
// To create the "inertia" effect, we now set the destination to be a point
// past the target.
Vector3 direction = (this.DrawPos - startPosition).normalized;
IntVec3 inertiaEndPos = (this.DrawPos + (direction * this.inertiaDistance)).ToIntVec3();
DestCellInfo.SetValue(this, inertiaEndPos);
@@ -126,35 +121,36 @@ namespace ArachnaeSwarm
}
// --- AOE Damage Logic ---
// Damage other hostiles in the path.
float distanceTravelled = ((Vector3)StartVecInfo.GetValue(this) - this.DrawPos).magnitude;
float currentAOEDamage = this.initialDamage + (distanceTravelled * this.damagePerTile);
foreach (var thing in GenRadial.RadialDistinctThingsAround(this.Position, this.Map, 1.0f, false))
foreach (var thing in GenRadial.RadialDistinctThingsAround(this.Position, this.Map, this.collisionRadius, false))
{
if (thing != this.FlyingPawn && thing != this && thing != primaryTarget.Thing)
{
if (thing is Pawn pawn && !pawn.Downed && pawn.HostileTo(this.FlyingPawn))
if (thing is Pawn pawn && !pawn.Downed)
{
if (!this.damageHostileOnly || pawn.HostileTo(this.FlyingPawn))
{
var aoeDinfo = new DamageInfo(this.collisionDamageDef, currentAOEDamage, 1f, -1, this.FlyingPawn);
pawn.TakeDamage(aoeDinfo);
}
}
else if (thing.def.destroyable && thing.def.building != null)
{
// --- CRITICAL FIX ---
// Create a *new* DamageInfo object for each target.
// Reusing the same dinfo object causes its damage value to be modified (e.g., by armor),
// resulting in subsequent targets taking zero damage.
var aoeDinfo = new DamageInfo(this.collisionDamageDef, currentAOEDamage, 1f, -1, this.FlyingPawn);
pawn.TakeDamage(aoeDinfo);
thing.TakeDamage(aoeDinfo);
}
}
}
// Let the base class do its thing. This is crucial.
// It will handle the movement, timing, and eventual landing based on its calculated ticksFlightTime.
base.Tick();
}
protected override void RespawnPawn()
{
// This is the correct place to call the base method.
// The base class's TickInterval will call this method before destroying the flyer.
base.RespawnPawn();
}
}

View File

@@ -48,6 +48,7 @@ namespace ArachnaeSwarm
trackingCharge.primaryTarget = this.currentTarget;
trackingCharge.collisionRadius = props.collisionRadius;
trackingCharge.impactSound = props.impactSound;
trackingCharge.damageHostileOnly = props.damageHostileOnly;
// Setup and spawn
trackingCharge.StartFlight(this.CasterPawn, this.currentTarget.Cell);