diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll
index d2344cbf..1b2f27f5 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/AbilityDefs/WULA_Flyover_Ability.xml b/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
index 321734f0..55e2e1e5 100644
--- a/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
+++ b/1.6/1.6/Defs/AbilityDefs/WULA_Flyover_Ability.xml
@@ -787,21 +787,22 @@
-
+
+
+ 450
20
true
- 3
+ WULA_EnergyLance_Base
+ 4
-
+
- BombardmentFacility
- 需要拥有<color=#BD2F31><i>武器阵列</i></color>设施的战舰在地图上才能进行轨道炮击支援
-
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml b/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
index 80e169e6..f49d9f3d 100644
--- a/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
+++ b/1.6/1.6/Defs/HediffDefs/WULA_FM_Hediffs.xml
@@ -75,6 +75,8 @@
WULA_Firepower_Minigun_Strafe
WULA_Firepower_Cannon_Salvo
+ WULA_Firepower_Cannon_Surveillance_Beacon
+ WULA_Firepower_EnergyLance_Strafe
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml b/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
index 506d9c88..571ff0a0 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/WULA_Flyover_Item.xml
@@ -888,48 +888,117 @@
-
+
WULA_EnergyLance_Base
- power beam
- PowerBeam
-
-
- WULA_EnergyLance_Base
- energy lance
+ 乌拉帝国光矛
+ 移动的能量光束武器
WulaFallenEmpire.EnergyLance
+ Normal
+ RealtimeOnly
+ true
+ true
+
- Flame
- true
- 0.9
-
- 60
- 95
-
-
- 5
- 10
-
+ 0.001
+ 3
+ 0.8
+ 4
+ 15
+
+
+ WULA_RW_Base_AR
+
-
+
6
- (255, 200, 50, 242)
+ (147, 116, 201, 212)
OrbitalBeam
+
+
0.02
+
+
+ 30
+ 15
- (255, 220, 180)
- (220, 200, 160)
- (255, 240, 200)
- 1.2
+ (147, 116, 201)
+ (147, 116, 185)
+ (147, 116, 150)
+ 1.5
+
+
+ WULA_EnergyLance_Effecter
+
+
+ WULA_EnergyLance_Effecter
+ 300
+
+
+ SubEffecter_Sustainer
+ VoidStructure_Emerging
+
+
+ SubEffecter_SprayerChance
+ EnergyLance_Fleck
+ 1
+ 999
+ 40
+ 1~1
+ 15
+ OnSource
+
+
+ SubEffecter_SprayerChance
+ EnergyLance_Fleck
+ 1
+ 999
+ 40
+ 1~1
+ 5
+ OnSource
+
+
+ SubEffecter_SprayerChance
+ EnergyLance_Fleck
+ 1
+ 999
+ 40
+ 1~1
+ 2
+ OnSource
+
+
+
+
+ EnergyLance_Fleck
+ MoteOverhead
+ 1
+ 0
+ 1
+ 5
+
+ Graphic_FleckPulse
+ Things/Mote/PowerBeam
+ MoteGlow
+ (147, 116, 201, 255)
+
+ <_NoiseTex>/Things/Mote/PsycastNoise
+ <_NoiseIntensity>100
+ <_Color2>(1, 1, 1, 0.85)
+
+ 10.0
+
+
\ No newline at end of file
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/AbilityWeaponDefExtension.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/AbilityWeaponDefExtension.cs
new file mode 100644
index 00000000..42d715a2
--- /dev/null
+++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/AbilityWeaponDefExtension.cs
@@ -0,0 +1,10 @@
+using RimWorld;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class AbilityWeaponDefExtension : DefModExtension
+ {
+ public ThingDef weaponDef; // 与此Ability相关的武器定义
+ }
+}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompAbilityEffect_EnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompAbilityEffect_EnergyLance.cs
index 2da71393..9398bad1 100644
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompAbilityEffect_EnergyLance.cs
+++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompAbilityEffect_EnergyLance.cs
@@ -6,124 +6,117 @@ namespace WulaFallenEmpire
{
public class CompAbilityEffect_EnergyLance : CompAbilityEffect_WithDest
{
- public new CompProperties_EnergyLance Props => (CompProperties_EnergyLance)props;
+ public new CompProperties_AbilityEnergyLance Props => (CompProperties_AbilityEnergyLance)props;
+
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
-
- // 计算光束的起点和方向
- IntVec3 startPos = target.Cell;
- IntVec3 endPos = dest.Cell;
-
- // 如果使用固定距离,则从起点向终点方向移动固定距离
- if (Props.useFixedDistance)
- {
- Vector3 direction = (endPos.ToVector3() - startPos.ToVector3()).normalized;
- Vector3 offset = direction * Props.moveDistance;
- endPos = startPos + new IntVec3(Mathf.RoundToInt(offset.x), 0, Mathf.RoundToInt(offset.z));
- }
-
- // 创建移动的能量光束
- EnergyLance obj = (EnergyLance)GenSpawn.Spawn(ThingDef.Named("EnergyLance"), startPos, parent.pawn.Map);
- obj.duration = Props.durationTicks;
- obj.instigator = parent.pawn;
- obj.startPos = startPos;
- obj.endPos = endPos;
- obj.moveDistance = Props.moveDistance;
- obj.useFixedDistance = Props.useFixedDistance;
- obj.firesPerTick = Props.firesPerTick;
- // 不再需要传递伤害范围,因为现在从ModExtension读取
- obj.StartStrike();
-
- Log.Message($"[EnergyLance] Created energy lance from {startPos} to {endPos}, distance: {Props.moveDistance}");
- }
-
- // 绘制预览效果
- public override void DrawEffectPreview(LocalTargetInfo target)
- {
- base.DrawEffectPreview(target);
- if (parent.pawn == null || parent.pawn.Map == null || !target.IsValid)
+ if (parent.pawn == null || parent.pawn.Map == null)
return;
try
{
- // 绘制起点预览
- GenDraw.DrawTargetHighlight(target.Cell);
+ // 使用配置的光束类型
+ ThingDef lanceDef = Props.energyLanceDef ?? ThingDef.Named("EnergyLance");
- // 如果选择了终点,绘制移动路径预览
- if (selectedTarget.IsValid)
- {
- DrawMovePathPreview(target.Cell, selectedTarget.Cell);
- }
+ // 创建EnergyLance
+ EnergyLance.MakeEnergyLance(
+ lanceDef,
+ target.Cell,
+ dest.Cell,
+ parent.pawn.Map,
+ Props.moveDistance,
+ Props.useFixedDistance,
+ Props.durationTicks,
+ parent.pawn
+ );
+
+ Log.Message($"[EnergyLance] Started {lanceDef.defName} from {target.Cell} to {dest.Cell}");
}
- catch (System.Exception)
+ catch (System.Exception ex)
{
- // 忽略预览绘制错误
+ Log.Error($"[EnergyLance] Error starting EnergyLance: {ex}");
}
}
- private void DrawMovePathPreview(IntVec3 startPos, IntVec3 endPos)
+ // 绘制预览保持不变
+ public new void DrawHighlight(LocalTargetInfo target)
+ {
+ if (selectedTarget.IsValid)
+ {
+ DrawBeamPathPreview(selectedTarget.Cell, target.Cell);
+ }
+ else
+ {
+ GenDraw.DrawTargetHighlight(target);
+ }
+ }
+
+ private void DrawBeamPathPreview(IntVec3 startCell, IntVec3 endCell)
{
Map map = parent.pawn.Map;
- // 计算实际终点
- IntVec3 actualEndPos = endPos;
+ Vector3 startPos = startCell.ToVector3();
+ Vector3 direction = (endCell.ToVector3() - startPos).normalized;
+ Vector3 actualEndPos;
+
if (Props.useFixedDistance)
{
- Vector3 direction = (endPos.ToVector3() - startPos.ToVector3()).normalized;
- Vector3 offset = direction * Props.moveDistance;
- actualEndPos = startPos + new IntVec3(Mathf.RoundToInt(offset.x), 0, Mathf.RoundToInt(offset.z));
+ actualEndPos = startPos + direction * Props.moveDistance;
+ }
+ else
+ {
+ actualEndPos = endCell.ToVector3();
}
- // 绘制移动路径
- Vector3 startVec = startPos.ToVector3Shifted();
- Vector3 endVec = actualEndPos.ToVector3Shifted();
+ IntVec3 actualEndCell = new IntVec3(
+ Mathf.RoundToInt(actualEndPos.x),
+ Mathf.RoundToInt(actualEndPos.y),
+ Mathf.RoundToInt(actualEndPos.z)
+ );
- GenDraw.DrawLineBetween(startVec, endVec, SimpleColor.Yellow, 0.2f);
-
- // 绘制终点预览
- GenDraw.DrawTargetHighlight(actualEndPos);
-
- // 绘制作用范围预览(在移动路径上)
- DrawEffectRangePreview(startPos, actualEndPos);
+ DrawBeamLine(startCell, actualEndCell);
+ GenDraw.DrawTargetHighlight(startCell);
+ GenDraw.DrawTargetHighlight(actualEndCell);
+ DrawEffectRadiusPreview(startCell);
+ DrawEffectRadiusPreview(actualEndCell);
}
- private void DrawEffectRangePreview(IntVec3 startPos, IntVec3 endPos)
+ private void DrawBeamLine(IntVec3 startCell, IntVec3 endCell)
+ {
+ Vector3 startPos = startCell.ToVector3Shifted();
+ Vector3 endPos = endCell.ToVector3Shifted();
+
+ GenDraw.DrawLineBetween(startPos, endPos, SimpleColor.Yellow, 0.3f);
+ }
+
+ private void DrawEffectRadiusPreview(IntVec3 center)
{
Map map = parent.pawn.Map;
-
- // 沿着移动路径绘制作用范围
- Vector3 currentPos = startPos.ToVector3();
- Vector3 direction = (endPos.ToVector3() - startPos.ToVector3()).normalized;
- float totalDistance = Vector3.Distance(startPos.ToVector3(), endPos.ToVector3());
- float step = 1f; // 每格绘制
-
- for (float distance = 0; distance <= totalDistance; distance += step)
- {
- Vector3 checkPos = startPos.ToVector3() + direction * distance;
- IntVec3 checkCell = new IntVec3(Mathf.RoundToInt(checkPos.x), 0, Mathf.RoundToInt(checkPos.z));
-
- if (checkCell.InBounds(map))
- {
- // 绘制作用范围指示
- GenDraw.DrawRadiusRing(checkCell, 1.5f, Color.red, (c) => true);
- }
- }
+ GenDraw.DrawRadiusRing(center, 15f, Color.yellow);
}
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
{
- string baseInfo = $"能量长矛: 持续{Props.durationTicks}刻";
-
- if (Props.useFixedDistance)
+ if (selectedTarget.IsValid)
{
- baseInfo += $"\n移动距离: {Props.moveDistance}格";
+ string beamType = Props.energyLanceDef?.label ?? "EnergyLance";
+ return $"选择{beamType}方向\n移动距离: {Props.moveDistance}格\n模式: {(Props.useFixedDistance ? "固定距离" : "移动到终点")}";
+ }
+ else
+ {
+ return "选择光束起点";
}
-
- baseInfo += $"\n选择起点后,再选择移动方向";
-
- return baseInfo;
}
+
+ public override TargetingParameters targetParams => new TargetingParameters
+ {
+ canTargetLocations = true,
+ canTargetPawns = false,
+ canTargetBuildings = false,
+ canTargetItems = false,
+ mapObjectTargetsMustBeAutoAttackable = false
+ };
}
}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_AbilityEnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_AbilityEnergyLance.cs
new file mode 100644
index 00000000..69eade0a
--- /dev/null
+++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_AbilityEnergyLance.cs
@@ -0,0 +1,25 @@
+using RimWorld;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class CompProperties_AbilityEnergyLance : CompProperties_EffectWithDest
+ {
+ // 光束持续时间
+ public int durationTicks = 600;
+
+ // 移动配置
+ public float moveDistance = 15f;
+ public bool useFixedDistance = true;
+
+ // 光束类型配置 - 新增:暴露光束类型
+ public ThingDef energyLanceDef; // 使用的EnergyLance ThingDef
+ public int firesPerTick = 4; // 每刻造成的火灾数量
+
+ public CompProperties_AbilityEnergyLance()
+ {
+ this.compClass = typeof(CompAbilityEffect_EnergyLance);
+ this.destination = AbilityEffectDestination.Selected;
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_EnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_EnergyLance.cs
deleted file mode 100644
index 5f18a848..00000000
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/CompProperties_EnergyLance.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using RimWorld;
-using Verse;
-
-namespace WulaFallenEmpire
-{
- public class CompProperties_EnergyLance : CompProperties_EffectWithDest
- {
- public int durationTicks = 600; // 光束持续时间
- public float moveDistance = 15f; // 光束移动距离
- public bool useFixedDistance = true; // 是否使用固定距离
-
- // 伤害配置
- public int firesPerTick = 4; // 每刻产生的火焰数量
- public IntRange flameDamageRange = new IntRange(65, 100); // 火焰伤害范围
- public IntRange corpseFlameDamageRange = new IntRange(5, 10); // 尸体火焰伤害范围
-
- public CompProperties_EnergyLance()
- {
- this.compClass = typeof(CompAbilityEffect_EnergyLance);
- }
- }
-}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLance.cs
index a9530d92..584f3001 100644
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLance.cs
+++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLance.cs
@@ -3,82 +3,141 @@ using Verse;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
+using Verse.Sound;
namespace WulaFallenEmpire
{
- public class EnergyLance : OrbitalStrike
+ [StaticConstructorOnStartup]
+ public class EnergyLance : ThingWithComps
{
// 移动相关属性
- public IntVec3 startPos;
- public IntVec3 endPos;
+ public IntVec3 startPosition;
+ public IntVec3 endPosition;
public float moveDistance;
public bool useFixedDistance;
+ public float flightSpeed = 1f;
+ public float currentProgress = 0f;
+ public float altitude = 20f;
// 伤害配置
public int firesPerTick = 4;
-
- // ModExtension引用
- private EnergyLanceExtension extension;
+ public float effectRadius = 15f;
+ public int durationTicks = 600;
+ private int ticksPassed = 0;
// 移动状态
- private Vector3 currentPos;
+ private Vector3 exactPosition;
private Vector3 moveDirection;
- private float moveSpeed;
- private float traveledDistance;
- private const float effectRadius = 3f; // 作用半径
+ private bool hasStarted = false;
+ private bool hasCompleted = false;
- private static List tmpThings = new List();
+ // 视觉效果
+ private CompOrbitalBeam orbitalBeamComp;
+ private Sustainer sustainer;
- public override void StartStrike()
+ // 伤害相关
+ private static List tmpThings = new List();
+ private static readonly IntRange FlameDamageAmountRange = new IntRange(65, 100);
+ private static readonly IntRange CorpseFlameDamageAmountRange = new IntRange(5, 10);
+ public Thing instigator;
+ public ThingDef weaponDef;
+
+ // 精确位置计算(基于FlyOver的逻辑)
+ public override Vector3 DrawPos
{
- base.StartStrike();
-
- // 获取ModExtension
- extension = def.GetModExtension();
- if (extension == null)
+ get
{
- Log.Error($"[EnergyLance] No EnergyLanceExtension found on {def.defName}");
- return;
+ Vector3 start = startPosition.ToVector3();
+ Vector3 end = CalculateEndPosition();
+ Vector3 basePos = Vector3.Lerp(start, end, currentProgress);
+ basePos.y = altitude;
+ return basePos;
}
-
- // 初始化移动参数
- currentPos = startPos.ToVector3();
-
- if (useFixedDistance)
- {
- // 从起点向终点方向移动固定距离
- Vector3 direction = (endPos.ToVector3() - startPos.ToVector3()).normalized;
- moveDirection = direction;
- moveSpeed = moveDistance / duration; // 根据持续时间计算移动速度
- }
- else
- {
- // 直接从起点移动到终点
- Vector3 direction = (endPos.ToVector3() - startPos.ToVector3());
- moveDirection = direction.normalized;
- moveSpeed = direction.magnitude / duration;
- }
-
- traveledDistance = 0f;
-
- // 创建视觉效果
- CreateVisualEffect();
-
- Log.Message($"[EnergyLance] Strike started from {startPos} to {endPos}, " +
- $"damage: {extension.damageDef.defName}, speed: {moveSpeed}");
}
- private void CreateVisualEffect()
+ // 计算实际终点位置
+ private Vector3 CalculateEndPosition()
{
- // 使用ModExtension中定义的Mote,如果没有则使用默认的PowerBeam
- if (extension.moteDef != null)
+ if (useFixedDistance)
{
- Mote mote = MoteMaker.MakeStaticMote(base.Position, base.Map, extension.moteDef);
+ Vector3 direction = (endPosition.ToVector3() - startPosition.ToVector3()).normalized;
+ return startPosition.ToVector3() + direction * moveDistance;
}
else
{
- // 使用原版PowerBeam的视觉效果
- MoteMaker.MakePowerBeamMote(base.Position, base.Map);
+ return endPosition.ToVector3();
+ }
+ }
+
+ // 精确旋转
+ public virtual Quaternion ExactRotation
+ {
+ get
+ {
+ Vector3 direction = (CalculateEndPosition() - startPosition.ToVector3()).normalized;
+ return Quaternion.LookRotation(direction.Yto0());
+ }
+ }
+
+ public override void SpawnSetup(Map map, bool respawningAfterLoad)
+ {
+ base.SpawnSetup(map, respawningAfterLoad);
+
+ orbitalBeamComp = GetComp();
+
+ if (!respawningAfterLoad)
+ {
+ base.Position = startPosition;
+ hasStarted = true;
+
+ // 计算移动方向
+ Vector3 endPos = CalculateEndPosition();
+ moveDirection = (endPos - startPosition.ToVector3()).normalized;
+
+ // 初始化光束组件
+ if (orbitalBeamComp != null)
+ {
+ // 使用反射调用StartAnimation方法
+ StartOrbitalBeamAnimation();
+ }
+
+ // 开始音效
+ StartSound();
+
+ Log.Message($"[EnergyLance] Spawned at {startPosition}, moving to {endPosition}, " +
+ $"distance: {moveDistance}, fixed: {useFixedDistance}");
+ }
+ }
+
+ // 使用反射调用StartAnimation方法
+ private void StartOrbitalBeamAnimation()
+ {
+ var startAnimationMethod = orbitalBeamComp.GetType().GetMethod("StartAnimation");
+ if (startAnimationMethod != null)
+ {
+ startAnimationMethod.Invoke(orbitalBeamComp, new object[] { durationTicks, 10, 0f });
+ Log.Message("[EnergyLance] Orbital beam animation started");
+ }
+ else
+ {
+ Log.Warning("[EnergyLance] Could not find StartAnimation method on CompOrbitalBeam");
+ }
+ }
+
+ private void StartSound()
+ {
+ var soundProp = orbitalBeamComp?.GetType().GetProperty("Props")?.GetValue(orbitalBeamComp);
+ if (soundProp != null)
+ {
+ var soundField = soundProp.GetType().GetField("sound");
+ if (soundField != null)
+ {
+ SoundDef soundDef = soundField.GetValue(soundProp) as SoundDef;
+ if (soundDef != null)
+ {
+ sustainer = soundDef.TrySpawnSustainer(SoundInfo.InMap(this, MaintenanceType.PerTick));
+ }
+ }
}
}
@@ -86,110 +145,142 @@ namespace WulaFallenEmpire
{
base.Tick();
- if (!base.Destroyed && extension != null)
+ if (!hasStarted || hasCompleted)
+ return;
+
+ ticksPassed++;
+
+ // 更新移动进度
+ UpdateMovement();
+
+ // 造成伤害
+ for (int i = 0; i < firesPerTick; i++)
{
- // 移动光束
- MoveBeam();
-
- // 造成伤害
- for (int i = 0; i < firesPerTick; i++)
- {
- DoBeamDamage();
- }
+ StartRandomFireAndDoFlameDamage();
+ }
+
+ // 更新音效
+ sustainer?.Maintain();
+
+ // 检查是否完成
+ if (ticksPassed >= durationTicks || currentProgress >= 1f)
+ {
+ CompleteEnergyLance();
}
}
- private void MoveBeam()
+ private void UpdateMovement()
{
- // 计算移动距离
- float moveThisTick = moveSpeed;
+ // 计算总距离
+ float totalDistance = useFixedDistance ? moveDistance : Vector3.Distance(startPosition.ToVector3(), endPosition.ToVector3());
- // 更新位置
- currentPos += moveDirection * moveThisTick;
- traveledDistance += moveThisTick;
+ // 计算移动速度(基于持续时间和总距离)
+ float progressPerTick = 1f / durationTicks;
+ currentProgress += progressPerTick;
+ currentProgress = Mathf.Clamp01(currentProgress);
+
+ // 更新精确位置
+ exactPosition = Vector3.Lerp(startPosition.ToVector3(), CalculateEndPosition(), currentProgress);
+
+ // 更新格子位置
+ IntVec3 newCell = new IntVec3(
+ Mathf.RoundToInt(exactPosition.x),
+ Mathf.RoundToInt(exactPosition.y),
+ Mathf.RoundToInt(exactPosition.z)
+ );
- // 更新光束的实际位置
- IntVec3 newCell = new IntVec3(Mathf.RoundToInt(currentPos.x), 0, Mathf.RoundToInt(currentPos.z));
if (newCell != base.Position && newCell.InBounds(base.Map))
{
base.Position = newCell;
}
-
- // 检查是否到达终点
- if (useFixedDistance && traveledDistance >= moveDistance)
- {
- // 固定距离模式:移动指定距离后结束
- Destroy();
- Log.Message($"[EnergyLance] Reached fixed distance, destroying");
- }
- else if (!useFixedDistance && traveledDistance >= Vector3.Distance(startPos.ToVector3(), endPos.ToVector3()))
- {
- // 终点模式:到达终点后结束
- Destroy();
- Log.Message($"[EnergyLance] Reached end position, destroying");
- }
}
- private void DoBeamDamage()
+ private void StartRandomFireAndDoFlameDamage()
{
- if (extension == null) return;
-
- // 在当前光束位置周围随机选择一个单元格
IntVec3 targetCell = (from x in GenRadial.RadialCellsAround(base.Position, effectRadius, useCenter: true)
where x.InBounds(base.Map)
select x).RandomElementByWeight((IntVec3 x) => 1f - Mathf.Min(x.DistanceTo(base.Position) / effectRadius, 1f) + 0.05f);
- // 尝试在该单元格点火(如果配置了点火)
- if (extension.igniteFires)
- {
- FireUtility.TryStartFireIn(targetCell, base.Map, Rand.Range(0.1f, extension.fireIgniteChance), instigator);
- }
+ FireUtility.TryStartFireIn(targetCell, base.Map, Rand.Range(0.1f, 0.925f), instigator);
- // 对该单元格内的物体造成伤害
tmpThings.Clear();
tmpThings.AddRange(targetCell.GetThingList(base.Map));
for (int i = 0; i < tmpThings.Count; i++)
{
- Thing thing = tmpThings[i];
-
- // 检查是否对尸体造成伤害
- if (!extension.applyDamageToCorpses && thing is Corpse)
- continue;
-
- // 计算伤害量
- int damageAmount = (thing is Corpse) ?
- extension.corpseDamageAmountRange.RandomInRange :
- extension.damageAmountRange.RandomInRange;
-
- Pawn pawn = thing as Pawn;
- BattleLogEntry_DamageTaken battleLogEntry = null;
+ int num = ((tmpThings[i] is Corpse) ? CorpseFlameDamageAmountRange.RandomInRange : FlameDamageAmountRange.RandomInRange);
+ Pawn pawn = tmpThings[i] as Pawn;
+ BattleLogEntry_DamageTaken battleLogEntry_DamageTaken = null;
if (pawn != null)
{
- battleLogEntry = new BattleLogEntry_DamageTaken(pawn, RulePackDefOf.DamageEvent_PowerBeam, instigator as Pawn);
- Find.BattleLog.Add(battleLogEntry);
+ battleLogEntry_DamageTaken = new BattleLogEntry_DamageTaken(pawn, RulePackDefOf.DamageEvent_PowerBeam, instigator as Pawn);
+ Find.BattleLog.Add(battleLogEntry_DamageTaken);
}
- // 使用ModExtension中定义的伤害类型
- DamageInfo damageInfo = new DamageInfo(extension.damageDef, damageAmount, 0f, -1f, instigator, null, weaponDef);
- thing.TakeDamage(damageInfo).AssociateWithLog(battleLogEntry);
-
- Log.Message($"[EnergyLance] Applied {extension.damageDef.defName} damage {damageAmount} to {thing.Label}");
+ DamageInfo damageInfo = new DamageInfo(DamageDefOf.Flame, num, 0f, -1f, instigator, null, weaponDef);
+ tmpThings[i].TakeDamage(damageInfo).AssociateWithLog(battleLogEntry_DamageTaken);
}
tmpThings.Clear();
}
+ private void CompleteEnergyLance()
+ {
+ hasCompleted = true;
+
+ // 停止音效
+ sustainer?.End();
+ sustainer = null;
+
+ Log.Message($"[EnergyLance] Completed at position {base.Position}");
+
+ // 销毁自身
+ Destroy();
+ }
+
+ // 重写绘制方法,确保光束正确显示
+ protected override void DrawAt(Vector3 drawLoc, bool flip = false)
+ {
+ // 让CompOrbitalBeam处理绘制
+ Comps_PostDraw();
+ }
+
public override void ExposeData()
{
base.ExposeData();
- Scribe_Values.Look(ref startPos, "startPos");
- Scribe_Values.Look(ref endPos, "endPos");
+ Scribe_Values.Look(ref startPosition, "startPosition");
+ Scribe_Values.Look(ref endPosition, "endPosition");
Scribe_Values.Look(ref moveDistance, "moveDistance");
Scribe_Values.Look(ref useFixedDistance, "useFixedDistance");
+ Scribe_Values.Look(ref flightSpeed, "flightSpeed", 1f);
+ Scribe_Values.Look(ref currentProgress, "currentProgress", 0f);
+ Scribe_Values.Look(ref altitude, "altitude", 20f);
Scribe_Values.Look(ref firesPerTick, "firesPerTick", 4);
+ Scribe_Values.Look(ref effectRadius, "effectRadius", 15f);
+ Scribe_Values.Look(ref durationTicks, "durationTicks", 600);
+ Scribe_Values.Look(ref ticksPassed, "ticksPassed", 0);
+ Scribe_Values.Look(ref hasStarted, "hasStarted", false);
+ Scribe_Values.Look(ref hasCompleted, "hasCompleted", false);
+ }
+
+ // 创建EnergyLance的静态方法
+ public static EnergyLance MakeEnergyLance(ThingDef energyLanceDef, IntVec3 start, IntVec3 end, Map map,
+ float distance = 15f, bool fixedDistance = true, int duration = 600, Pawn instigatorPawn = null)
+ {
+ EnergyLance energyLance = (EnergyLance)ThingMaker.MakeThing(energyLanceDef);
+ energyLance.startPosition = start;
+ energyLance.endPosition = end;
+ energyLance.moveDistance = distance;
+ energyLance.useFixedDistance = fixedDistance;
+ energyLance.durationTicks = duration;
+ energyLance.instigator = instigatorPawn;
+
+ GenSpawn.Spawn(energyLance, start, map);
+
+ Log.Message($"[EnergyLance] Created {energyLanceDef.defName} from {start} to {end}");
+ return energyLance;
}
}
}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLanceExtension.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLanceExtension.cs
index 59b98a30..a4ea5904 100644
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLanceExtension.cs
+++ b/Source/WulaFallenEmpire/Ability/WULA_AbilityEnergyLance/EnergyLanceExtension.cs
@@ -5,18 +5,13 @@ namespace WulaFallenEmpire
{
public class EnergyLanceExtension : DefModExtension
{
- // 伤害类型配置
- public DamageDef damageDef = DamageDefOf.Flame; // 伤害类型,默认为火焰伤害
- public bool applyDamageToCorpses = true; // 是否对尸体造成伤害
- public bool igniteFires = true; // 是否点燃火焰
- public float fireIgniteChance = 0.8f; // 点燃火焰的概率
+ // 移动平滑配置
+ public float moveSmoothing = 0.1f; // 移动平滑度 (0-1),值越小越平滑
+ public int moteSpawnInterval = 3; // Mote生成间隔,值越大密度越低
+ public float moteScale = 0.8f; // Mote缩放比例
- // 伤害量配置
- public IntRange damageAmountRange = new IntRange(65, 100); // 对生物的伤害范围
- public IntRange corpseDamageAmountRange = new IntRange(5, 10); // 对尸体的伤害范围
-
- // 视觉效果配置
- public ThingDef moteDef; // 使用的Mote类型
- public SoundDef impactSound; // 撞击音效
+ // 伤害配置
+ public int firesPerTick = 4;
+ public float effectRadius = 15f;
}
}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompBuildingEnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompBuildingEnergyLance.cs
deleted file mode 100644
index 4bd58ae4..00000000
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompBuildingEnergyLance.cs
+++ /dev/null
@@ -1,361 +0,0 @@
-using RimWorld;
-using Verse;
-using UnityEngine;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace WulaFallenEmpire
-{
- public class CompBuildingEnergyLance : ThingComp
- {
- public CompProperties_BuildingEnergyLance Props => (CompProperties_BuildingEnergyLance)props;
-
- // 状态管理
- private EnergyLanceState currentState = EnergyLanceState.Idle;
- private int nextUpdateTick = 0;
- private int noTargetTicks = 0;
-
- // 目标管理
- private Pawn currentTarget = null;
- private IntVec3 lastTargetPosition = IntVec3.Invalid;
-
- // EnergyLance实例
- private GuidedEnergyLance activeLance = null;
-
- public override void PostSpawnSetup(bool respawningAfterLoad)
- {
- base.PostSpawnSetup(respawningAfterLoad);
-
- if (!respawningAfterLoad)
- {
- // 新生成时立即开始搜索目标
- nextUpdateTick = Find.TickManager.TicksGame;
- currentState = EnergyLanceState.Searching;
-
- Log.Message($"[BuildingEnergyLance] Building spawned, starting target search");
- }
- }
-
- private void UpdateState()
- {
- switch (currentState)
- {
- case EnergyLanceState.Idle:
- // 空闲状态,等待下一次更新
- break;
-
- case EnergyLanceState.Searching:
- SearchForTarget();
- break;
-
- case EnergyLanceState.Tracking:
- TrackTarget();
- break;
-
- case EnergyLanceState.NoTarget:
- HandleNoTarget();
- break;
- }
- }
-
- private void SearchForTarget()
- {
- Map map = parent.Map;
- if (map == null) return;
-
- // 获取范围内的所有有效目标
- var potentialTargets = new List();
-
- foreach (var pawn in map.mapPawns.AllPawnsSpawned)
- {
- if (IsValidTarget(pawn) && IsInRange(pawn.Position))
- {
- potentialTargets.Add(pawn);
- }
- }
-
- if (potentialTargets.Count > 0)
- {
- // 选择第一个目标(可以改为其他选择逻辑)
- currentTarget = potentialTargets[0];
- lastTargetPosition = currentTarget.Position;
-
- // 创建EnergyLance
- CreateEnergyLance();
-
- currentState = EnergyLanceState.Tracking;
- noTargetTicks = 0;
-
- Log.Message($"[BuildingEnergyLance] Locked target: {currentTarget.Label}, position: {currentTarget.Position}");
- }
- else
- {
- // 没有找到目标
- currentState = EnergyLanceState.NoTarget;
- Log.Message($"[BuildingEnergyLance] No targets found in range");
- }
- }
-
- private void TrackTarget()
- {
- if (currentTarget == null || !currentTarget.Spawned)
- {
- // 目标丢失,重新搜索
- currentState = EnergyLanceState.Searching;
- currentTarget = null;
- return;
- }
-
- // 检查目标是否仍然有效
- if (!IsValidTarget(currentTarget) || !IsInRange(currentTarget.Position))
- {
- // 目标无效或超出范围,寻找最近的敌人
- FindNearestTarget();
- return;
- }
-
- // 更新目标位置
- lastTargetPosition = currentTarget.Position;
-
- // 向EnergyLance发送目标位置
- if (activeLance != null && !activeLance.Destroyed)
- {
- activeLance.UpdateTarget(lastTargetPosition);
- noTargetTicks = 0;
-
- Log.Message($"[BuildingEnergyLance] Updated target position: {lastTargetPosition}");
- }
- else
- {
- // EnergyLance丢失,重新创建
- CreateEnergyLance();
- }
- }
-
- private void FindNearestTarget()
- {
- Map map = parent.Map;
- if (map == null) return;
-
- Pawn nearestTarget = null;
- float nearestDistance = float.MaxValue;
-
- // 获取当前EnergyLance位置
- IntVec3 searchCenter = (activeLance != null && !activeLance.Destroyed) ?
- activeLance.Position : parent.Position;
-
- foreach (var pawn in map.mapPawns.AllPawnsSpawned)
- {
- if (IsValidTarget(pawn) && IsInRange(pawn.Position))
- {
- float distance = Vector3.Distance(searchCenter.ToVector3(), pawn.Position.ToVector3());
- if (distance < nearestDistance)
- {
- nearestDistance = distance;
- nearestTarget = pawn;
- }
- }
- }
-
- if (nearestTarget != null)
- {
- currentTarget = nearestTarget;
- lastTargetPosition = currentTarget.Position;
-
- // 更新EnergyLance目标
- if (activeLance != null && !activeLance.Destroyed)
- {
- activeLance.UpdateTarget(lastTargetPosition);
- }
-
- Log.Message($"[BuildingEnergyLance] Switched to nearest target: {currentTarget.Label}, distance: {nearestDistance}");
- }
- else
- {
- // 没有找到替代目标
- currentState = EnergyLanceState.NoTarget;
- currentTarget = null;
- Log.Message($"[BuildingEnergyLance] No alternative targets found");
- }
- }
-
- private void HandleNoTarget()
- {
- noTargetTicks++;
-
- // 向EnergyLance发送空位置
- if (activeLance != null && !activeLance.Destroyed)
- {
- activeLance.UpdateTarget(IntVec3.Invalid);
- }
-
- // 检查是否应该销毁EnergyLance
- if (noTargetTicks >= Props.maxNoTargetTicks)
- {
- if (activeLance != null && !activeLance.Destroyed)
- {
- activeLance.Destroy();
- activeLance = null;
- }
-
- // 回到搜索状态
- currentState = EnergyLanceState.Searching;
- noTargetTicks = 0;
-
- Log.Message($"[BuildingEnergyLance] EnergyLance destroyed due to no targets");
- }
- else if (noTargetTicks % 60 == 0) // 每60刻检查一次是否有新目标
- {
- SearchForTarget();
- }
- }
-
- private void CreateEnergyLance()
- {
- if (Props.energyLanceDef == null)
- {
- Log.Error($"[BuildingEnergyLance] No energyLanceDef configured");
- return;
- }
-
- try
- {
- // 销毁现有的EnergyLance
- if (activeLance != null && !activeLance.Destroyed)
- {
- activeLance.Destroy();
- }
-
- // 创建新的EnergyLance
- IntVec3 spawnPos = GetLanceSpawnPosition();
- activeLance = (GuidedEnergyLance)GenSpawn.Spawn(Props.energyLanceDef, spawnPos, parent.Map);
-
- // 初始化EnergyLance
- activeLance.duration = Props.energyLanceDuration;
- activeLance.instigator = parent;
- activeLance.controlBuilding = this.parent;
- activeLance.firesPerTick = Props.firesPerTick;
-
- // 如果有当前目标,设置初始位置
- if (currentTarget != null)
- {
- activeLance.UpdateTarget(currentTarget.Position);
- }
-
- activeLance.StartStrike();
-
- Log.Message($"[BuildingEnergyLance] Created EnergyLance at {spawnPos}");
- }
- catch (System.Exception ex)
- {
- Log.Error($"[BuildingEnergyLance] Error creating EnergyLance: {ex}");
- }
- }
-
- private IntVec3 GetLanceSpawnPosition()
- {
- // 在建筑周围寻找一个合适的生成位置
- Map map = parent.Map;
- IntVec3 center = parent.Position;
-
- // 优先选择建筑上方的位置
- if (center.InBounds(map) && center.Walkable(map))
- {
- return center;
- }
-
- // 如果建筑位置不可用,在周围寻找
- foreach (IntVec3 cell in GenRadial.RadialCellsAround(center, 2f, true))
- {
- if (cell.InBounds(map) && cell.Walkable(map))
- {
- return cell;
- }
- }
-
- // 如果都不可用,返回建筑位置
- return center;
- }
-
- private bool IsValidTarget(Pawn pawn)
- {
- if (pawn == null || pawn.Downed || pawn.Dead || !pawn.Spawned)
- return false;
-
- // 检查目标类型
- if (Props.targetEnemies && pawn.HostileTo(parent.Faction))
- return true;
-
- if (Props.targetNeutrals && !pawn.HostileTo(parent.Faction) && pawn.Faction != parent.Faction)
- return true;
-
- if (Props.targetAnimals && pawn.RaceProps.Animal)
- return true;
-
- return false;
- }
-
- private bool IsInRange(IntVec3 position)
- {
- float distance = Vector3.Distance(parent.Position.ToVector3(), position.ToVector3());
- return distance <= Props.radius;
- }
-
- public override void CompTick()
- {
- base.CompTick();
-
- int currentTick = Find.TickManager.TicksGame;
-
- // 检查是否需要更新状态
- if (currentTick >= nextUpdateTick)
- {
- UpdateState();
- nextUpdateTick = currentTick + Props.updateIntervalTicks;
- }
-
- // 检查EnergyLance状态
- if (activeLance != null && activeLance.Destroyed)
- {
- activeLance = null;
- if (currentState == EnergyLanceState.Tracking)
- {
- currentState = EnergyLanceState.Searching;
- }
- }
- }
-
- // 外部调用:当EnergyLance需要目标时调用
- public bool TryGetCurrentTarget(out IntVec3 targetPos)
- {
- if (currentTarget != null && IsValidTarget(currentTarget) && IsInRange(currentTarget.Position))
- {
- targetPos = currentTarget.Position;
- return true;
- }
-
- targetPos = IntVec3.Invalid;
- return false;
- }
-
- public override void PostExposeData()
- {
- base.PostExposeData();
-
- Scribe_Values.Look(ref currentState, "currentState", EnergyLanceState.Idle);
- Scribe_Values.Look(ref nextUpdateTick, "nextUpdateTick", 0);
- Scribe_Values.Look(ref noTargetTicks, "noTargetTicks", 0);
- Scribe_References.Look(ref currentTarget, "currentTarget");
- Scribe_Values.Look(ref lastTargetPosition, "lastTargetPosition", IntVec3.Invalid);
- Scribe_References.Look(ref activeLance, "activeLance");
- }
- }
-
- public enum EnergyLanceState
- {
- Idle,
- Searching,
- Tracking,
- NoTarget
- }
-}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompProperties_BuildingEnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompProperties_BuildingEnergyLance.cs
deleted file mode 100644
index c10e475f..00000000
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/CompProperties_BuildingEnergyLance.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using RimWorld;
-using Verse;
-
-namespace WulaFallenEmpire
-{
- public class CompProperties_BuildingEnergyLance : CompProperties
- {
- // 基础配置
- public float radius = 20f; // 作用半径
- public int updateIntervalTicks = 30; // 目标更新间隔(刻)
- public int maxNoTargetTicks = 120; // 无目标时最大存活时间
-
- // 目标选择配置
- public bool targetEnemies = true; // 是否以敌人为目标
- public bool targetNeutrals = false; // 是否以中立单位为目标
- public bool targetAnimals = false; // 是否以动物为目标
-
- // EnergyLance配置
- public ThingDef energyLanceDef; // 使用的EnergyLance类型
- public int energyLanceDuration = 600; // EnergyLance基础持续时间
- public int firesPerTick = 3; // 每刻伤害次数
-
- public CompProperties_BuildingEnergyLance()
- {
- this.compClass = typeof(CompBuildingEnergyLance);
- }
- }
-}
diff --git a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/GuidedEnergyLance.cs b/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/GuidedEnergyLance.cs
deleted file mode 100644
index 150f0243..00000000
--- a/Source/WulaFallenEmpire/Ability/WULA_AbilityGuidedEnergyLance/GuidedEnergyLance.cs
+++ /dev/null
@@ -1,255 +0,0 @@
-using RimWorld;
-using Verse;
-using UnityEngine;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace WulaFallenEmpire
-{
- public class GuidedEnergyLance : OrbitalStrike
- {
- // 引导相关属性
- public Thing controlBuilding; // 控制建筑
- private IntVec3 currentTarget = IntVec3.Invalid; // 当前目标位置
- private int lastTargetUpdateTick = -1; // 最后收到目标更新的刻
- private int maxNoUpdateTicks = 60; // 无更新时的最大存活时间
-
- // 移动配置
- public float moveSpeed = 2.0f; // 移动速度(格/秒)
- public float turnSpeed = 90f; // 转向速度(度/秒)
-
- // 状态
- private Vector3 currentVelocity;
- private bool hasValidTarget = false;
-
- // ModExtension引用
- private EnergyLanceExtension extension;
-
- private static List tmpThings = new List();
-
- public override void StartStrike()
- {
- base.StartStrike();
-
- // 获取ModExtension
- extension = def.GetModExtension();
- if (extension == null)
- {
- Log.Error($"[GuidedEnergyLance] No EnergyLanceExtension found on {def.defName}");
- return;
- }
-
- lastTargetUpdateTick = Find.TickManager.TicksGame;
-
- // 创建视觉效果
- CreateVisualEffect();
-
- Log.Message($"[GuidedEnergyLance] Guided EnergyLance started, controlled by {controlBuilding?.Label ?? "None"}");
- }
-
- private void CreateVisualEffect()
- {
- // 使用ModExtension中定义的Mote,如果没有则使用默认的PowerBeam
- if (extension.moteDef != null)
- {
- Mote mote = MoteMaker.MakeStaticMote(base.Position, base.Map, extension.moteDef);
- }
- else
- {
- // 使用原版PowerBeam的视觉效果
- MoteMaker.MakePowerBeamMote(base.Position, base.Map);
- }
- }
-
- protected override void Tick()
- {
- base.Tick();
-
- if (!base.Destroyed && extension != null)
- {
- // 检查目标更新状态
- CheckTargetStatus();
-
- // 移动光束
- MoveBeam();
-
- // 造成伤害
- for (int i = 0; i < firesPerTick; i++)
- {
- DoBeamDamage();
- }
- }
- }
-
- private void CheckTargetStatus()
- {
- int currentTick = Find.TickManager.TicksGame;
- int ticksSinceUpdate = currentTick - lastTargetUpdateTick;
-
- // 检查是否长时间未收到更新
- if (ticksSinceUpdate >= maxNoUpdateTicks)
- {
- Log.Message($"[GuidedEnergyLance] No target updates for {ticksSinceUpdate} ticks, destroying");
- Destroy();
- return;
- }
-
- // 检查控制建筑状态
- if (controlBuilding == null || controlBuilding.Destroyed || !controlBuilding.Spawned)
- {
- Log.Message($"[GuidedEnergyLance] Control building lost, destroying");
- Destroy();
- return;
- }
- }
-
- private void MoveBeam()
- {
- if (!hasValidTarget || !currentTarget.IsValid)
- {
- // 没有有效目标,缓慢移动或保持原地
- ApplyMinimalMovement();
- return;
- }
-
- // 计算移动方向
- Vector3 targetDirection = (currentTarget.ToVector3() - base.Position.ToVector3()).normalized;
-
- // 平滑转向
- if (currentVelocity.magnitude > 0.1f)
- {
- float maxTurnAngle = turnSpeed * 0.0167f; // 每帧最大转向角度(假设60FPS)
- currentVelocity = Vector3.RotateTowards(currentVelocity, targetDirection, maxTurnAngle * Mathf.Deg2Rad, moveSpeed * 0.0167f);
- }
- else
- {
- currentVelocity = targetDirection * moveSpeed * 0.0167f;
- }
-
- // 应用移动
- Vector3 newPos = base.Position.ToVector3() + currentVelocity;
- IntVec3 newCell = new IntVec3(Mathf.RoundToInt(newPos.x), 0, Mathf.RoundToInt(newPos.z));
-
- if (newCell != base.Position && newCell.InBounds(base.Map))
- {
- base.Position = newCell;
- }
-
- // 检查是否接近目标
- float distanceToTarget = Vector3.Distance(base.Position.ToVector3(), currentTarget.ToVector3());
- if (distanceToTarget < 1.5f)
- {
- // 到达目标附近,可以减速或保持位置
- currentVelocity *= 0.8f;
- }
-
- Log.Message($"[GuidedEnergyLance] Moving to {currentTarget}, distance: {distanceToTarget:F1}");
- }
-
- private void ApplyMinimalMovement()
- {
- // 无目标时的最小移动,防止完全静止
- if (currentVelocity.magnitude < 0.1f)
- {
- // 随机轻微移动
- currentVelocity = new Vector3(Rand.Range(-0.1f, 0.1f), 0f, Rand.Range(-0.1f, 0.1f));
- }
- else
- {
- // 缓慢减速
- currentVelocity *= 0.95f;
- }
-
- Vector3 newPos = base.Position.ToVector3() + currentVelocity;
- IntVec3 newCell = new IntVec3(Mathf.RoundToInt(newPos.x), 0, Mathf.RoundToInt(newPos.z));
-
- if (newCell != base.Position && newCell.InBounds(base.Map))
- {
- base.Position = newCell;
- }
- }
-
- private void DoBeamDamage()
- {
- if (extension == null) return;
-
- // 在当前光束位置周围随机选择一个单元格
- IntVec3 targetCell = (from x in GenRadial.RadialCellsAround(base.Position, 2f, useCenter: true)
- where x.InBounds(base.Map)
- select x).RandomElementByWeight((IntVec3 x) => 1f - Mathf.Min(x.DistanceTo(base.Position) / 2f, 1f) + 0.05f);
-
- // 尝试在该单元格点火(如果配置了点火)
- if (extension.igniteFires)
- {
- FireUtility.TryStartFireIn(targetCell, base.Map, Rand.Range(0.1f, extension.fireIgniteChance), instigator);
- }
-
- // 对该单元格内的物体造成伤害
- tmpThings.Clear();
- tmpThings.AddRange(targetCell.GetThingList(base.Map));
-
- for (int i = 0; i < tmpThings.Count; i++)
- {
- Thing thing = tmpThings[i];
-
- // 检查是否对尸体造成伤害
- if (!extension.applyDamageToCorpses && thing is Corpse)
- continue;
-
- // 计算伤害量
- int damageAmount = (thing is Corpse) ?
- extension.corpseDamageAmountRange.RandomInRange :
- extension.damageAmountRange.RandomInRange;
-
- Pawn pawn = thing as Pawn;
- BattleLogEntry_DamageTaken battleLogEntry = null;
-
- if (pawn != null)
- {
- battleLogEntry = new BattleLogEntry_DamageTaken(pawn, RulePackDefOf.DamageEvent_PowerBeam, instigator as Pawn);
- Find.BattleLog.Add(battleLogEntry);
- }
-
- // 使用ModExtension中定义的伤害类型
- DamageInfo damageInfo = new DamageInfo(extension.damageDef, damageAmount, 0f, -1f, instigator, null, weaponDef);
- thing.TakeDamage(damageInfo).AssociateWithLog(battleLogEntry);
- }
-
- tmpThings.Clear();
- }
-
- // 外部调用:更新目标位置
- public void UpdateTarget(IntVec3 newTarget)
- {
- lastTargetUpdateTick = Find.TickManager.TicksGame;
-
- if (newTarget.IsValid && newTarget.InBounds(base.Map))
- {
- currentTarget = newTarget;
- hasValidTarget = true;
-
- Log.Message($"[GuidedEnergyLance] Target updated to {newTarget}");
- }
- else
- {
- hasValidTarget = false;
- currentTarget = IntVec3.Invalid;
-
- Log.Message($"[GuidedEnergyLance] Target cleared");
- }
- }
-
- public override void ExposeData()
- {
- base.ExposeData();
-
- Scribe_References.Look(ref controlBuilding, "controlBuilding");
- Scribe_Values.Look(ref currentTarget, "currentTarget", IntVec3.Invalid);
- Scribe_Values.Look(ref lastTargetUpdateTick, "lastTargetUpdateTick", -1);
- Scribe_Values.Look(ref maxNoUpdateTicks, "maxNoUpdateTicks", 60);
- Scribe_Values.Look(ref moveSpeed, "moveSpeed", 2.0f);
- Scribe_Values.Look(ref turnSpeed, "turnSpeed", 90f);
- Scribe_Values.Look(ref firesPerTick, "firesPerTick", 3);
- }
- }
-}
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 34950f92..612883ea 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -76,8 +76,9 @@
+
-
+