暂存
This commit is contained in:
301
Source/WulaFallenEmpire/LightningBombardment.cs
Normal file
301
Source/WulaFallenEmpire/LightningBombardment.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.Sound;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompAbilityEffect_DRM_LightningBombardment : CompAbilityEffect
|
||||
{
|
||||
public new CompProperties_AbilityDRM_LightningBombardment Props
|
||||
{
|
||||
get => (CompProperties_AbilityDRM_LightningBombardment)props;
|
||||
}
|
||||
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
Map map = parent.pawn.MapHeld;
|
||||
|
||||
// 获取或创建地图组件
|
||||
MapComponent_LightningBombardment comp = GetOrCreateMapComponent(map);
|
||||
|
||||
// 启动轰炸任务
|
||||
comp.StartBombardment(
|
||||
target: target.Cell,
|
||||
instigator: parent.pawn,
|
||||
explosionCount: Props.explosionCount,
|
||||
bombIntervalTicks: Props.bombIntervalTicks,
|
||||
impactAreaRadius: Props.impactAreaRadius,
|
||||
explosionRadiusRange: Props.explosionRadiusRange,
|
||||
damageDef: Props.damageDef,
|
||||
damageAmount: Props.damageAmount,
|
||||
armorPenetration: Props.armorPenetration,
|
||||
postExplosionSpawnThingDef: Props.postExplosionSpawnThingDef,
|
||||
postExplosionSpawnChance: Props.postExplosionSpawnChance,
|
||||
postExplosionSpawnThingCount: Props.postExplosionSpawnThingCount
|
||||
);
|
||||
|
||||
// 播放启动音效
|
||||
SoundDefOf.Thunder_OffMap.PlayOneShotOnCamera(map);
|
||||
}
|
||||
|
||||
private MapComponent_LightningBombardment GetOrCreateMapComponent(Map map)
|
||||
{
|
||||
MapComponent_LightningBombardment comp = map.GetComponent<MapComponent_LightningBombardment>();
|
||||
if (comp == null)
|
||||
{
|
||||
comp = new MapComponent_LightningBombardment(map);
|
||||
map.components.Add(comp);
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
public override void DrawEffectPreview(LocalTargetInfo target)
|
||||
{
|
||||
// 显示施法范围
|
||||
float castingRange = parent.verb.verbProps.range;
|
||||
GenDraw.DrawRadiusRing(parent.pawn.Position, castingRange, Color.white);
|
||||
|
||||
// 显示爆炸作用范围
|
||||
GenDraw.DrawRadiusRing(target.Cell, Props.impactAreaRadius, Color.white);
|
||||
if (target.IsValid) GenDraw.DrawTargetHighlight(target);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompProperties_AbilityDRM_LightningBombardment : CompProperties_AbilityEffect
|
||||
{
|
||||
public CompProperties_AbilityDRM_LightningBombardment()
|
||||
{
|
||||
compClass = typeof(CompAbilityEffect_DRM_LightningBombardment);
|
||||
}
|
||||
|
||||
public float impactAreaRadius = 10f;
|
||||
public FloatRange explosionRadiusRange = new FloatRange(3f, 4f);
|
||||
public int bombIntervalTicks = 30;
|
||||
public int explosionCount = 3;
|
||||
|
||||
public DamageDef damageDef;
|
||||
public int damageAmount = 30;
|
||||
public float armorPenetration = 0.8f;
|
||||
|
||||
public ThingDef postExplosionSpawnThingDef;
|
||||
public float postExplosionSpawnChance;
|
||||
public int postExplosionSpawnThingCount;
|
||||
}
|
||||
|
||||
// 地图组件管理轰炸任务
|
||||
public class MapComponent_LightningBombardment : MapComponent
|
||||
{
|
||||
private readonly List<BombardmentCoroutine> activeCoroutines = new List<BombardmentCoroutine>();
|
||||
private const int MAX_CONCURRENT_BOMBARDMENTS = 5;
|
||||
|
||||
public MapComponent_LightningBombardment(Map map) : base(map) { }
|
||||
|
||||
public void StartBombardment(
|
||||
IntVec3 target,
|
||||
Pawn instigator,
|
||||
int explosionCount,
|
||||
int bombIntervalTicks,
|
||||
float impactAreaRadius,
|
||||
FloatRange explosionRadiusRange,
|
||||
DamageDef damageDef,
|
||||
int damageAmount,
|
||||
float armorPenetration,
|
||||
ThingDef postExplosionSpawnThingDef,
|
||||
float postExplosionSpawnChance,
|
||||
int postExplosionSpawnThingCount)
|
||||
{
|
||||
// 防止过多任务影响性能
|
||||
if (activeCoroutines.Count >= MAX_CONCURRENT_BOMBARDMENTS)
|
||||
{
|
||||
Log.Warning($"Too many concurrent bombardments on map {map}, max is {MAX_CONCURRENT_BOMBARDMENTS}");
|
||||
return;
|
||||
}
|
||||
|
||||
activeCoroutines.Add(new BombardmentCoroutine(
|
||||
target: target,
|
||||
map: map,
|
||||
instigator: instigator,
|
||||
explosionCount: explosionCount,
|
||||
bombIntervalTicks: bombIntervalTicks,
|
||||
impactAreaRadius: impactAreaRadius,
|
||||
explosionRadiusRange: explosionRadiusRange,
|
||||
damageDef: damageDef,
|
||||
damageAmount: damageAmount,
|
||||
armorPenetration: armorPenetration,
|
||||
postExplosionSpawnThingDef: postExplosionSpawnThingDef,
|
||||
postExplosionSpawnChance: postExplosionSpawnChance,
|
||||
postExplosionSpawnThingCount: postExplosionSpawnThingCount
|
||||
));
|
||||
}
|
||||
|
||||
public override void MapComponentTick()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = activeCoroutines.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!activeCoroutines[i].Tick())
|
||||
{
|
||||
activeCoroutines.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Lightning bombardment error: {ex}");
|
||||
activeCoroutines.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StaticConstructorOnStartup]
|
||||
// 轰炸任务协程
|
||||
public class BombardmentCoroutine
|
||||
{
|
||||
private readonly IntVec3 target;
|
||||
private readonly Map map;
|
||||
private readonly Pawn instigator;
|
||||
private readonly int explosionCount;
|
||||
private readonly FloatRange explosionRadiusRange;
|
||||
private readonly float impactAreaRadius;
|
||||
private readonly int bombIntervalTicks;
|
||||
|
||||
public DamageDef damageDef;
|
||||
public int damageAmount;
|
||||
public float armorPenetration;
|
||||
public ThingDef postExplosionSpawnThingDef;
|
||||
public float postExplosionSpawnChance;
|
||||
public int postExplosionSpawnThingCount;
|
||||
|
||||
private int nextBombTick;
|
||||
private int explosionsRemaining;
|
||||
|
||||
private static readonly Material LightningMat = MatLoader.LoadMat("Weather/LightningBolt", -1);
|
||||
|
||||
public BombardmentCoroutine(
|
||||
IntVec3 target,
|
||||
Map map,
|
||||
Pawn instigator,
|
||||
int explosionCount,
|
||||
int bombIntervalTicks,
|
||||
float impactAreaRadius,
|
||||
FloatRange explosionRadiusRange,
|
||||
DamageDef damageDef,
|
||||
int damageAmount,
|
||||
float armorPenetration,
|
||||
ThingDef postExplosionSpawnThingDef,
|
||||
float postExplosionSpawnChance,
|
||||
int postExplosionSpawnThingCount)
|
||||
{
|
||||
this.target = target;
|
||||
this.map = map;
|
||||
this.instigator = instigator;
|
||||
this.explosionCount = explosionCount;
|
||||
this.bombIntervalTicks = bombIntervalTicks;
|
||||
this.impactAreaRadius = impactAreaRadius;
|
||||
this.explosionRadiusRange = explosionRadiusRange;
|
||||
this.damageDef = damageDef;
|
||||
this.damageAmount = damageAmount;
|
||||
this.armorPenetration = armorPenetration;
|
||||
this.postExplosionSpawnThingDef = postExplosionSpawnThingDef;
|
||||
this.postExplosionSpawnChance = postExplosionSpawnChance;
|
||||
this.postExplosionSpawnThingCount = postExplosionSpawnThingCount;
|
||||
|
||||
explosionsRemaining = explosionCount;
|
||||
nextBombTick = Find.TickManager.TicksGame + bombIntervalTicks;
|
||||
}
|
||||
|
||||
public bool Tick()
|
||||
{
|
||||
if (Find.TickManager.TicksGame >= nextBombTick)
|
||||
{
|
||||
ExecuteBomb();
|
||||
explosionsRemaining--;
|
||||
|
||||
if (explosionsRemaining > 0)
|
||||
{
|
||||
nextBombTick += bombIntervalTicks;
|
||||
}
|
||||
}
|
||||
return explosionsRemaining > 0;
|
||||
}
|
||||
|
||||
private void ExecuteBomb()
|
||||
{
|
||||
// 在轰炸区域内随机选择目标点
|
||||
IntVec3 bombTarget = GetRandomCellInRadius(target, map, impactAreaRadius);
|
||||
|
||||
// 创建闪电视觉效果
|
||||
CreateLightningEffect(bombTarget);
|
||||
|
||||
// 执行爆炸
|
||||
GenExplosion.DoExplosion(
|
||||
center: bombTarget,
|
||||
map: map,
|
||||
radius: explosionRadiusRange.RandomInRange,
|
||||
damType: damageDef,
|
||||
instigator: instigator,
|
||||
damAmount: damageAmount,
|
||||
armorPenetration: armorPenetration,
|
||||
postExplosionSpawnThingDef: postExplosionSpawnThingDef,
|
||||
postExplosionSpawnChance: postExplosionSpawnChance,
|
||||
postExplosionSpawnThingCount: postExplosionSpawnThingCount,
|
||||
applyDamageToExplosionCellsNeighbors: true,
|
||||
chanceToStartFire: 0.4f,
|
||||
damageFalloff: true
|
||||
);
|
||||
}
|
||||
|
||||
private IntVec3 GetRandomCellInRadius(IntVec3 center, Map map, float radius)
|
||||
{
|
||||
if (radius <= 0.0f) return center;
|
||||
|
||||
if (CellFinder.TryFindRandomCellNear(
|
||||
center,
|
||||
map,
|
||||
Mathf.CeilToInt(radius),
|
||||
c => c.DistanceTo(center) <= radius && c.Standable(map),
|
||||
out IntVec3 result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return center; // 备用方案
|
||||
}
|
||||
|
||||
private void CreateLightningEffect(IntVec3 strikeLoc)
|
||||
{
|
||||
if (strikeLoc.Fogged(map)) return;
|
||||
|
||||
Vector3 position = strikeLoc.ToVector3Shifted();
|
||||
|
||||
// 1. 播放声音
|
||||
SoundDefOf.Thunder_OffMap.PlayOneShotOnCamera(map);
|
||||
|
||||
// 2. 生成粒子效果
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
FleckMaker.ThrowSmoke(position, map, 1.5f);
|
||||
FleckMaker.ThrowMicroSparks(position, map);
|
||||
FleckMaker.ThrowLightningGlow(position, map, 1.5f);
|
||||
}
|
||||
|
||||
// 3. 绘制闪电网格
|
||||
Mesh boltMesh = LightningBoltMeshPool.RandomBoltMesh;
|
||||
Graphics.DrawMesh(
|
||||
boltMesh,
|
||||
strikeLoc.ToVector3ShiftedWithAltitude(AltitudeLayer.Weather),
|
||||
Quaternion.identity,
|
||||
FadedMaterialPool.FadedVersionOf(LightningMat, 1f),
|
||||
0
|
||||
);
|
||||
|
||||
// 4. 播放局部雷声
|
||||
SoundInfo soundInfo = SoundInfo.InMap(new TargetInfo(strikeLoc, map));
|
||||
SoundDefOf.Thunder_OnMap.PlayOneShot(soundInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,7 @@
|
||||
<Compile Include="JobGiver_WulaGetEnergy.cs" />
|
||||
<Compile Include="JobGiver_WulaPackEnergy.cs" />
|
||||
<Compile Include="JobGiverDefExtension_WulaPackEnergy.cs" />
|
||||
<Compile Include="LightningBombardment.cs" />
|
||||
<Compile Include="MechanitorPatch.cs" />
|
||||
<Compile Include="MentalBreakWorker_BrokenPersonality.cs" />
|
||||
<Compile Include="MentalState_BrokenPersonality.cs" />
|
||||
|
||||
Reference in New Issue
Block a user