diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index db604075..b930915a 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.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
index fb6f39e3..73f74dac 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
@@ -1219,7 +1219,7 @@
0.6
3
- x
+
WulaFallenEmpire.Verb_ShootBeamExplosive
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml
index 3df15718..c6d234b2 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml
@@ -4,7 +4,7 @@
WULA_RW_Penetrating_Rifle
-
+
一把经过实验性改造的“蓝锥”步枪,能够发射一种特殊的钢针,利用过载的能量使其在击中第一个目标后仍能继续飞行,对路径上的多个敌人造成伤害。
Spacer
@@ -27,10 +27,10 @@
1300
3.5
- 0.3
- 0.8
- 0.9
- 0.8
+ 1.0
+ 1.0
+ 1.0
+ 1.0
0.8
@@ -59,7 +59,13 @@
Bullet_WULA_RW_Penetrating_Rifle
- WulaFallenEmpire.Projectile_WulaLineAttack
+ WulaFallenEmpire.Projectile_WulaLineAttack
+
+
+ -1
+ 0
+
+
Normal
True
diff --git a/Source/WulaFallenEmpire/CompMaintenancePod.cs b/Source/WulaFallenEmpire/CompMaintenancePod.cs
index f337a904..dee1f776 100644
--- a/Source/WulaFallenEmpire/CompMaintenancePod.cs
+++ b/Source/WulaFallenEmpire/CompMaintenancePod.cs
@@ -98,16 +98,6 @@ namespace WulaFallenEmpire
}
}
- public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish)
- {
- base.PostDeSpawn(map, mode);
- // This handles cases like uninstalling where the pod is removed from the map
- // without being "destroyed". We still need to eject the occupant.
- Log.Warning($"[WulaPodDebug] Pod despawned. Ejecting pawn.");
- EjectPawn();
- }
-
-
// ===================== IThingHolder Implementation =====================
public void GetChildHolders(List outChildren)
{
diff --git a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
index 82c48ef0..c21022f7 100644
--- a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
+++ b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
@@ -5,14 +5,27 @@ using Verse;
namespace WulaFallenEmpire
{
+ // Final, robust extension class for configuring path-based penetration.
+ public class Wula_PathPierce_Extension : DefModExtension
+ {
+ // Set to a positive number for limited hits, or -1 for infinite penetration.
+ public int maxHits = 3;
+ // The percentage of damage lost per hit. 0.25 means 25% damage loss per hit.
+ public float damageFalloff = 0.25f;
+ }
+
public class Projectile_WulaLineAttack : Projectile
{
+ private int hitCounter = 0;
private List alreadyDamaged = new List();
private Vector3 lastTickPosition;
+ private Wula_PathPierce_Extension Props => def.GetModExtension();
+
public override void ExposeData()
{
base.ExposeData();
+ Scribe_Values.Look(ref hitCounter, "hitCounter", 0);
Scribe_Collections.Look(ref alreadyDamaged, "alreadyDamaged", LookMode.Reference);
Scribe_Values.Look(ref lastTickPosition, "lastTickPosition");
if (alreadyDamaged == null)
@@ -26,70 +39,93 @@ namespace WulaFallenEmpire
base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
this.lastTickPosition = origin;
this.alreadyDamaged.Clear();
+ this.hitCounter = 0;
}
protected override void Tick()
{
Vector3 startPos = this.lastTickPosition;
-
- base.Tick(); // 这会更新弹丸的位置,并可能调用Impact()
+ base.Tick();
+
+ if (this.Destroyed) return;
- if (this.Destroyed)
- {
- return;
- }
-
Vector3 endPos = this.ExactPosition;
+
+ CheckPathForDamage(startPos, endPos);
- // 调用路径伤害检测
- DamageMissedPawns(startPos, endPos);
-
- // 为下一帧更新位置
this.lastTickPosition = endPos;
}
-
+
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
- // 在最终碰撞前,最后一次检查从上一帧到当前碰撞点的路径
- DamageMissedPawns(this.lastTickPosition, this.ExactPosition);
+ CheckPathForDamage(lastTickPosition, this.ExactPosition);
- // 如果最终目标还没被路径伤害击中,在这里造成一次伤害
- if (hitThing != null && !alreadyDamaged.Contains(hitThing))
+ if (hitThing != null && alreadyDamaged.Contains(hitThing))
{
- DamageInfo dinfo = new DamageInfo(this.def.projectile.damageDef, (float)this.DamageAmount, this.ArmorPenetration, this.ExactRotation.eulerAngles.y, this.launcher, null, this.equipmentDef, DamageInfo.SourceCategory.ThingOrUnknown, this.intendedTarget.Thing);
- hitThing.TakeDamage(dinfo);
+ base.Impact(null, blockedByShield);
+ }
+ else
+ {
+ base.Impact(hitThing, blockedByShield);
}
-
- // 调用基类方法来处理XML中定义的爆炸等最终效果
- base.Impact(hitThing, blockedByShield);
}
- private void DamageMissedPawns(Vector3 startPos, Vector3 endPos)
+ private void CheckPathForDamage(Vector3 startPos, Vector3 endPos)
{
if (startPos == endPos) return;
+ int maxHits = Props?.maxHits ?? 1;
+ bool infinitePenetration = maxHits < 0;
+
+ if (!infinitePenetration && hitCounter >= maxHits) return;
+
Map map = this.Map;
float distance = Vector3.Distance(startPos, endPos);
Vector3 direction = (endPos - startPos).normalized;
- for (float i = 0; i < distance; i += 0.5f)
+ for (float i = 0; i < distance; i += 0.8f)
{
- Vector3 checkPos = startPos + direction * i;
- IntVec3 checkCell = new IntVec3(checkPos);
+ if (!infinitePenetration && hitCounter >= maxHits) break;
+
+ Vector3 checkPos = startPos + direction * i;
+ var thingsInCell = new HashSet(map.thingGrid.ThingsListAt(checkPos.ToIntVec3()));
- if (!checkCell.InBounds(map)) continue;
-
- var thingsInCell = new HashSet(map.thingGrid.ThingsListAt(checkCell));
foreach (Thing thing in thingsInCell)
{
if (thing is Pawn pawn && pawn != this.launcher && !alreadyDamaged.Contains(pawn) && GenHostility.HostileTo(pawn, this.launcher.Faction))
{
- var dinfo = new DamageInfo(this.def.projectile.damageDef, (float)this.DamageAmount, this.ArmorPenetration, this.ExactRotation.eulerAngles.y, this.launcher, null, this.equipmentDef, DamageInfo.SourceCategory.ThingOrUnknown, this.intendedTarget.Thing);
- pawn.TakeDamage(dinfo);
- alreadyDamaged.Add(pawn);
+ ApplyPathDamage(pawn);
+ if (!infinitePenetration && hitCounter >= maxHits) break;
}
}
}
}
+
+ private void ApplyPathDamage(Pawn pawn)
+ {
+ Wula_PathPierce_Extension props = Props;
+ float falloff = props?.damageFalloff ?? 0.25f;
+
+ // Damage falloff now applies universally, even for infinite penetration.
+ float damageMultiplier = Mathf.Pow(1f - falloff, hitCounter);
+
+ int damageAmount = (int)(this.DamageAmount * damageMultiplier);
+ if (damageAmount <= 0) return;
+
+ var dinfo = new DamageInfo(
+ this.def.projectile.damageDef,
+ damageAmount,
+ this.ArmorPenetration * damageMultiplier,
+ this.ExactRotation.eulerAngles.y,
+ this.launcher,
+ null,
+ this.equipmentDef,
+ DamageInfo.SourceCategory.ThingOrUnknown,
+ this.intendedTarget.Thing);
+
+ pawn.TakeDamage(dinfo);
+ alreadyDamaged.Add(pawn);
+ hitCounter++;
+ }
}
}
\ No newline at end of file