diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index ee211921..db604075 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_Penetrating.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml
new file mode 100644
index 00000000..3df15718
--- /dev/null
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Penetrating.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+ WULA_RW_Penetrating_Rifle
+
+ 一把经过实验性改造的“蓝锥”步枪,能够发射一种特殊的钢针,利用过载的能量使其在击中第一个目标后仍能继续飞行,对路径上的多个敌人造成伤害。
+ Spacer
+
+ Wula/Weapon/WULA_RW_Fractal_RF
+ Graphic_Single
+
+ Interact_Rifle
+
+ LongShots
+ RangedHeavy
+
+
+
+ WULA_Cube_Productor_BIO
+ WULA_Cube_Productor_Energy
+
+ WULA_Synth_Weapon_Technology
+ UnfinishedWeapon
+
+
+ 1300
+ 3.5
+ 0.3
+ 0.8
+ 0.9
+ 0.8
+ 0.8
+
+
+ 120
+ 6
+
+
+
+ Verb_Shoot
+ true
+ Bullet_WULA_RW_Penetrating_Rifle
+ 2
+ 38
+ 1
+ ChargeLance_Fire
+ GunTail_Medium
+ 9
+
+
+
+ Wula_Weapon_Init
+
+ RewardStandardQualitySuper
+
+
+
+ Bullet_WULA_RW_Penetrating_Rifle
+
+ WulaFallenEmpire.Projectile_WulaLineAttack
+ Normal
+ True
+
+ Things/Projectile/ChargeLanceShot
+ Graphic_Single
+ TransparentPostLight
+ 1.4
+
+
+ Bullet
+ 25
+ 130
+ 0.5
+ 5
+
+
+
+
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/CompWulaRitualSpot.cs b/Source/WulaFallenEmpire/CompWulaRitualSpot.cs
index 61964e38..a24138fd 100644
--- a/Source/WulaFallenEmpire/CompWulaRitualSpot.cs
+++ b/Source/WulaFallenEmpire/CompWulaRitualSpot.cs
@@ -35,28 +35,31 @@ namespace WulaFallenEmpire
// Find all rituals that are of our custom base class type.
foreach (PsychicRitualDef_Wula ritualDef in DefDatabase.AllDefs)
{
- Command_Action command_Action = new Command_Action();
- command_Action.defaultLabel = ritualDef.LabelCap.Resolve();
- command_Action.defaultDesc = ritualDef.description;
- command_Action.icon = ritualDef.uiIcon;
- command_Action.action = delegate
+ if (ritualDef.Visible)
{
- // Mimic vanilla initialization
- TargetInfo target = new TargetInfo(this.parent);
- PsychicRitualRoleAssignments assignments = ritualDef.BuildRoleAssignments(target);
- PsychicRitualCandidatePool candidatePool = ritualDef.FindCandidatePool();
- ritualDef.InitializeCast(this.parent.Map);
- Find.WindowStack.Add(new Dialog_BeginPsychicRitual(ritualDef, candidatePool, assignments, this.parent.Map));
- };
+ Command_Action command_Action = new Command_Action();
+ command_Action.defaultLabel = ritualDef.LabelCap.Resolve();
+ command_Action.defaultDesc = ritualDef.description;
+ command_Action.icon = ritualDef.uiIcon;
+ command_Action.action = delegate
+ {
+ // Mimic vanilla initialization
+ TargetInfo target = new TargetInfo(this.parent);
+ PsychicRitualRoleAssignments assignments = ritualDef.BuildRoleAssignments(target);
+ PsychicRitualCandidatePool candidatePool = ritualDef.FindCandidatePool();
+ ritualDef.InitializeCast(this.parent.Map);
+ Find.WindowStack.Add(new Dialog_BeginPsychicRitual(ritualDef, candidatePool, assignments, this.parent.Map));
+ };
- // Corrected check for cooldown and other requirements
- AcceptanceReport acceptanceReport = Find.PsychicRitualManager.CanInvoke(ritualDef, this.parent.Map);
- if (!acceptanceReport.Accepted)
- {
- command_Action.Disable(acceptanceReport.Reason.CapitalizeFirst());
+ // Corrected check for cooldown and other requirements
+ AcceptanceReport acceptanceReport = Find.PsychicRitualManager.CanInvoke(ritualDef, this.parent.Map);
+ if (!acceptanceReport.Accepted)
+ {
+ command_Action.Disable(acceptanceReport.Reason.CapitalizeFirst());
+ }
+
+ yield return command_Action;
}
-
- yield return command_Action;
}
}
}
diff --git a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
index 89d634f9..82c48ef0 100644
--- a/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
+++ b/Source/WulaFallenEmpire/Projectile_WulaPenetrating.cs
@@ -8,63 +8,88 @@ namespace WulaFallenEmpire
public class Projectile_WulaLineAttack : Projectile
{
private List alreadyDamaged = new List();
+ private Vector3 lastTickPosition;
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref alreadyDamaged, "alreadyDamaged", LookMode.Reference);
+ Scribe_Values.Look(ref lastTickPosition, "lastTickPosition");
+ if (alreadyDamaged == null)
+ {
+ alreadyDamaged = new List();
+ }
+ }
+
+ public override void Launch(Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire = false, Thing equipment = null, ThingDef targetCoverDef = null)
+ {
+ base.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, preventFriendlyFire, equipment, targetCoverDef);
+ this.lastTickPosition = origin;
+ this.alreadyDamaged.Clear();
}
protected override void Tick()
{
- base.Tick();
+ Vector3 startPos = this.lastTickPosition;
+
+ base.Tick(); // 这会更新弹丸的位置,并可能调用Impact()
+
if (this.Destroyed)
{
return;
}
-
- Map map = this.Map;
- IntVec3 currentPosition = this.Position;
- // 使用HashSet进行更高效的查找
- var thingsInCell = new HashSet(map.thingGrid.ThingsListAt(currentPosition));
+ Vector3 endPos = this.ExactPosition;
- foreach (Thing thing in thingsInCell)
- {
- if (thing is Pawn pawn && pawn != this.launcher && !alreadyDamaged.Contains(thing) && GenHostility.HostileTo(thing, this.launcher.Faction))
- {
- 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);
-
- pawn.TakeDamage(dinfo);
- alreadyDamaged.Add(pawn);
- }
- }
+ // 调用路径伤害检测
+ DamageMissedPawns(startPos, endPos);
+
+ // 为下一帧更新位置
+ this.lastTickPosition = endPos;
}
protected override void Impact(Thing hitThing, bool blockedByShield = false)
{
- // 如果最终命中的目标还没有在飞行路径上被伤害过,
- // 就在这里将它标记为已伤害,以避免在基类Impact中再次造成伤害。
+ // 在最终碰撞前,最后一次检查从上一帧到当前碰撞点的路径
+ DamageMissedPawns(this.lastTickPosition, this.ExactPosition);
+
+ // 如果最终目标还没被路径伤害击中,在这里造成一次伤害
if (hitThing != null && !alreadyDamaged.Contains(hitThing))
{
- // 注意:这里我们不直接造成伤害,因为基类的Impact会处理。
- // 我们只是标记它,以防万一。
- // 但实际上,由于基类Impact会造成伤害,这条线可能不是必须的,
- // 除非我们想完全控制伤害的施加时机。为了安全起见,我们保留它。
+ 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);
}
- // 调用基类的Impact方法来处理最终的命中效果,
- // 比如爆炸、声音、或对最终目标的直接伤害。
+ // 调用基类方法来处理XML中定义的爆炸等最终效果
base.Impact(hitThing, blockedByShield);
}
+
+ private void DamageMissedPawns(Vector3 startPos, Vector3 endPos)
+ {
+ if (startPos == endPos) 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)
+ {
+ Vector3 checkPos = startPos + direction * i;
+ IntVec3 checkCell = new IntVec3(checkPos);
+
+ 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);
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file