diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index dd6f7824..5993a73f 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/Defs/Effects/Mote_Wula.xml b/1.6/1.6/Defs/Effects/Mote_Wula.xml
index 34d67e77..b6b77e23 100644
--- a/1.6/1.6/Defs/Effects/Mote_Wula.xml
+++ b/1.6/1.6/Defs/Effects/Mote_Wula.xml
@@ -28,4 +28,28 @@
+
+
+ Mote_WULA_RW_Penetrating_Beam
+ MoteDualAttached
+ MoteOverhead
+
+ 0.1
+ 0.1
+ 0.1
+ True
+ True
+
+ true
+
+ Things/Projectile/ChargeLanceShot
+ Graphic_MoteWithAgeSecs
+ MoteBeam
+
+ <_ScrollSpeedA>0
+ <_ScrollSpeedB>0
+ <_Intensity>2
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_CruiseMissile.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_CruiseMissile.xml
deleted file mode 100644
index 1a6ef9d4..00000000
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_CruiseMissile.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
- Weapon_ExampleCruiseMissileLauncher
-
- A heavy launcher designed for cruise missiles, capable of long-range precision strikes and area bombardment.
- Spacer
-
- Things/Item/Weapon/Launcher
- Graphic_Single
-
- 1
- Interact_ChargeRifle
-
- LongShots
- RangedHeavy
-
-
-
- WULA_Cube_Productor_BIO
- WULA_Cube_Productor_Energy
-
- WULA_Synth_Weapon_Technology
- UnfinishedWeapon
-
-
- 2500
- 6.0
- 0.3
- 0.5
- 0.6
- 0.7
- 4.0
-
-
- 180
- 10
- 40
- 15
-
-
-
- Verb_LaunchProjectile
- true
- Bullet_ExampleCruiseMissile
- 3.0
- 60
- 1
- Shot_ChargeLance
- GunTail_Heavy
- 15
-
- true
-
- false
-
-
-
- Wula_Weapon_Init
- CruiseMissileLauncher
-
-
- RewardStandardQualitySuper
-
-
-
-
- Bullet_ExampleCruiseMissile
-
-
- Things/Projectile/Bullet_Big
- Graphic_Single
-
- WulaFallenEmpire.Projectile_CruiseMissile
-
- 30
- Bomb
- 20
- 2.5
- 0.8
- Explosion_Bomb
- Impact_Metal
- true
- 1.0
- 4.0
- Filth_Rubble
- 1.0
- 5
- 120
- 1.5
- true
- 1.0
- 8
- 0.7
- true
- true
-
-
- Bomb
- 25
- 3.5
- Explosion_Bomb
- true
- 5
- 2.0
- 15
- 7.0
- Bomb
- Explosion_Bomb
- WULA_GunTail_Smoke
- 0.05
- 15
-
- 180
- 300
-
- 0.001
-
- 10
- 20
-
- 1.5
-
-
-
-
-
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
index 60360de1..0fdfeb62 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
@@ -6,8 +6,9 @@
A rifle designed to fire homing projectiles. It can track targets and adjust its trajectory in real-time.
Spacer
- Things/Item/Weapon/Rifle
+ Wula/Weapon/WULA_RW_Plasm_AR
Graphic_Single
+ 1.4
1
Interact_Rifle
@@ -45,7 +46,7 @@
1.0
35
1
- Shot_ChargeRifle
+ Shot_ChargeRifle
GunTail_Medium
9
@@ -63,7 +64,7 @@
Bullet_ExampleHoming
- Things/Projectile/Bullet_Big
+ Things/Projectile/Bullet_Big
Graphic_Single
WulaFallenEmpire.Projectile_Homing
@@ -78,9 +79,6 @@
false
0.5
0.5
- Filth_Rubble
- 0.5
- 1
0
0.5
false
@@ -89,22 +87,22 @@
0.1
true
true
-
-
- 10
- 0.05
- 60
- 1.5
- 0.8
- Bullet_ExampleHoming
- 0.05
-
- 20
- 40
-
- WULA_GunTail_Smoke
-
-
+
+
+ 10
+ 0.05
+ 60
+ 1.5
+ 0.8
+ Bullet_ExampleHoming
+ 0.05
+
+ 20
+ 40
+
+ WULA_GunTail_Smoke
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_HomingExplosive.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_HomingExplosive.xml
index b9314b46..153f8455 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_HomingExplosive.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_HomingExplosive.xml
@@ -6,8 +6,9 @@
A powerful launcher that fires homing projectiles with explosive payloads. Ideal for area denial and heavy damage.
Spacer
- Things/Item/Weapon/Launcher
+ Wula/Weapon/WULA_RW_Plasm_AR
Graphic_Single
+ 1.4
0.8
Interact_ChargeRifle
@@ -79,10 +80,6 @@
true
0.8
3.0
- Filth_Rubble
- 1.0
- 3
- 60
1.0
true
1.0
@@ -90,34 +87,22 @@
0.5
true
true
-
-
- 5
- 0.03
- 90
- 2.0
- 0.7
- Bullet_ExampleHomingExplosive
- 0.03
-
- 20
- 30
-
- WULA_GunTail_Smoke
-
-
- 30
- 5
- 3
- Bullet_ShotgunPellet
- 5
-
- 1
- 3
-
- true
-
-
+
+
+ 5
+ 0.03
+ 90
+ 2.0
+ 0.7
+ Bullet_ExampleHomingExplosive
+ 0.03
+
+ 20
+ 30
+
+ WULA_GunTail_Smoke
+
+
\ No newline at end of file
diff --git a/1.6/Anomaly/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml b/1.6/Anomaly/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml
index 4392bb17..a3f0a9e8 100644
--- a/1.6/Anomaly/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml
+++ b/1.6/Anomaly/Defs/EventDefs/EventDef_WULA_FE_Spiritualist.xml
@@ -302,7 +302,7 @@
- Wula_UI_FE_Spiritualist_10
+ Wula_UI_FE_Spiritualist_11
Wula/Events/Portraits/WULA_FE_Spiritualist_1
帝国修女
diff --git a/Source/WulaFallenEmpire/HomingProjectileDef.cs b/Source/WulaFallenEmpire/HomingProjectileDef.cs
index 65ba2ff1..69a279d1 100644
--- a/Source/WulaFallenEmpire/HomingProjectileDef.cs
+++ b/Source/WulaFallenEmpire/HomingProjectileDef.cs
@@ -5,21 +5,8 @@ namespace WulaFallenEmpire
{
public class HomingProjectileDef : DefModExtension
{
- public float SpeedChangeTilesPerTickOverride
- {
- get
- {
- return this.speedChangePerTick / 100f;
- }
- }
-
- public FloatRange SpeedRangeTilesPerTickOverride
- {
- get
- {
- return this.speedRangeOverride.Value * 0.01f;
- }
- }
+ public float SpeedChangeTilesPerTickOverride;
+ public FloatRange SpeedRangeTilesPerTickOverride;
public float hitChance = 0.5f;
@@ -27,7 +14,7 @@ namespace WulaFallenEmpire
public float initRotateAngle = 30f;
- public float proximityFuseRange = 0f;
+ public float proximityFuseRange = 0.5f; // 调整默认值,使其在接近目标时能正确触发引信
public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120);
@@ -37,5 +24,12 @@ namespace WulaFallenEmpire
public FloatRange? speedRangeOverride;
public FleckDef tailFleckDef;
+ // 拖尾特效的详细配置参数
+ public int fleckMakeFleckTickMax = 1;
+ public IntRange fleckMakeFleckNum = new IntRange(1, 1);
+ public FloatRange fleckAngle = new FloatRange(-180f, 180f);
+ public FloatRange fleckScale = new FloatRange(1f, 1f);
+ public FloatRange fleckSpeed = new FloatRange(0f, 0f);
+ public FloatRange fleckRotation = new FloatRange(-180f, 180f);
}
}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Projectile_Homing.cs b/Source/WulaFallenEmpire/Projectile_Homing.cs
index 93f38c22..9243a528 100644
--- a/Source/WulaFallenEmpire/Projectile_Homing.cs
+++ b/Source/WulaFallenEmpire/Projectile_Homing.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using System.Reflection;
using RimWorld;
@@ -9,317 +8,319 @@ using Verse.Sound;
namespace WulaFallenEmpire
{
- public class Projectile_Homing : Bullet
- {
- public HomingProjectileDef HomingDef
- {
- get
- {
- bool flag = this.homingDefInt == null;
- if (flag)
- {
- this.homingDefInt = this.def.GetModExtension();
- }
- return this.homingDefInt;
- }
- }
+ public class Projectile_Homing : Bullet
+ {
+ private HomingProjectileDef homingDefInt;
- public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
- {
- bool flag = false;
- bool flag2 = usedTarget.HasThing && usedTarget.Thing is IAttackTarget;
- if (flag2)
- {
- bool flag3 = Rand.Chance(this.GetHitChance(usedTarget.Thing));
- if (flag3)
- {
- hitFlags |= ProjectileHitFlags.IntendedTarget;
- intendedTarget = usedTarget;
- flag = true;
- }
- }
- else
- {
- bool flag4 = Rand.Chance(this.GetHitChance(intendedTarget.Thing));
- if (flag4)
- {
- hitFlags |= ProjectileHitFlags.IntendedTarget;
- usedTarget = intendedTarget;
- flag = true;
- }
- }
- bool flag5 = flag;
- if (flag5)
- {
- hitFlags &= ~ProjectileHitFlags.IntendedTarget;
- }
- base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
- this.exactPositionInt = origin.Yto0() + Vector3.up * this.def.Altitude;
- Vector3 normalized = (this.destination - origin).Yto0().normalized;
- float degrees = Rand.Range(-this.HomingDef.initRotateAngle, this.HomingDef.initRotateAngle);
- Vector2 vector = new Vector2(normalized.x, normalized.z);
- vector = vector.RotatedBy(degrees);
- Vector3 a = new Vector3(vector.x, 0f, vector.y);
- bool flag6 = this.HomingDef.speedRangeOverride == null;
- if (flag6)
- {
- this.curSpeed = a * this.def.projectile.SpeedTilesPerTick;
- }
- else
- {
- this.curSpeed = a * this.HomingDef.SpeedRangeTilesPerTickOverride.RandomInRange;
- }
- this.ticksToImpact = int.MaxValue;
- this.lifetime = int.MaxValue;
- this.ReflectInit();
- }
+ private Sustainer ambientSustainer;
- protected void ReflectInit()
- {
- bool flag = !this.def.projectile.soundAmbient.NullOrUndefined();
- if (flag)
- {
- this.ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
- }
- this.comps = (List)NonPublicFields.ThingWithComps_comps.GetValue(this);
- }
+ private List comps;
- public float GetHitChance(Thing thing)
- {
- float num = this.HomingDef.hitChance;
- bool flag = thing == null;
- float result;
- if (flag)
- {
- result = num;
- }
- else
- {
- Pawn pawn = thing as Pawn;
- bool flag2 = pawn != null;
- if (flag2)
- {
- num *= Mathf.Clamp(pawn.BodySize, 0.5f, 1.5f);
- bool flag3 = pawn.GetPosture() > PawnPosture.Standing;
- if (flag3)
- {
- num *= 0.5f;
- }
- float num2 = 1f;
- switch (this.equipmentQuality)
- {
- case QualityCategory.Awful:
- num2 = 0.5f;
- goto IL_DD;
- case QualityCategory.Poor:
- num2 = 0.75f;
- goto IL_DD;
- case QualityCategory.Normal:
- num2 = 1f;
- goto IL_DD;
- case QualityCategory.Excellent:
- num2 = 1.1f;
- goto IL_DD;
- case QualityCategory.Masterwork:
- num2 = 1.2f;
- goto IL_DD;
- case QualityCategory.Legendary:
- num2 = 1.3f;
- goto IL_DD;
- }
- Log.Message("Unknown QualityCategory, returning default qualityFactor = 1");
- IL_DD:
- num *= num2;
- }
- else
- {
- num *= 1.5f * thing.def.fillPercent;
- }
- result = Mathf.Clamp(num, 0f, 1f);
- }
- return result;
- }
+ protected Vector3 exactPositionInt;
- public override Vector3 ExactPosition
- {
- get
- {
- return this.exactPositionInt;
- }
- }
+ public Vector3 curSpeed;
- public override Quaternion ExactRotation
- {
- get
- {
- return Quaternion.LookRotation(this.curSpeed);
- }
- }
+ public bool homing = true;
+ private int Fleck_MakeFleckTick; // 拖尾特效的计时器
+ private Vector3 lastTickPosition; // 记录上一帧的位置,用于计算移动方向
- public virtual void MovementTick()
- {
- Vector3 vect = this.ExactPosition + this.curSpeed;
- ShootLine shootLine = new ShootLine(this.ExactPosition.ToIntVec3(), vect.ToIntVec3());
- Vector3 vector = (this.intendedTarget.Cell.ToVector3() - this.ExactPosition).Yto0();
- bool flag = this.homing;
- if (flag)
- {
- Vector3 a = vector.normalized - this.curSpeed.normalized;
- bool flag2 = a.sqrMagnitude >= 1.414f;
- if (flag2)
- {
- this.homing = false;
- this.lifetime = this.HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
- this.ticksToImpact = this.lifetime;
- base.HitFlags &= ~ProjectileHitFlags.IntendedTarget;
- base.HitFlags |= ProjectileHitFlags.NonTargetPawns;
- base.HitFlags |= ProjectileHitFlags.NonTargetWorld;
- }
- else
- {
- this.curSpeed += a * this.HomingDef.homingSpeed * this.curSpeed.magnitude;
- }
- }
- foreach (IntVec3 b in shootLine.Points())
- {
- bool flag3 = (this.intendedTarget.Cell - b).SqrMagnitude <= this.HomingDef.proximityFuseRange * this.HomingDef.proximityFuseRange;
- if (flag3)
- {
- this.homing = false;
- this.lifetime = this.HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
- bool flag4 = (base.HitFlags & ProjectileHitFlags.IntendedTarget) == ProjectileHitFlags.IntendedTarget || this.HomingDef.proximityFuseRange > 0f;
- if (flag4)
- {
- this.lifetime = 0;
- this.ticksToImpact = 0;
- vect = b.ToVector3();
- bool flag5 = Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
- if (flag5)
- {
- this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
- }
- }
- }
- }
- this.exactPositionInt = vect;
- this.curSpeed *= (this.curSpeed.magnitude + this.HomingDef.SpeedChangeTilesPerTickOverride) / this.curSpeed.magnitude;
- }
+ private static class NonPublicFields
+ {
+ public static FieldInfo Projectile_AmbientSustainer = typeof(Projectile).GetField("ambientSustainer", BindingFlags.Instance | BindingFlags.NonPublic);
+ public static FieldInfo ThingWithComps_comps = typeof(ThingWithComps).GetField("comps", BindingFlags.Instance | BindingFlags.NonPublic);
+ public static MethodInfo ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
+ }
- protected override void Tick()
- {
- this.ThingWithCompsTick();
- this.lifetime--;
- if (this.HomingDef.tailFleckDef != null)
- {
- FleckMaker.Static(this.ExactPosition, base.Map, this.HomingDef.tailFleckDef, 1f);
- }
- bool landed = this.landed;
- if (!landed)
- {
- Vector3 exactPosition = this.ExactPosition;
- this.ticksToImpact--;
- this.MovementTick();
- bool flag = !this.ExactPosition.InBounds(base.Map);
- if (flag)
- {
- base.Position = exactPosition.ToIntVec3();
- this.Destroy(DestroyMode.Vanish);
- }
- else
- {
- Vector3 exactPosition2 = this.ExactPosition;
- object[] parameters = new object[]
- {
- exactPosition,
- exactPosition2
- };
- bool flag2 = (bool)Projectile_Homing.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
- if (!flag2)
- {
- base.Position = this.ExactPosition.ToIntVec3();
- bool flag3 = this.ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
- if (flag3)
- {
- this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
- }
- bool flag4 = this.ticksToImpact <= 0;
- if (flag4)
- {
- this.ImpactSomething();
- }
- else
- {
- bool flag5 = this.ambientSustainer != null;
- if (flag5)
- {
- this.ambientSustainer.Maintain();
- }
- }
- }
- }
- }
- }
+ public HomingProjectileDef HomingDef
+ {
+ get
+ {
+ if (homingDefInt == null)
+ {
+ homingDefInt = def.GetModExtension();
+ if (homingDefInt == null)
+ {
+ Log.ErrorOnce($"HomingProjectileDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
+ this.homingDefInt = new HomingProjectileDef();
+ }
+ }
+ return homingDefInt;
+ }
+ }
- private void ThingWithCompsTick()
- {
- bool flag = this.comps != null;
- if (flag)
- {
- int i = 0;
- int count = this.comps.Count;
- while (i < count)
- {
- this.comps[i].CompTick();
- i++;
- }
- }
- }
+ public override Vector3 ExactPosition => exactPositionInt;
- protected override void Impact(Thing hitThing, bool blockedByShield = false)
- {
- Map map = base.Map;
- IntVec3 position = base.Position;
- base.Impact(hitThing, blockedByShield);
- bool flag = this.HomingDef.extraProjectile != null;
- if (flag)
- {
- bool flag2 = hitThing != null && hitThing.Spawned;
- if (flag2)
- {
- ((Projectile)GenSpawn.Spawn(this.HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(this.launcher, this.ExactPosition, hitThing, hitThing, ProjectileHitFlags.All, false, null, null);
- }
- else
- {
- ((Projectile)GenSpawn.Spawn(this.HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(this.launcher, this.ExactPosition, position, position, ProjectileHitFlags.All, false, null, null);
- }
- }
- }
+ public override Quaternion ExactRotation => Quaternion.LookRotation(curSpeed);
- public override void ExposeData()
- {
- base.ExposeData();
- Scribe_Values.Look(ref this.exactPositionInt, "exactPosition", default(Vector3), false);
- Scribe_Values.Look(ref this.curSpeed, "curSpeed", default(Vector3), false);
- Scribe_Values.Look(ref this.homing, "homing", false, false);
- bool flag = Scribe.mode == LoadSaveMode.PostLoadInit;
- if (flag)
- {
- this.ReflectInit();
- }
- }
+ public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
+ {
+ bool flag = false;
+ if (usedTarget.HasThing && usedTarget.Thing is IAttackTarget)
+ {
+ if (Rand.Chance(GetHitChance(usedTarget.Thing)))
+ {
+ hitFlags |= ProjectileHitFlags.IntendedTarget;
+ intendedTarget = usedTarget;
+ flag = true;
+ }
+ }
+ else if (Rand.Chance(GetHitChance(intendedTarget.Thing)))
+ {
+ hitFlags |= ProjectileHitFlags.IntendedTarget;
+ usedTarget = intendedTarget;
+ flag = true;
+ }
+ if (flag)
+ {
+ hitFlags &= ~ProjectileHitFlags.IntendedTarget;
+ }
+ base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
+ exactPositionInt = origin.Yto0() + Vector3.up * def.Altitude;
+ lastTickPosition = origin; // 初始化 lastTickPosition
+ Vector3 normalized = (destination - origin).Yto0().normalized;
+ float degrees = Rand.Range(0f - HomingDef.initRotateAngle, HomingDef.initRotateAngle);
+ Vector2 v = new Vector2(normalized.x, normalized.z);
+ v = v.RotatedBy(degrees);
+ Vector3 vector = new Vector3(v.x, 0f, v.y);
+ // 检查 HomingDef.speedRangeOverride 是否有值
+ if (!HomingDef.speedRangeOverride.HasValue)
+ {
+ curSpeed = vector * def.projectile.SpeedTilesPerTick;
+ }
+ else
+ {
+ curSpeed = vector * HomingDef.SpeedRangeTilesPerTickOverride.RandomInRange;
+ }
+ ticksToImpact = int.MaxValue;
+ lifetime = int.MaxValue;
+ ReflectInit();
+ }
- private HomingProjectileDef homingDefInt;
+ protected void ReflectInit()
+ {
+ if (!def.projectile.soundAmbient.NullOrUndefined())
+ {
+ ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
+ }
+ comps = (List)NonPublicFields.ThingWithComps_comps.GetValue(this);
+ }
- private Sustainer ambientSustainer;
+ public float GetHitChance(Thing thing)
+ {
+ if (this.HomingDef == null)
+ {
+ Log.ErrorOnce("HomingDef is null for projectile " + this.def.defName + ". Returning default hitChance.", this.thingIDNumber ^ 0x12345678);
+ return 0.7f;
+ }
- private List comps;
+ float hitChance = HomingDef.hitChance;
+ if (thing == null)
+ {
+ return hitChance;
+ }
+ if (thing is Pawn pawn)
+ {
+ hitChance *= Mathf.Clamp(pawn.BodySize, 0.5f, 1.5f);
+ if (pawn.GetPosture() != 0)
+ {
+ hitChance *= 0.5f;
+ }
+ float num = 1f;
+ switch (equipmentQuality)
+ {
+ case QualityCategory.Awful:
+ num = 0.5f;
+ break;
+ case QualityCategory.Poor:
+ num = 0.75f;
+ break;
+ case QualityCategory.Normal:
+ num = 1f;
+ break;
+ case QualityCategory.Excellent:
+ num = 1.1f;
+ break;
+ case QualityCategory.Masterwork:
+ num = 1.2f;
+ break;
+ case QualityCategory.Legendary:
+ num = 1.3f;
+ break;
+ default:
+ Log.Message("Unknown QualityCategory, returning default qualityFactor = 1");
+ break;
+ }
+ hitChance *= num;
+ }
+ else
+ {
+ hitChance *= 1.5f * thing.def.fillPercent;
+ }
+ return Mathf.Clamp(hitChance, 0f, 1f);
+ }
- protected Vector3 exactPositionInt;
+ public virtual void MovementTick()
+ {
+ Vector3 vect = ExactPosition + curSpeed;
+ ShootLine shootLine = new ShootLine(ExactPosition.ToIntVec3(), vect.ToIntVec3());
+ Vector3 vector = (intendedTarget.Cell.ToVector3() - ExactPosition).Yto0();
+ if (homing)
+ {
+ Vector3 vector2 = vector.normalized - curSpeed.normalized;
+ if (vector2.sqrMagnitude >= 1.414f)
+ {
+ homing = false;
+ lifetime = HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
+ ticksToImpact = lifetime;
+ base.HitFlags &= ~ProjectileHitFlags.IntendedTarget;
+ base.HitFlags |= ProjectileHitFlags.NonTargetPawns;
+ base.HitFlags |= ProjectileHitFlags.NonTargetWorld;
+ }
+ else
+ {
+ curSpeed += vector2 * HomingDef.homingSpeed * curSpeed.magnitude;
+ }
+ }
+ foreach (IntVec3 item in shootLine.Points())
+ {
+ if (!((intendedTarget.Cell - item).SqrMagnitude <= HomingDef.proximityFuseRange * HomingDef.proximityFuseRange))
+ {
+ continue;
+ }
+ homing = false;
+ lifetime = HomingDef.destroyTicksAfterLosingTrack.RandomInRange;
+ if ((base.HitFlags & ProjectileHitFlags.IntendedTarget) == ProjectileHitFlags.IntendedTarget || HomingDef.proximityFuseRange > 0f)
+ {
+ lifetime = 0;
+ ticksToImpact = 0;
+ vect = item.ToVector3();
+ if (Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && def.projectile.soundImpactAnticipate != null)
+ {
+ def.projectile.soundImpactAnticipate.PlayOneShot(this);
+ }
+ }
+ }
+ exactPositionInt = vect;
+ curSpeed *= (curSpeed.magnitude + HomingDef.SpeedChangeTilesPerTickOverride) / curSpeed.magnitude;
+ }
- public Vector3 curSpeed;
+ protected override void Tick()
+ {
+ ThingWithCompsTick();
+ lifetime--;
+
+ // 处理拖尾特效
+ if (HomingDef != null && HomingDef.tailFleckDef != null)
+ {
+ Fleck_MakeFleckTick++;
+ if (Fleck_MakeFleckTick >= HomingDef.fleckMakeFleckTickMax)
+ {
+ Fleck_MakeFleckTick = 0;
+ Map map = base.Map;
+ int randomInRange = HomingDef.fleckMakeFleckNum.RandomInRange;
+ Vector3 currentPosition = ExactPosition;
+ Vector3 previousPosition = lastTickPosition;
- public bool homing = true;
+ for (int i = 0; i < randomInRange; i++)
+ {
+ float num = (currentPosition - previousPosition).AngleFlat();
+ float velocityAngle = HomingDef.fleckAngle.RandomInRange + num;
+ float randomInRange2 = HomingDef.fleckScale.RandomInRange;
+ float randomInRange3 = HomingDef.fleckSpeed.RandomInRange;
+
+ FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, HomingDef.tailFleckDef, randomInRange2);
+ dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
+ dataStatic.rotationRate = HomingDef.fleckRotation.RandomInRange;
+ dataStatic.velocityAngle = velocityAngle;
+ dataStatic.velocitySpeed = randomInRange3;
+ map.flecks.CreateFleck(dataStatic);
+ }
+ }
+ }
+ lastTickPosition = ExactPosition; // 更新上一帧位置
- private static MethodInfo ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
- }
+ if (landed)
+ {
+ return;
+ }
+ Vector3 exactPosition = ExactPosition;
+ ticksToImpact--;
+ MovementTick();
+ if (!ExactPosition.InBounds(base.Map))
+ {
+ base.Position = exactPosition.ToIntVec3();
+ Destroy();
+ return;
+ }
+ Vector3 exactPosition2 = ExactPosition;
+ object[] parameters = new object[2] { exactPosition, exactPosition2 };
+ if (!(bool)NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters))
+ {
+ base.Position = ExactPosition.ToIntVec3();
+ if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && def.projectile.soundImpactAnticipate != null)
+ {
+ def.projectile.soundImpactAnticipate.PlayOneShot(this);
+ }
+ if (ticksToImpact <= 0)
+ {
+ ImpactSomething();
+ }
+ else if (ambientSustainer != null)
+ {
+ ambientSustainer.Maintain();
+ }
+ }
+ }
+
+ private void ThingWithCompsTick()
+ {
+ if (comps != null)
+ {
+ int i = 0;
+ for (int count = comps.Count; i < count; i++)
+ {
+ comps[i].CompTick();
+ }
+ }
+ }
+
+ protected override void Impact(Thing hitThing, bool blockedByShield = false)
+ {
+ Map map = base.Map;
+ IntVec3 position = base.Position;
+ base.Impact(hitThing, blockedByShield);
+ if (HomingDef.extraProjectile != null)
+ {
+ if (hitThing != null && hitThing.Spawned)
+ {
+ ((Projectile)GenSpawn.Spawn(HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(launcher, ExactPosition, hitThing, hitThing, ProjectileHitFlags.All, false, null, null);
+ }
+ else
+ {
+ ((Projectile)GenSpawn.Spawn(HomingDef.extraProjectile, base.Position, map, WipeMode.Vanish)).Launch(launcher, ExactPosition, position, position, ProjectileHitFlags.All, false, null, null);
+ }
+ }
+ }
+
+ public override void ExposeData()
+ {
+ base.ExposeData();
+ Scribe_Values.Look(ref exactPositionInt, "exactPosition");
+ Scribe_Values.Look(ref curSpeed, "curSpeed");
+ Scribe_Values.Look(ref homing, "homing", defaultValue: false);
+ if (Scribe.mode == LoadSaveMode.PostLoadInit)
+ {
+ ReflectInit();
+ if (this.homingDefInt == null)
+ {
+ this.homingDefInt = this.def.GetModExtension();
+ if (this.homingDefInt == null)
+ {
+ Log.ErrorOnce($"HomingProjectileDef is null for projectile {this.def.defName} after PostLoadInit. Creating a default instance.", this.thingIDNumber ^ 0x12345678);
+ this.homingDefInt = new HomingProjectileDef();
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Projectile_WulaBeam.cs b/Source/WulaFallenEmpire/Projectile_WulaBeam.cs
index ff6d1fd8..b8d22d11 100644
--- a/Source/WulaFallenEmpire/Projectile_WulaBeam.cs
+++ b/Source/WulaFallenEmpire/Projectile_WulaBeam.cs
@@ -84,19 +84,32 @@ namespace WulaFallenEmpire
{
if (!infinitePenetration && hitCounter >= maxHits) break;
- if (thing is Pawn pawn && pawn != launcher && !alreadyDamaged.Contains(pawn))
+ // 统一处理 Pawn 和 Building 的伤害逻辑
+ // 确保 Thing 未被伤害过且不是发射者
+ if (thing != launcher && !alreadyDamaged.Contains(thing))
{
bool shouldDamage = false;
- if (intendedTarget.Thing == pawn) shouldDamage = true;
- else if (pawn.HostileTo(launcher)) shouldDamage = true;
- else if (!shouldPreventFriendlyFire) shouldDamage = true;
+ Pawn pawn = thing as Pawn;
+ Building building = thing as Building;
+
+ if (pawn != null) // 如果是 Pawn
+ {
+ if (intendedTarget.Thing == pawn) shouldDamage = true;
+ else if (pawn.HostileTo(launcher)) shouldDamage = true;
+ else if (!shouldPreventFriendlyFire) shouldDamage = true;
+ }
+ else if (building != null) // 如果是 Building
+ {
+ shouldDamage = true; // 默认对 Building 造成伤害
+ }
if (shouldDamage)
{
- ApplyPathDamage(pawn, props);
+ ApplyPathDamage(thing, props); // 传递 Thing
}
}
- else if (thing.def.Fillage == FillCategory.Full && thing.def.blockLight)
+ // 只有当遇到完全阻挡的 Thing 且不是 Pawn 或 Building 时才停止穿透
+ else if (thing.def.Fillage == FillCategory.Full && thing.def.blockLight && !(thing is Pawn) && !(thing is Building))
{
break;
}
@@ -105,9 +118,15 @@ namespace WulaFallenEmpire
this.Destroy(DestroyMode.Vanish);
}
- private void ApplyPathDamage(Pawn pawn, Wula_BeamPierce_Extension props)
+ private void ApplyPathDamage(Thing targetThing, Wula_BeamPierce_Extension props) // 接受 Thing 参数
{
- float damageMultiplier = Mathf.Pow(1f - props.damageFalloff, hitCounter);
+ float damageMultiplier = 1f;
+ if (targetThing is Pawn) // 只有 Pawn 才计算穿透衰减
+ {
+ damageMultiplier = Mathf.Pow(1f - props.damageFalloff, hitCounter);
+ }
+ // Building 不受穿透衰减影响,或者 Building 的穿透衰减始终为 1 (不衰减)
+
int damageAmount = (int)(this.DamageAmount * damageMultiplier);
if (damageAmount <= 0) return;
@@ -123,9 +142,13 @@ namespace WulaFallenEmpire
DamageInfo.SourceCategory.ThingOrUnknown,
this.intendedTarget.Thing);
- pawn.TakeDamage(dinfo);
- alreadyDamaged.Add(pawn);
- hitCounter++;
+ targetThing.TakeDamage(dinfo); // 对 targetThing 造成伤害
+ alreadyDamaged.Add(targetThing);
+
+ if (targetThing is Pawn) // 只有 Pawn 才增加 hitCounter
+ {
+ hitCounter++;
+ }
}
protected override void Tick() { }
diff --git a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
index 2f3b1df4..ed182f5e 100644
--- a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
+++ b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
@@ -17,7 +17,7 @@ namespace WulaFallenEmpire
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
}
- public class Projectile_WulaLineAttack : Projectile
+ public class Projectile_WulaLineAttack : Bullet
{
private int hitCounter = 0;
private List alreadyDamaged = new List();
diff --git a/Source/WulaFallenEmpire/Verb/Trackingbullet.cs b/Source/WulaFallenEmpire/Verb/Trackingbullet.cs
index f49445ca..a74d6794 100644
--- a/Source/WulaFallenEmpire/Verb/Trackingbullet.cs
+++ b/Source/WulaFallenEmpire/Verb/Trackingbullet.cs
@@ -1,8 +1,6 @@
using RimWorld;
using System.Collections.Generic;
-using Verse.Sound;
using System.Linq;
-using System.Reflection;
using UnityEngine;
using Verse;
@@ -22,150 +20,74 @@ namespace WulaFallenEmpire
public float subExplosionSpread = 6f;
public DamageDef subDamageDef;
public SoundDef subSoundExplode;
- public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
- public float homingSpeed = 0.1f;
- public float initRotateAngle = 30f;
- public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120);
- public float speedChangePerTick;
- public FloatRange? speedRangeOverride;
- public float proximityFuseRange = 0f;
+
+ // 新增的弹道配置参数
+ public float bezierArcHeightFactor = 0.05f; // 贝塞尔曲线高度因子
+ public float bezierMinArcHeight = 2f; // 贝塞尔曲线最小高度
+ public float bezierMaxArcHeight = 6f; // 贝塞尔曲线最大高度
+ public float bezierHorizontalOffsetFactor = 0.1f; // 贝塞尔曲线水平偏移因子
+ public float bezierSideOffsetFactor = 0.2f; // 贝塞尔曲线侧向偏移因子
+ public float bezierRandomOffsetScale = 0.5f; // 贝塞尔曲线随机偏移缩放
+
}
public class Projectile_CruiseMissile : Projectile_Explosive
{
private CruiseMissileProperties settings;
- protected Vector3 exactPositionInt;
- public Vector3 curSpeed;
- public bool homing = true;
- private Sustainer ambientSustainer;
- private List comps;
- private int ticksToDestroy = -1;
-
- // Launch 方法的参数作为字段
-
- // 拖尾特效相关字段
- private int Fleck_MakeFleckTick;
- public int Fleck_MakeFleckTickMax = 1;
- public IntRange Fleck_MakeFleckNum = new IntRange(1, 1);
- public FloatRange Fleck_Angle = new FloatRange(-180f, 180f);
- public FloatRange Fleck_Scale = new FloatRange(1f, 1f);
- public FloatRange Fleck_Speed = new FloatRange(0f, 0f);
- public FloatRange Fleck_Rotation = new FloatRange(-180f, 180f);
+ private bool flag2;
+ private Vector3 Randdd;
+ private Vector3 position2;
+ public Vector3 ExPos;
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
settings = def.GetModExtension() ?? new CruiseMissileProperties();
- this.ReflectInit();
}
- public override void Launch(Thing launcherParam, Vector3 originParam, LocalTargetInfo usedTargetParam, LocalTargetInfo intendedTargetParam, ProjectileHitFlags hitFlagsParam, bool preventFriendlyFireParam = false, Thing equipmentParam = null, ThingDef targetCoverDefParam = null)
+ private void RandFactor()
{
- this.launcher = launcherParam;
- this.origin = originParam;
- this.usedTarget = usedTargetParam;
- this.intendedTarget = intendedTargetParam;
- this.HitFlags = hitFlagsParam;
- this.preventFriendlyFire = preventFriendlyFireParam;
- this.equipment = equipmentParam;
- this.targetCoverDef = targetCoverDefParam;
-
- this.exactPositionInt = origin.Yto0() + Vector3.up * this.def.Altitude;
- Vector3 normalized = (this.destination - origin).Yto0().normalized;
- float degrees = Rand.Range(-this.settings.initRotateAngle, this.settings.initRotateAngle);
- Vector2 vector = new Vector2(normalized.x, normalized.z);
- vector = vector.RotatedBy(degrees);
- Vector3 a = new Vector3(vector.x, 0f, vector.y);
- bool flag6 = this.settings.speedRangeOverride == null;
- if (flag6)
- {
- this.curSpeed = a * this.def.projectile.SpeedTilesPerTick;
- }
- else
- {
- this.curSpeed = a * this.settings.speedRangeOverride.Value.RandomInRange;
- }
- this.ticksToImpact = int.MaxValue;
- this.lifetime = int.MaxValue;
+ // 调整随机范围,用于控制C形弹道的随机偏移
+ Randdd = new Vector3(
+ Rand.Range(-settings.bezierRandomOffsetScale, settings.bezierRandomOffsetScale), // X轴的随机偏移
+ Rand.Range(0f, 0f), // Y轴(高度)不进行随机,保持平稳
+ Rand.Range(-settings.bezierRandomOffsetScale, settings.bezierRandomOffsetScale) // Z轴的随机偏移
+ );
+ flag2 = true;
}
- protected void ReflectInit()
+ public Vector3 BPos(float t)
{
- if (NonPublicFields.Projectile_AmbientSustainer == null)
- {
- NonPublicFields.Projectile_AmbientSustainer = typeof(Projectile).GetField("ambientSustainer", BindingFlags.Instance | BindingFlags.NonPublic);
- }
- if (NonPublicFields.ThingWithComps_comps == null)
- {
- NonPublicFields.ThingWithComps_comps = typeof(ThingWithComps).GetField("comps", BindingFlags.Instance | BindingFlags.NonPublic);
- }
- if (NonPublicFields.ProjectileCheckForFreeInterceptBetween == null)
- {
- NonPublicFields.ProjectileCheckForFreeInterceptBetween = typeof(Projectile).GetMethod("CheckForFreeInterceptBetween", BindingFlags.Instance | BindingFlags.NonPublic);
- }
+ if (!flag2) RandFactor();
- bool flag = !this.def.projectile.soundAmbient.NullOrUndefined();
- if (flag)
- {
- this.ambientSustainer = (Sustainer)NonPublicFields.Projectile_AmbientSustainer.GetValue(this);
- }
- this.comps = (List)NonPublicFields.ThingWithComps_comps.GetValue(this);
+ // 计算水平距离
+ float horizontalDistance = Vector3.Distance(new Vector3(origin.x, 0, origin.z),
+ new Vector3(destination.x, 0, destination.z));
+
+ // 动态调整控制点高度,使其更扁平,使用XML配置的高度因子
+ float arcHeight = Mathf.Clamp(horizontalDistance * settings.bezierArcHeightFactor, settings.bezierMinArcHeight, settings.bezierMaxArcHeight);
+
+ // 计算从起点到终点的方向向量
+ Vector3 direction = (destination - origin).normalized;
+ // 计算垂直于方向向量的水平向量(用于侧向偏移),确保C形弯曲方向一致
+ Vector3 perpendicularDirection = Vector3.Cross(direction, Vector3.up).normalized;
+
+ // 调整控制点以形成扁平 C 形,使用XML配置的偏移因子
+ // P1: 在起点附近,向前偏移,向上偏移,并向一侧偏移
+ Vector3 p1 = origin + direction * horizontalDistance * settings.bezierHorizontalOffsetFactor + Vector3.up * arcHeight + perpendicularDirection * horizontalDistance * settings.bezierSideOffsetFactor + Randdd;
+ // P2: 在终点附近,向后偏移,向上偏移,并向同一侧偏移
+ Vector3 p2 = destination - direction * horizontalDistance * settings.bezierHorizontalOffsetFactor + Vector3.up * arcHeight + perpendicularDirection * horizontalDistance * settings.bezierSideOffsetFactor + Randdd;
+
+ return BezierCurve(origin, p1, p2, destination, t);
}
- public float GetHitChance(Thing thing)
+ private Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
- float num = this.settings.homingSpeed;
- bool flag = thing == null;
- float result;
- if (flag)
- {
- result = num;
- }
- else
- {
- Pawn pawn = thing as Pawn;
- bool flag2 = pawn != null;
- if (flag2)
- {
- num *= Mathf.Clamp(pawn.BodySize, 0.5f, 1.5f);
- bool flag3 = pawn.GetPosture() > PawnPosture.Standing;
- if (flag3)
- {
- num *= 0.5f;
- }
- float num2 = 1f;
- switch (this.equipmentQuality)
- {
- case QualityCategory.Awful:
- num2 = 0.5f;
- goto IL_DD;
- case QualityCategory.Poor:
- num2 = 0.75f;
- goto IL_DD;
- case QualityCategory.Normal:
- num2 = 1f;
- goto IL_DD;
- case QualityCategory.Excellent:
- num2 = 1.1f;
- goto IL_DD;
- case QualityCategory.Masterwork:
- num2 = 1.2f;
- goto IL_DD;
- case QualityCategory.Legendary:
- num2 = 1.3f;
- goto IL_DD;
- }
- Log.Message("Unknown QualityCategory, returning default qualityFactor = 1");
- IL_DD:
- num *= num2;
- }
- else
- {
- num *= 1.5f * thing.def.fillPercent;
- }
- result = Mathf.Clamp(num, 0f, 1f);
- }
- return result;
+ float u = 1 - t;
+ return u * u * u * p0
+ + 3 * u * u * t * p1
+ + 3 * u * t * t * p2
+ + t * t * t * p3;
}
private IEnumerable GetValidCells(Map map)
@@ -230,149 +152,43 @@ namespace WulaFallenEmpire
);
}
- public override Quaternion ExactRotation
+ protected override void DrawAt(Vector3 position, bool flip = false)
{
- get
- {
- return Quaternion.LookRotation(this.curSpeed);
- }
- }
- public override Vector3 ExactPosition
- {
- get
- {
- return this.exactPositionInt;
- }
+ position2 = BPos(DistanceCoveredFraction - 0.01f);
+ ExPos = position = BPos(DistanceCoveredFraction);
+ base.DrawAt(position, flip);
}
protected override void Tick()
{
- this.ThingWithCompsTick();
- this.lifetime--;
- if (this.settings.tailFleckDef != null)
+ if (intendedTarget.Thing is Pawn pawn && pawn.Spawned && !pawn.Destroyed)
{
- this.Fleck_MakeFleckTick++;
- if (this.Fleck_MakeFleckTick >= this.Fleck_MakeFleckTickMax)
+ if ((pawn.Dead || pawn.Downed) && DistanceCoveredFraction < 0.6f)
{
- this.Fleck_MakeFleckTick = 0;
- for (int i = 0; i < this.Fleck_MakeFleckNum.RandomInRange; i++)
- {
- FleckMaker.Static(this.ExactPosition + Gen.RandomHorizontalVector(this.Fleck_Scale.RandomInRange / 2f), base.Map, this.settings.tailFleckDef, this.Fleck_Scale.RandomInRange);
- }
- }
- }
-
- bool landed = this.landed;
- if (!landed)
- {
- Vector3 exactPosition = this.ExactPosition;
- this.ticksToImpact--;
- this.MovementTick();
- bool flag = !this.ExactPosition.InBounds(base.Map);
- if (flag)
- {
- base.Position = exactPosition.ToIntVec3();
- this.Destroy(DestroyMode.Vanish);
- }
- else
- {
- Vector3 exactPosition2 = this.ExactPosition;
- object[] parameters = new object[]
- {
- exactPosition,
- exactPosition2
- };
- bool flag2 = (bool)NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
- if (!flag2)
- {
- base.Position = this.ExactPosition.ToIntVec3();
- bool flag3 = this.ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null;
- if (flag3)
- {
- this.def.projectile.soundImpactAnticipate.PlayOneShot(this);
- }
- bool flag4 = this.ticksToImpact <= 0;
- if (flag4)
- {
- this.Impact(null);
- }
- else
- {
- bool flag5 = this.ambientSustainer != null;
- if (flag5)
- {
- this.ambientSustainer.Maintain();
- }
- }
- }
+ FindNextTarget(pawn.DrawPos);
}
+ destination = pawn.DrawPos;
}
+ base.Tick();
}
- private void MovementTick()
+ private void FindNextTarget(Vector3 center)
{
- if (this.homing)
+ var map = base.Map;
+ if (map == null) return;
+
+ foreach (IntVec3 cell in GenRadial.RadialCellsAround(IntVec3.FromVector3(center), 7f, true))
{
- if (this.intendedTarget != null && this.intendedTarget.Thing != null)
+ if (!cell.InBounds(map)) continue;
+
+ Pawn target = cell.GetFirstPawn(map);
+ if (target != null && target.Faction.HostileTo(launcher?.Faction))
{
- Vector3 vector = (this.intendedTarget.Thing.DrawPos - this.exactPositionInt).normalized;
- this.curSpeed = Vector3.RotateTowards(this.curSpeed, vector * this.curSpeed.magnitude, this.settings.homingSpeed, 0f);
- }
- else if (this.ticksToDestroy == -1)
- {
- this.ticksToDestroy = this.settings.destroyTicksAfterLosingTrack.RandomInRange;
- }
- }
- if (this.ticksToDestroy > 0)
- {
- this.ticksToDestroy--;
- if (this.ticksToDestroy == 0)
- {
- this.Destroy(DestroyMode.Vanish);
+ intendedTarget = target;
return;
}
}
- if (this.settings.speedChangePerTick != 0f)
- {
- this.curSpeed = this.curSpeed.normalized * (this.curSpeed.magnitude + this.settings.speedChangePerTick);
- }
- if (this.settings.proximityFuseRange > 0f)
- {
- if (this.intendedTarget != null && this.intendedTarget.Thing != null && (this.intendedTarget.Thing.DrawPos - this.exactPositionInt).magnitude < this.settings.proximityFuseRange)
- {
- this.Impact(null);
- return;
- }
- }
-
- this.exactPositionInt += this.curSpeed;
+ intendedTarget = CellRect.CenteredOn(IntVec3.FromVector3(center), 7).RandomCell;
}
-
- protected void ThingWithCompsTick()
- {
- if (this.comps != null)
- {
- for (int i = 0; i < this.comps.Count; i++)
- {
- this.comps[i].CompTick();
- }
- }
- }
-
- public override void ExposeData()
- {
- base.ExposeData();
- Scribe_Values.Look(ref this.exactPositionInt, "exactPosition", default(Vector3), false);
- Scribe_Values.Look(ref this.curSpeed, "curSpeed", default(Vector3), false);
- Scribe_Values.Look(ref this.homing, "homing", true, false);
- Scribe_Values.Look(ref this.ticksToDestroy, "ticksToDestroy", -1, false);
- }
- }
-
- public static class NonPublicFields
- {
- public static FieldInfo Projectile_AmbientSustainer;
- public static FieldInfo ThingWithComps_comps;
- public static MethodInfo ProjectileCheckForFreeInterceptBetween;
}
}
\ No newline at end of file