zz暂存
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompAbilityEffect_TrackingCharge : CompAbilityEffect
|
||||
{
|
||||
public new CompProperties_TrackingCharge Props => (CompProperties_TrackingCharge)this.props;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_TrackingCharge : CompProperties_AbilityEffect
|
||||
{
|
||||
public float homingSpeed = 1.0f;
|
||||
public float initialDamage = 10f;
|
||||
public float damagePerTile = 2f;
|
||||
public float inertiaDistance = 3f;
|
||||
public DamageDef collisionDamageDef;
|
||||
public ThingDef flyerDef;
|
||||
|
||||
public CompProperties_TrackingCharge()
|
||||
{
|
||||
this.compClass = typeof(CompAbilityEffect_TrackingCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
156
Source/ArachnaeSwarm/Abilities/PawnFlyer_TrackingCharge.cs
Normal file
156
Source/ArachnaeSwarm/Abilities/PawnFlyer_TrackingCharge.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using Verse.AI;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class PawnFlyer_TrackingCharge : PawnFlyer
|
||||
{
|
||||
// --- Public fields to be set by the Verb ---
|
||||
public float homingSpeed;
|
||||
public float initialDamage;
|
||||
public float damagePerTile;
|
||||
public float inertiaDistance;
|
||||
public DamageDef collisionDamageDef;
|
||||
public LocalTargetInfo primaryTarget;
|
||||
|
||||
// --- Internal state ---
|
||||
private Vector3 currentSpeed;
|
||||
private float distanceTraveled = 0f;
|
||||
private bool homing = true;
|
||||
private int inertiaTicks = -1;
|
||||
private Vector3 exactPosition;
|
||||
|
||||
// --- Reflection Fields ---
|
||||
private static FieldInfo TicksFlyingInfo;
|
||||
private static FieldInfo TicksFlightTimeInfo;
|
||||
private static FieldInfo StartVecInfo;
|
||||
private static FieldInfo DestCellInfo;
|
||||
private static FieldInfo PawnWasDraftedInfo;
|
||||
private static FieldInfo PawnCanFireAtWillInfo;
|
||||
private static FieldInfo JobQueueInfo;
|
||||
private static FieldInfo InnerContainerInfo;
|
||||
|
||||
static PawnFlyer_TrackingCharge()
|
||||
{
|
||||
TicksFlyingInfo = typeof(PawnFlyer).GetField("ticksFlying", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
TicksFlightTimeInfo = typeof(PawnFlyer).GetField("ticksFlightTime", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
StartVecInfo = typeof(PawnFlyer).GetField("startVec", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
DestCellInfo = typeof(PawnFlyer).GetField("destCell", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
PawnWasDraftedInfo = typeof(PawnFlyer).GetField("pawnWasDrafted", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
PawnCanFireAtWillInfo = typeof(PawnFlyer).GetField("pawnCanFireAtWill", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
JobQueueInfo = typeof(PawnFlyer).GetField("jobQueue", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
InnerContainerInfo = typeof(PawnFlyer).GetField("innerContainer", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
}
|
||||
|
||||
// Custom initializer called by the Verb
|
||||
public void StartFlight(Pawn pawn, IntVec3 finalDest)
|
||||
{
|
||||
var innerContainer = (ThingOwner)InnerContainerInfo.GetValue(this);
|
||||
|
||||
StartVecInfo.SetValue(this, pawn.TrueCenter());
|
||||
DestCellInfo.SetValue(this, finalDest);
|
||||
PawnWasDraftedInfo.SetValue(this, pawn.Drafted);
|
||||
if (pawn.drafter != null) PawnCanFireAtWillInfo.SetValue(this, pawn.drafter.FireAtWill);
|
||||
if (pawn.CurJob != null) pawn.jobs.SuspendCurrentJob(JobCondition.InterruptForced);
|
||||
JobQueueInfo.SetValue(this, pawn.jobs.CaptureAndClearJobQueue());
|
||||
|
||||
if (pawn.Spawned) pawn.DeSpawn(DestroyMode.WillReplace);
|
||||
if (!innerContainer.TryAdd(pawn))
|
||||
{
|
||||
Log.Error("Could not add pawn to tracking flyer.");
|
||||
pawn.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||
{
|
||||
base.SpawnSetup(map, respawningAfterLoad);
|
||||
if (!respawningAfterLoad)
|
||||
{
|
||||
this.exactPosition = base.DrawPos;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Tick()
|
||||
{
|
||||
int ticksFlying = (int)TicksFlyingInfo.GetValue(this);
|
||||
|
||||
if (ticksFlying == 0)
|
||||
{
|
||||
Vector3 startVec = (Vector3)StartVecInfo.GetValue(this);
|
||||
IntVec3 destCell = (IntVec3)DestCellInfo.GetValue(this);
|
||||
Vector3 destinationPos = GenThing.TrueCenter(destCell, Rot4.North, this.FlyingThing.def.size, this.def.Altitude);
|
||||
Vector3 direction = (destinationPos - startVec).normalized;
|
||||
this.currentSpeed = direction * this.def.pawnFlyer.flightSpeed;
|
||||
}
|
||||
|
||||
this.exactPosition += this.currentSpeed;
|
||||
this.distanceTraveled += this.currentSpeed.magnitude;
|
||||
|
||||
if (inertiaTicks > 0)
|
||||
{
|
||||
inertiaTicks--;
|
||||
if (inertiaTicks <= 0) { Land(); return; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (homing && primaryTarget.HasThing && primaryTarget.Thing.Spawned)
|
||||
{
|
||||
Vector3 desiredDirection = (primaryTarget.Thing.DrawPos - this.exactPosition).normalized;
|
||||
this.currentSpeed = Vector3.RotateTowards(this.currentSpeed, desiredDirection, this.homingSpeed * 0.017f, 999f).normalized * this.def.pawnFlyer.flightSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
homing = false;
|
||||
}
|
||||
|
||||
float calculatedDamage = this.initialDamage + (this.distanceTraveled * this.damagePerTile);
|
||||
var dinfo = new DamageInfo(this.collisionDamageDef, calculatedDamage, 1f, -1, this.FlyingPawn);
|
||||
|
||||
if (homing && primaryTarget.HasThing && (this.exactPosition - primaryTarget.Thing.DrawPos).sqrMagnitude < 1.5f * 1.5f)
|
||||
{
|
||||
primaryTarget.Thing.TakeDamage(dinfo);
|
||||
homing = false;
|
||||
this.inertiaTicks = (int)(this.inertiaDistance / this.currentSpeed.magnitude);
|
||||
}
|
||||
|
||||
foreach (var thing in GenRadial.RadialDistinctThingsAround(this.exactPosition.ToIntVec3(), this.Map, 1.0f, false))
|
||||
{
|
||||
if (thing == this.FlyingPawn || thing == this || thing == primaryTarget.Thing) continue;
|
||||
if (thing is Pawn pawn && !pawn.Downed && pawn.HostileTo(this.FlyingPawn)) pawn.TakeDamage(dinfo);
|
||||
else if (thing.def.destroyable && thing.def.building != null) thing.TakeDamage(dinfo);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DestCellInfo.SetValue(this, this.exactPosition.ToIntVec3());
|
||||
TicksFlightTimeInfo.SetValue(this, ticksFlying + 2);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.ErrorOnce($"Exception during reflection in PawnFlyer_TrackingCharge: {ex}", this.thingIDNumber);
|
||||
}
|
||||
|
||||
TicksFlyingInfo.SetValue(this, ticksFlying + 1);
|
||||
|
||||
int flightTime = (int)TicksFlightTimeInfo.GetValue(this);
|
||||
if (!this.exactPosition.ToIntVec3().InBounds(this.Map) || ticksFlying > flightTime * 2)
|
||||
{
|
||||
Land();
|
||||
}
|
||||
}
|
||||
|
||||
private void Land()
|
||||
{
|
||||
if (this.Destroyed) return;
|
||||
base.RespawnPawn();
|
||||
this.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Verb_CastAbilityTrackingCharge : Verb_CastAbility
|
||||
{
|
||||
protected override bool TryCastShot()
|
||||
{
|
||||
var props = this.ability.def.comps?.OfType<CompProperties_TrackingCharge>().FirstOrDefault();
|
||||
if (props == null)
|
||||
{
|
||||
Log.Error("Verb_CastAbilityTrackingCharge requires CompProperties_TrackingCharge on the ability def.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (props.flyerDef == null)
|
||||
{
|
||||
Log.Error("CompProperties_TrackingCharge requires a flyerDef.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.CasterPawn == null || !this.CasterPawn.Spawned)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- This is now a fully custom Thing, so we spawn it directly ---
|
||||
var trackingCharge = (PawnFlyer_TrackingCharge)ThingMaker.MakeThing(props.flyerDef);
|
||||
|
||||
// Inject properties
|
||||
trackingCharge.homingSpeed = props.homingSpeed;
|
||||
trackingCharge.initialDamage = props.initialDamage;
|
||||
trackingCharge.damagePerTile = props.damagePerTile;
|
||||
trackingCharge.inertiaDistance = props.inertiaDistance;
|
||||
trackingCharge.collisionDamageDef = props.collisionDamageDef;
|
||||
trackingCharge.primaryTarget = this.currentTarget;
|
||||
|
||||
// Setup and spawn
|
||||
trackingCharge.StartFlight(this.CasterPawn, this.currentTarget.Cell);
|
||||
GenSpawn.Spawn(trackingCharge, this.CasterPawn.Position, this.CasterPawn.Map);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,12 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="HediffComp_Temperature.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Abilities\CompAbilityEffect_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\CompProperties_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\PawnFlyer_TrackingCharge.cs" />
|
||||
<Compile Include="Abilities\Verb_CastAbilityTrackingCharge.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 自定义清理任务,删除obj文件夹中的临时文件 -->
|
||||
<Target Name="CleanDebugFiles" AfterTargets="Build">
|
||||
|
||||
Reference in New Issue
Block a user