diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index ef72ddc5..f6ffb914 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/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 3cf0c030..b55c3dd7 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
@@ -69,7 +69,7 @@
WulaFallenEmpire.Projectile_TrackingBullet
- 30
+ 60
Bullet
15
0.5
@@ -78,7 +78,12 @@
0.5
- 10
+ 30
+
+ 60
+ 120
+
+ WULA_GunTail_Blue
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 b6c7a27f..0c5ee6cd 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
@@ -89,7 +89,17 @@
0.5
5
-
+
+ 60
+ 120
+
+ Mote_BlastFlame
+ 3
+ 1
+ 30
+ 0.8~1.2
+ 0.2~0.5
+ 0~360
diff --git a/Source/WulaFallenEmpire/ExplosiveTrackingBulletDef.cs b/Source/WulaFallenEmpire/ExplosiveTrackingBulletDef.cs
new file mode 100644
index 00000000..e98fcc79
--- /dev/null
+++ b/Source/WulaFallenEmpire/ExplosiveTrackingBulletDef.cs
@@ -0,0 +1,24 @@
+using Verse;
+using RimWorld;
+
+namespace WulaFallenEmpire
+{
+ public class ExplosiveTrackingBulletDef : DefModExtension
+ {
+ public float explosionRadius = 1.9f;
+ public DamageDef damageDef;
+ public int explosionDelay = 0;
+ public SoundDef soundExplode;
+ public FleckDef preExplosionFlash;
+ public ThingDef postExplosionSpawnThingDef;
+ public float postExplosionSpawnChance = 0f;
+ public int postExplosionSpawnThingCount = 1;
+ public GasType? gasType; // 修改为可空类型
+ public bool applyDamageToExplosionCellsNeighbors = false;
+ public bool doExplosionDamageAfterThingDestroyed = false;
+ public float preExplosionSpawnMinMeleeThreat = -1f;
+ public float explosionChanceToStartFire = 0f; // 从bool改为float,并设置默认值
+ public bool explosionDamageFalloff = false;
+ public bool doExplosionVFX = true;
+ }
+}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Projectile_ExplosiveTrackingBullet.cs b/Source/WulaFallenEmpire/Projectile_ExplosiveTrackingBullet.cs
new file mode 100644
index 00000000..2c407f2e
--- /dev/null
+++ b/Source/WulaFallenEmpire/Projectile_ExplosiveTrackingBullet.cs
@@ -0,0 +1,77 @@
+using RimWorld;
+using UnityEngine;
+using Verse;
+using Verse.Sound;
+
+namespace WulaFallenEmpire
+{
+ public class Projectile_ExplosiveTrackingBullet : Projectile_TrackingBullet
+ {
+ private ExplosiveTrackingBulletDef explosiveDefInt;
+
+ public ExplosiveTrackingBulletDef ExplosiveDef
+ {
+ get
+ {
+ if (explosiveDefInt == null)
+ {
+ explosiveDefInt = def.GetModExtension();
+ if (explosiveDefInt == null)
+ {
+ Log.ErrorOnce($"ExplosiveTrackingBulletDef for {this.def.defName} is null. Creating a default instance.", this.thingIDNumber ^ 0x12345679);
+ this.explosiveDefInt = new ExplosiveTrackingBulletDef();
+ }
+ }
+ return explosiveDefInt;
+ }
+ }
+
+ protected override void Impact(Thing hitThing, bool blockedByShield = false)
+ {
+ base.Impact(hitThing, blockedByShield); // 调用基类的Impact逻辑
+
+ if (ExplosiveDef.explosionRadius > 0f)
+ {
+ // 爆炸逻辑
+ GenExplosion.DoExplosion(
+ center: Position, // 爆炸中心
+ map: Map, // 地图
+ radius: ExplosiveDef.explosionRadius, // 爆炸半径
+ damType: ExplosiveDef.damageDef ?? DamageDefOf.Bomb, // 伤害类型,如果未配置则默认为Bomb
+ instigator: launcher, // 制造者
+ damAmount: this.DamageAmount, // 伤害量,使用子弹当前的伤害量
+ armorPenetration: this.ArmorPenetration, // 护甲穿透,使用子弹当前的护甲穿透
+ explosionSound: ExplosiveDef.soundExplode, // 爆炸音效
+ weapon: equipmentDef, // 武器
+ projectile: def, // 弹药定义
+ intendedTarget: intendedTarget.Thing, // 预期目标
+ postExplosionSpawnThingDef: ExplosiveDef.postExplosionSpawnThingDef, // 爆炸后生成物
+ postExplosionSpawnChance: ExplosiveDef.postExplosionSpawnChance, // 爆炸后生成几率
+ postExplosionSpawnThingCount: ExplosiveDef.postExplosionSpawnThingCount, // 爆炸后生成数量
+ postExplosionGasType: ExplosiveDef.gasType, // 气体类型 (注意参数名已修正)
+ postExplosionGasRadiusOverride: null, // 爆炸气体半径覆盖 (我没有定义这个参数)
+ postExplosionGasAmount: 255, // 爆炸气体数量 (默认值)
+ applyDamageToExplosionCellsNeighbors: ExplosiveDef.applyDamageToExplosionCellsNeighbors, // 是否对爆炸单元格邻居造成伤害
+ preExplosionSpawnThingDef: null, // 爆炸前生成物 (我没有定义这个参数)
+ preExplosionSpawnChance: 0f, // 爆炸前生成几率 (默认值)
+ preExplosionSpawnThingCount: 0, // 爆炸前生成数量 (默认值)
+ chanceToStartFire: ExplosiveDef.explosionChanceToStartFire, // 是否有几率点燃 (注意参数名已修正)
+ damageFalloff: ExplosiveDef.explosionDamageFalloff, // 爆炸伤害衰减
+ direction: null, // 方向 (我没有定义这个参数)
+ ignoredThings: null, // 忽略的物体 (我没有定义这个参数)
+ affectedAngle: null, // 受影响角度 (我没有定义这个参数)
+ doVisualEffects: ExplosiveDef.doExplosionVFX, // 是否显示视觉效果
+ propagationSpeed: 1f, // 传播速度 (默认值)
+ excludeRadius: 0f, // 排除半径 (默认值)
+ doSoundEffects: true, // 是否播放音效 (默认值)
+ postExplosionSpawnThingDefWater: null, // 爆炸后在水中生成物 (我没有定义这个参数)
+ screenShakeFactor: 1f, // 屏幕震动因子 (默认值)
+ flammabilityChanceCurve: null, // 易燃性几率曲线 (我没有定义这个参数)
+ overrideCells: null, // 覆盖单元格 (我没有定义这个参数)
+ postExplosionSpawnSingleThingDef: null, // 爆炸后生成单个物体 (我没有定义这个参数)
+ preExplosionSpawnSingleThingDef: null // 爆炸前生成单个物体 (我没有定义这个参数)
+ );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Projectile_TrackingBullet.cs b/Source/WulaFallenEmpire/Projectile_TrackingBullet.cs
index 4dc05f36..07b1aa2c 100644
--- a/Source/WulaFallenEmpire/Projectile_TrackingBullet.cs
+++ b/Source/WulaFallenEmpire/Projectile_TrackingBullet.cs
@@ -15,6 +15,9 @@ namespace WulaFallenEmpire
protected Vector3 exactPositionInt;
public Vector3 curSpeed;
public bool homing = true;
+ private int destroyTicksAfterLosingTrack = -1; // 失去追踪后多少tick自毁,-1表示不自毁
+ private int Fleck_MakeFleckTick; // 拖尾特效的计时器
+ private Vector3 lastTickPosition; // 记录上一帧的位置,用于计算移动方向
private static class NonPublicFields
{
@@ -58,6 +61,7 @@ namespace WulaFallenEmpire
curSpeed = rotatedDirection * def.projectile.SpeedTilesPerTick;
ReflectInit();
+ lastTickPosition = origin; // 初始化 lastTickPosition
}
protected void ReflectInit()
@@ -80,67 +84,41 @@ namespace WulaFallenEmpire
if (homing)
{
- // 计算需要转向的方向
- Vector3 desiredDirection = vectorToTarget.normalized;
- Vector3 currentDirection = curSpeed.normalized;
-
- // 计算方向差异
- Vector3 directionDifference = desiredDirection - currentDirection;
-
- // 如果方向差异过大,可能失去追踪,或者直接转向
- if (directionDifference.sqrMagnitude > 0.001f) // 避免浮点数精度问题
+ // 如果目标消失或距离太远,停止追踪
+ if (!intendedTarget.IsValid || !intendedTarget.Thing.Spawned || (intendedTarget.Cell.ToVector3() - ExactPosition).magnitude > def.projectile.speed * 2f) // 假设2倍速度为最大追踪距离
{
- // 调整当前速度,使其更接近目标方向
- curSpeed += directionDifference * TrackingDef.homingSpeed * curSpeed.magnitude;
- curSpeed = curSpeed.normalized * def.projectile.SpeedTilesPerTick; // 保持速度恒定
+ homing = false;
+ destroyTicksAfterLosingTrack = TrackingDef.destroyTicksAfterLosingTrack.RandomInRange; // 失去追踪后根据XML配置的范围自毁
+ }
+ else
+ {
+ // 计算需要转向的方向
+ Vector3 desiredDirection = vectorToTarget.normalized;
+ Vector3 currentDirection = curSpeed.normalized;
+
+ // 计算方向差异
+ Vector3 directionDifference = desiredDirection - currentDirection;
+
+ // 如果方向差异过大,可能失去追踪,或者直接转向
+ if (directionDifference.sqrMagnitude > 0.001f) // 避免浮点数精度问题
+ {
+ // 调整当前速度,使其更接近目标方向
+ curSpeed += directionDifference * TrackingDef.homingSpeed * curSpeed.magnitude;
+ curSpeed = curSpeed.normalized * def.projectile.SpeedTilesPerTick; // 保持速度恒定
+ }
}
}
exactPositionInt = ExactPosition + curSpeed; // 更新位置
}
- protected override void Tick()
- {
- base.Tick(); // 调用父类Bullet的Tick,处理一些基本逻辑,如lifetime, ticksToImpact
-
- MovementTick(); // 调用追踪移动逻辑
-
- // 检查是否撞到东西或超出地图
- Vector3 exactPosition = ExactPosition; // 之前的ExactPosition
- ticksToImpact--; // 减少impact计时器
-
- if (!ExactPosition.InBounds(base.Map)) // 超出地图边界
- {
- base.Position = exactPosition.ToIntVec3(); // 设回旧位置,然后销毁
- Destroy();
- return;
- }
-
- // 检查是否有东西在路径上拦截
- Vector3 exactPositionAfterMove = ExactPosition; // 移动后的ExactPosition
- object[] parameters = new object[2] { exactPosition, exactPositionAfterMove };
- if (!(bool)NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters))
- {
- base.Position = ExactPosition.ToIntVec3(); // 更新位置到当前精确位置
- if (ticksToImpact <= 0) // 达到impact时间
- {
- ImpactSomething(); // 触发Impact
- }
- }
- }
-
- protected override void Impact(Thing hitThing, bool blockedByShield = false)
- {
- // 默认Impact逻辑,可以根据需要扩展
- base.Impact(hitThing, blockedByShield);
- }
-
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: true);
+ Scribe_Values.Look(ref destroyTicksAfterLosingTrack, "destroyTicksAfterLosingTrack", -1);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
ReflectInit();
@@ -155,5 +133,84 @@ namespace WulaFallenEmpire
}
}
}
+
+ protected override void Tick()
+ {
+ base.Tick(); // 调用父类Bullet的Tick,处理 ticksToImpact 减少和最终命中
+
+ if (destroyTicksAfterLosingTrack > 0)
+ {
+ destroyTicksAfterLosingTrack--;
+ if (destroyTicksAfterLosingTrack <= 0)
+ {
+ Destroy(); // 如果自毁计时器归零,直接销毁
+ return;
+ }
+ }
+
+ // 处理拖尾特效
+ if (TrackingDef != null && TrackingDef.tailFleckDef != null)
+ {
+ Fleck_MakeFleckTick++;
+ // 只有当达到延迟时间后才开始生成Fleck
+ if (Fleck_MakeFleckTick >= TrackingDef.fleckDelayTicks)
+ {
+ if (Fleck_MakeFleckTick >= (TrackingDef.fleckDelayTicks + TrackingDef.fleckMakeFleckTickMax))
+ {
+ Fleck_MakeFleckTick = TrackingDef.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
+ }
+
+ Map map = base.Map;
+ int randomInRange = TrackingDef.fleckMakeFleckNum.RandomInRange;
+ Vector3 currentPosition = ExactPosition;
+ Vector3 previousPosition = lastTickPosition;
+
+ for (int i = 0; i < randomInRange; i++)
+ {
+ float num = (currentPosition - previousPosition).AngleFlat();
+ float velocityAngle = TrackingDef.fleckAngle.RandomInRange + num;
+ float randomInRange2 = TrackingDef.fleckScale.RandomInRange;
+ float randomInRange3 = TrackingDef.fleckSpeed.RandomInRange;
+
+ FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, TrackingDef.tailFleckDef, randomInRange2);
+ dataStatic.rotation = (currentPosition - previousPosition).AngleFlat();
+ dataStatic.rotationRate = TrackingDef.fleckRotation.RandomInRange;
+ dataStatic.velocityAngle = velocityAngle;
+ dataStatic.velocitySpeed = randomInRange3;
+ map.flecks.CreateFleck(dataStatic);
+ }
+ }
+ }
+ lastTickPosition = ExactPosition; // 更新上一帧位置
+
+ // 保存移动前的精确位置
+ Vector3 exactPositionBeforeMove = exactPositionInt;
+
+ MovementTick(); // 调用追踪移动逻辑,更新 exactPositionInt (即新的 ExactPosition)
+
+ // 检查是否超出地图边界
+ if (!ExactPosition.InBounds(base.Map))
+ {
+ // 如果超出地图,直接销毁,不触发 ImpactSomething()
+ Destroy();
+ return;
+ }
+
+ // 检查是否有东西在路径上拦截
+ // ProjectileCheckForFreeInterceptBetween 会在内部处理命中,并调用 ImpactSomething()
+ // 所以这里不需要额外的 ImpactSomething() 调用
+ object[] parameters = new object[2] { exactPositionBeforeMove, exactPositionInt }; // 传入移动前和移动后的位置
+
+ // 调用 ProjectileCheckForFreeInterceptBetween
+ // 如果它返回 true,说明有拦截,并且拦截逻辑已在内部处理。
+ // 如果返回 false,说明没有拦截,子弹继续飞行。
+ NonPublicFields.ProjectileCheckForFreeInterceptBetween.Invoke(this, parameters);
+ }
+
+ protected override void Impact(Thing hitThing, bool blockedByShield = false)
+ {
+ // 默认Impact逻辑,可以根据需要扩展
+ base.Impact(hitThing, blockedByShield);
+ }
}
}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
index ed182f5e..9b8b3281 100644
--- a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
+++ b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
@@ -15,6 +15,7 @@ namespace WulaFallenEmpire
// If true, this projectile will never cause friendly fire, regardless of game settings.
public bool preventFriendlyFire = false;
public FleckDef tailFleckDef; // 用于配置拖尾特效的 FleckDef
+ public int fleckDelayTicks = 10; // 拖尾特效延迟生成时间(tick)
}
public class Projectile_WulaLineAttack : Bullet
@@ -62,26 +63,31 @@ namespace WulaFallenEmpire
if (this.Destroyed) return;
this.Fleck_MakeFleckTick++;
- bool flag = this.Fleck_MakeFleckTick >= this.Fleck_MakeFleckTickMax;
- if (flag)
+ // 只有当达到延迟时间后才开始生成Fleck
+ if (this.Fleck_MakeFleckTick >= Props.fleckDelayTicks)
{
- this.Fleck_MakeFleckTick = 0;
+ if (this.Fleck_MakeFleckTick >= (Props.fleckDelayTicks + this.Fleck_MakeFleckTickMax))
+ {
+ this.Fleck_MakeFleckTick = Props.fleckDelayTicks; // 重置计时器,从延迟时间开始循环
+ }
+
Map map = base.Map;
int randomInRange = this.Fleck_MakeFleckNum.RandomInRange;
- Vector3 vector = this.ExactPosition; // Current position of the bullet
- Vector3 vector2 = this.lastTickPosition; // Previous position of the bullet
+ Vector3 currentPosition = this.ExactPosition; // Current position of the bullet
+ Vector3 previousPosition = this.lastTickPosition; // Previous position of the bullet
for (int i = 0; i < randomInRange; i++)
{
- float num = (vector - vector2).AngleFlat(); // Angle based on movement direction
- float velocityAngle = this.Fleck_Angle.RandomInRange + num;
+ float currentBulletAngle = ExactRotation.eulerAngles.y; // 使用子弹当前的水平旋转角度
+ float fleckRotationAngle = currentBulletAngle; // Fleck 的旋转角度与子弹方向一致
+ float velocityAngle = this.Fleck_Angle.RandomInRange + currentBulletAngle; // Fleck 的速度角度基于子弹方向加上随机偏移
float randomInRange2 = this.Fleck_Scale.RandomInRange;
float randomInRange3 = this.Fleck_Speed.RandomInRange;
if (Props?.tailFleckDef != null)
{
- FleckCreationData dataStatic = FleckMaker.GetDataStatic(vector, map, Props.tailFleckDef, randomInRange2);
- dataStatic.rotation = (vector - vector2).AngleFlat();
+ FleckCreationData dataStatic = FleckMaker.GetDataStatic(currentPosition, map, Props.tailFleckDef, randomInRange2);
+ dataStatic.rotation = fleckRotationAngle;
dataStatic.rotationRate = this.Fleck_Rotation.RandomInRange;
dataStatic.velocityAngle = velocityAngle;
dataStatic.velocitySpeed = randomInRange3;
diff --git a/Source/WulaFallenEmpire/TrackingBulletDef.cs b/Source/WulaFallenEmpire/TrackingBulletDef.cs
index 43adcf11..f94a470d 100644
--- a/Source/WulaFallenEmpire/TrackingBulletDef.cs
+++ b/Source/WulaFallenEmpire/TrackingBulletDef.cs
@@ -6,5 +6,15 @@ namespace WulaFallenEmpire
{
public float homingSpeed = 0.1f; // 追踪速度,值越大追踪越灵敏
public float initRotateAngle = 0f; // 初始旋转角度
+
+ public FleckDef tailFleckDef; // 拖尾特效的FleckDef
+ public int fleckMakeFleckTickMax = 1; // 拖尾特效的生成间隔(tick)
+ public int fleckDelayTicks = 10; // 拖尾特效延迟生成时间(tick)
+ 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); // 拖尾特效的旋转速度范围
+ public IntRange destroyTicksAfterLosingTrack = new IntRange(60, 120); // 失去追踪后多少tick自毁
}
}
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 0fc83f50..53c40873 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -128,6 +128,8 @@
+
+