暂存2
This commit is contained in:
@@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
=====================================================================
|
=====================================================================
|
||||||
离子武器最终正确架构配置示例
|
离子武器最终正确架构配置示例 (V17.0)
|
||||||
=====================================================================
|
=====================================================================
|
||||||
说明:
|
说明:
|
||||||
- 核心架构: 自定义 VerbProperties (VerbProperties_Wula_IonicBeam)
|
- 核心架构: 自定义 VerbProperties (VerbProperties_Wula_IonicBeam)
|
||||||
- 数据流: XML -> VerbProperties_Wula_IonicBeam -> Verb_Wula_...
|
- 伤害逻辑: 完全在C#中自定义,包括路径伤害和能量消耗。
|
||||||
- 特效: 复用原版Verb_ShootBeam的XML参数,由我们自己的C#代码读取和播放。
|
- 特效逻辑: 主要由我们自己在VerbProperties中定义的参数手动控制。
|
||||||
- 伤害: 由我们自定义的伤害参数控制,逻辑完全在C#中。
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<ThingDef Name="Wula_BaseIonicGun" Abstract="True" ParentName="BaseHumanMakeableGun">
|
<ThingDef Name="Wula_BaseIonicGun" Abstract="True" ParentName="BaseHumanMakeableGun">
|
||||||
@@ -31,12 +30,12 @@
|
|||||||
</statBases>
|
</statBases>
|
||||||
</ThingDef>
|
</ThingDef>
|
||||||
|
|
||||||
<!-- ==================== 模式一: 离子突破光束枪 (爆发贯穿) ==================== -->
|
<!-- ==================== 模式一: 离子突破光束枪 (爆发贯穿 + 路径爆炸) ==================== -->
|
||||||
|
|
||||||
<ThingDef ParentName="Wula_BaseIonicGun">
|
<ThingDef ParentName="Wula_BaseIonicGun">
|
||||||
<defName>WULA_Weapon_BreachingBeamGun</defName>
|
<defName>WULA_Weapon_BreachingBeamGun</defName>
|
||||||
<label>离子突破光束枪</label>
|
<label>离子突破光束枪</label>
|
||||||
<description>发射一道高能离子束,能够烧穿路径上的多个目标,直到能量耗尽。单发威力巨大,但射速较慢。</description>
|
<description>发射一道高能离子束,能够烧穿路径上的多个目标,直到能量耗尽。光束路径上会周期性地引发小规模湮灭反应。</description>
|
||||||
<verbs>
|
<verbs>
|
||||||
<li Class="WulaFallenEmpire.VerbProperties_Wula_IonicBeam">
|
<li Class="WulaFallenEmpire.VerbProperties_Wula_IonicBeam">
|
||||||
<verbClass>WulaFallenEmpire.Verb_Wula_BreachingBeam</verbClass>
|
<verbClass>WulaFallenEmpire.Verb_Wula_BreachingBeam</verbClass>
|
||||||
@@ -46,40 +45,40 @@
|
|||||||
<warmupTime>2.5</warmupTime>
|
<warmupTime>2.5</warmupTime>
|
||||||
<range>40</range>
|
<range>40</range>
|
||||||
<burstShotCount>1</burstShotCount>
|
<burstShotCount>1</burstShotCount>
|
||||||
<soundCast>Shot_ChargeLance</soundCast>
|
<soundCast>BeamGraser_Shooting</soundCast>
|
||||||
|
|
||||||
<!-- 我们自定义的伤害参数 -->
|
<!-- 我们自定义的伤害参数 -->
|
||||||
<breachingDamage>30000</breachingDamage>
|
<breachingDamage>300</breachingDamage>
|
||||||
<armorPenetration>0.95</armorPenetration>
|
<armorPenetration>0.95</armorPenetration>
|
||||||
<breachingBeamDuration>45</breachingBeamDuration> <!-- 光束命中后的短暂持续时间 -->
|
<breachingBeamDuration>45</breachingBeamDuration>
|
||||||
|
|
||||||
<!-- ==================== 特效参数 (由我们复制的逻辑使用) ==================== -->
|
<!-- 路径爆炸参数 -->
|
||||||
|
<explosionEnabled>true</explosionEnabled>
|
||||||
|
<explosionTickInterval>10</explosionTickInterval>
|
||||||
|
<explosionDamageDef>Wula_Dark_Matter</explosionDamageDef>
|
||||||
|
<explosionEnergyCostRatio>0.1</explosionEnergyCostRatio>
|
||||||
|
|
||||||
<!-- 核心特效 -->
|
<!-- 手动特效参数 -->
|
||||||
<beamMoteDef>Mote_ChargeLanceBeam</beamMoteDef> <!-- 光束主体样式 -->
|
<explosionHeatEnergyPerCell>10</explosionHeatEnergyPerCell>
|
||||||
<beamEndEffecterDef>ChargeLance_Explosion</beamEndEffecterDef> <!-- 光束终点特效 -->
|
<explosionCellFleck>BlastFlame</explosionCellFleck>
|
||||||
<soundCastBeam>Shot_ChargeLance_Sustainer</soundCastBeam> <!-- 光束持续音效 -->
|
<soundExplosion>Explosion_Flame</soundExplosion>
|
||||||
<muzzleFlashScale>12</muzzleFlashScale> <!-- 枪口火焰大小 -->
|
|
||||||
|
|
||||||
<!-- 范围与伤害类型 (伤害数值由我们的自定义参数控制) -->
|
<!-- 光束视觉特效参数 -->
|
||||||
<beamWidth>3</beamWidth> <!-- **决定视觉宽度和伤害范围** -->
|
<soundCastBeam>BeamGraser_Shooting</soundCastBeam>
|
||||||
<beamDamageDef>Beam</beamDamageDef> <!-- 伤害类型,主要影响被击中时的特效和音效 -->
|
<muzzleFlashScale>12</muzzleFlashScale>
|
||||||
<beamHitsNeighborCells>true</beamHitsNeighborCells> <!-- 是否对主光束旁边的格子造成溅射影响 -->
|
<beamWidth>3</beamWidth>
|
||||||
|
<beamMoteDef>Mote_GraserBeamBase</beamMoteDef>
|
||||||
<!-- 火焰效果 -->
|
<beamEndEffecterDef>GraserBeam_End</beamEndEffecterDef>
|
||||||
<beamChanceToStartFire>0.2</beamChanceToStartFire> <!-- 在地面点燃火焰的几率 -->
|
|
||||||
<beamChanceToAttachFire>0.2</beamChanceToAttachFire> <!-- 点燃击中单位的几率 -->
|
|
||||||
<beamFireSizeRange>0.3~0.5</beamFireSizeRange> <!-- 火焰大小 -->
|
|
||||||
</li>
|
</li>
|
||||||
</verbs>
|
</verbs>
|
||||||
</ThingDef>
|
</ThingDef>
|
||||||
|
|
||||||
<!-- ==================== 模式二: 离子灼烧光束枪 (持续伤害) ==================== -->
|
<!-- ==================== 模式二: 离子灼烧光束枪 (持续伤害 + 路径爆炸) ==================== -->
|
||||||
|
|
||||||
<ThingDef ParentName="Wula_BaseIonicGun">
|
<ThingDef ParentName="Wula_BaseIonicGun">
|
||||||
<defName>WULA_Weapon_SustainedBeamGun</defName>
|
<defName>WULA_Weapon_SustainedBeamGun</defName>
|
||||||
<label>离子灼烧光束枪</label>
|
<label>离子灼烧光束枪</label>
|
||||||
<description>投射一道持续存在的离子场,对作用范围内的所有敌人进行周期性灼烧。适合用于区域压制和清理大量轻甲目标。</description>
|
<description>投射一道持续存在的离子场,对作用范围内的所有敌人进行周期性灼烧,并引发连续的能量爆炸。</description>
|
||||||
<verbs>
|
<verbs>
|
||||||
<li Class="WulaFallenEmpire.VerbProperties_Wula_IonicBeam">
|
<li Class="WulaFallenEmpire.VerbProperties_Wula_IonicBeam">
|
||||||
<verbClass>WulaFallenEmpire.Verb_Wula_SustainedBeam</verbClass>
|
<verbClass>WulaFallenEmpire.Verb_Wula_SustainedBeam</verbClass>
|
||||||
@@ -90,40 +89,27 @@
|
|||||||
<range>30</range>
|
<range>30</range>
|
||||||
|
|
||||||
<!-- 我们自定义的伤害参数 -->
|
<!-- 我们自定义的伤害参数 -->
|
||||||
<sustainedDamagePerTick>20</sustainedDamagePerTick>
|
<sustainedDamagePerTick>15</sustainedDamagePerTick>
|
||||||
<tickInterval>15</tickInterval>
|
<tickInterval>15</tickInterval>
|
||||||
<duration>240</duration> <!-- 4 seconds -->
|
<duration>240</duration>
|
||||||
<armorPenetration>0.5</armorPenetration>
|
<armorPenetration>0.5</armorPenetration>
|
||||||
|
|
||||||
<!-- ==================== 特效参数 (由我们复制的逻辑使用) ==================== -->
|
<!-- 路径爆炸参数 -->
|
||||||
|
<explosionEnabled>true</explosionEnabled>
|
||||||
|
<explosionTickInterval>25</explosionTickInterval>
|
||||||
|
<explosionDamageDef>Wula_Dark_Matter_Flame</explosionDamageDef>
|
||||||
|
|
||||||
<!-- 核心特效 -->
|
<!-- 手动特效参数 -->
|
||||||
<beamMoteDef>Mote_GraserBeamBase</beamMoteDef>
|
<explosionHeatEnergyPerCell>10</explosionHeatEnergyPerCell>
|
||||||
<beamEndEffecterDef>GraserBeam_End</beamEndEffecterDef>
|
<explosionCellFleck>BlastFlame</explosionCellFleck>
|
||||||
|
<soundExplosion>Explosion_Flame</soundExplosion>
|
||||||
|
|
||||||
|
<!-- 光束视觉特效参数 -->
|
||||||
<soundCastBeam>BeamGraser_Shooting</soundCastBeam>
|
<soundCastBeam>BeamGraser_Shooting</soundCastBeam>
|
||||||
<muzzleFlashScale>9</muzzleFlashScale>
|
<muzzleFlashScale>9</muzzleFlashScale>
|
||||||
|
<beamWidth>3</beamWidth>
|
||||||
<!-- 范围与伤害类型 (伤害数值由我们的自定义参数控制) -->
|
<beamMoteDef>Mote_GraserBeamBase</beamMoteDef>
|
||||||
<beamWidth>3</beamWidth> <!-- **决定视觉宽度和伤害范围** -->
|
<beamEndEffecterDef>GraserBeam_End</beamEndEffecterDef>
|
||||||
<beamDamageDef>Flame</beamDamageDef>
|
|
||||||
<beamHitsNeighborCells>true</beamHitsNeighborCells>
|
|
||||||
|
|
||||||
<!-- 火焰效果 -->
|
|
||||||
<beamChanceToStartFire>0.1</beamChanceToStartFire>
|
|
||||||
<beamChanceToAttachFire>0.1</beamChanceToAttachFire>
|
|
||||||
<beamFireSizeRange>0.4~0.6</beamFireSizeRange>
|
|
||||||
|
|
||||||
<!-- 粒子效果 (可选,用于增加细节) -->
|
|
||||||
<beamGroundFleckDef>Fleck_Longspark</beamGroundFleckDef> <!-- 光束在地面上留下的斑点 -->
|
|
||||||
<beamFleckChancePerTick>0.5</beamFleckChancePerTick> <!-- 每Tick生成地面斑点的几率 -->
|
|
||||||
<beamLineFleckDef>Fleck_BeamSpark</beamLineFleckDef> <!-- 光束路径上的粒子 -->
|
|
||||||
<beamLineFleckChanceCurve> <!-- 路径粒子生成几率曲线 -->
|
|
||||||
<points>
|
|
||||||
<li>(0, 0)</li>
|
|
||||||
<li>(0.5, 0.5)</li>
|
|
||||||
<li>(1, 0)</li>
|
|
||||||
</points>
|
|
||||||
</beamLineFleckChanceCurve>
|
|
||||||
</li>
|
</li>
|
||||||
</verbs>
|
</verbs>
|
||||||
</ThingDef>
|
</ThingDef>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
using RimWorld;
|
using RimWorld;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
namespace WulaFallenEmpire
|
namespace WulaFallenEmpire
|
||||||
{
|
{
|
||||||
@@ -13,5 +14,18 @@ namespace WulaFallenEmpire
|
|||||||
public float sustainedDamagePerTick = 15f;
|
public float sustainedDamagePerTick = 15f;
|
||||||
public int tickInterval = 10;
|
public int tickInterval = 10;
|
||||||
public int duration = 120;
|
public int duration = 120;
|
||||||
|
|
||||||
|
// --- NEW: Explosion Path Properties (for both modes) ---
|
||||||
|
public bool explosionEnabled = false;
|
||||||
|
public int explosionTickInterval = 15;
|
||||||
|
public DamageDef explosionDamageDef;
|
||||||
|
public float explosionEnergyCostRatio = 0.5f; // Only for Breaching Beam
|
||||||
|
|
||||||
|
// Manual explosion effect properties
|
||||||
|
public float explosionHeatEnergyPerCell = 0;
|
||||||
|
public FleckDef explosionCellFleck;
|
||||||
|
public Color explosionColorCenter = Color.white;
|
||||||
|
public Color explosionColorEdge = Color.white;
|
||||||
|
public SoundDef soundExplosion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,9 @@ namespace WulaFallenEmpire
|
|||||||
// --- Our custom state ---
|
// --- Our custom state ---
|
||||||
private Vector3 beamEndPoint;
|
private Vector3 beamEndPoint;
|
||||||
private int ticksLeft;
|
private int ticksLeft;
|
||||||
private bool beamHitMapEdge; // NEW: Flag to check if the beam reached the map edge
|
private bool beamHitMapEdge;
|
||||||
|
private int explosionTicks;
|
||||||
|
private float beamEnergy;
|
||||||
|
|
||||||
private VerbProperties_Wula_IonicBeam BeamProps => (VerbProperties_Wula_IonicBeam)verbProps;
|
private VerbProperties_Wula_IonicBeam BeamProps => (VerbProperties_Wula_IonicBeam)verbProps;
|
||||||
|
|
||||||
@@ -28,14 +30,14 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
base.WarmupComplete();
|
base.WarmupComplete();
|
||||||
|
|
||||||
// --- Custom Damage Logic ---
|
// --- Initial Damage and Path Calculation ---
|
||||||
beamHitMapEdge = true; // Assume it will hit the edge unless stopped
|
beamHitMapEdge = true;
|
||||||
float shotAngle = (currentTarget.Cell - caster.Position).AngleFlat;
|
float shotAngle = (currentTarget.Cell - caster.Position).AngleFlat;
|
||||||
beamEndPoint = GetMapEdgePoint(caster.Position, shotAngle);
|
beamEndPoint = GetMapEdgePoint(caster.Position, shotAngle);
|
||||||
var cellsOnPath = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEndPoint.ToIntVec3(), verbProps.beamWidth);
|
var cellsOnPath = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEndPoint.ToIntVec3(), (int)verbProps.beamWidth);
|
||||||
var beamEnergy = BeamProps.breachingDamage; // Local variable for calculation
|
this.beamEnergy = BeamProps.breachingDamage;
|
||||||
|
|
||||||
// This loop calculates the final beam end point based on energy depletion
|
// This loop calculates the final beam end point based on the initial piercing damage
|
||||||
foreach (var cell in cellsOnPath)
|
foreach (var cell in cellsOnPath)
|
||||||
{
|
{
|
||||||
if (!cell.InBounds(caster.Map)) continue;
|
if (!cell.InBounds(caster.Map)) continue;
|
||||||
@@ -46,7 +48,7 @@ namespace WulaFallenEmpire
|
|||||||
if (beamEnergy <= 0) break;
|
if (beamEnergy <= 0) break;
|
||||||
|
|
||||||
float damageToDeal = Mathf.Min(beamEnergy, thing.HitPoints);
|
float damageToDeal = Mathf.Min(beamEnergy, thing.HitPoints);
|
||||||
var dinfo = new DamageInfo(verbProps.beamDamageDef ?? DamageDefOf.Burn, damageToDeal, BeamProps.armorPenetration, shotAngle, caster, EquipmentSource);
|
var dinfo = new DamageInfo(verbProps.beamDamageDef ?? DamageDefOf.Burn, damageToDeal, BeamProps.armorPenetration, shotAngle, caster, null, EquipmentSource?.def);
|
||||||
|
|
||||||
thing.TakeDamage(dinfo);
|
thing.TakeDamage(dinfo);
|
||||||
beamEnergy -= thing.HitPoints;
|
beamEnergy -= thing.HitPoints;
|
||||||
@@ -54,13 +56,13 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
if (beamEnergy <= 0)
|
if (beamEnergy <= 0)
|
||||||
{
|
{
|
||||||
beamEndPoint = cell.ToVector3Shifted(); // The beam stops here
|
beamEndPoint = cell.ToVector3Shifted();
|
||||||
beamHitMapEdge = false; // It was stopped, so it didn't hit the edge
|
beamHitMapEdge = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Copied Effect Logic ---
|
// --- Start Visual Effects ---
|
||||||
if (verbProps.beamMoteDef != null)
|
if (verbProps.beamMoteDef != null)
|
||||||
{
|
{
|
||||||
mote = MoteMaker.MakeInteractionOverlay(verbProps.beamMoteDef, caster, new TargetInfo(beamEndPoint.ToIntVec3(), caster.Map));
|
mote = MoteMaker.MakeInteractionOverlay(verbProps.beamMoteDef, caster, new TargetInfo(beamEndPoint.ToIntVec3(), caster.Map));
|
||||||
@@ -75,7 +77,7 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
if (ticksLeft > 0)
|
if (ticksLeft > 0)
|
||||||
{
|
{
|
||||||
// --- Copied Effect Logic ---
|
// --- Maintain Visual Effects ---
|
||||||
if (mote != null)
|
if (mote != null)
|
||||||
{
|
{
|
||||||
mote.UpdateTargets(new TargetInfo(caster.Position, caster.Map), new TargetInfo(beamEndPoint.ToIntVec3(), caster.Map), Vector3.zero, Vector3.zero);
|
mote.UpdateTargets(new TargetInfo(caster.Position, caster.Map), new TargetInfo(beamEndPoint.ToIntVec3(), caster.Map), Vector3.zero, Vector3.zero);
|
||||||
@@ -91,6 +93,17 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
sustainer?.Maintain();
|
sustainer?.Maintain();
|
||||||
|
|
||||||
|
// --- Path Explosion Logic ---
|
||||||
|
if (BeamProps.explosionEnabled)
|
||||||
|
{
|
||||||
|
explosionTicks--;
|
||||||
|
if (explosionTicks <= 0)
|
||||||
|
{
|
||||||
|
ApplyPathExplosionDamage();
|
||||||
|
explosionTicks = BeamProps.explosionTickInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ticksLeft--;
|
ticksLeft--;
|
||||||
if (ticksLeft <= 0)
|
if (ticksLeft <= 0)
|
||||||
{
|
{
|
||||||
@@ -101,19 +114,19 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
protected override bool TryCastShot()
|
protected override bool TryCastShot()
|
||||||
{
|
{
|
||||||
// The actual "shot" is just starting the effects, damage is pre-calculated in WarmupComplete
|
|
||||||
this.state = VerbState.Bursting;
|
this.state = VerbState.Bursting;
|
||||||
|
|
||||||
// NEW: Set duration based on whether it hit the map edge
|
|
||||||
if (beamHitMapEdge)
|
if (beamHitMapEdge)
|
||||||
{
|
{
|
||||||
this.ticksLeft = BeamProps.breachingBeamDuration;
|
this.ticksLeft = BeamProps.breachingBeamDuration;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.ticksLeft = 1; // Disappears almost instantly if blocked
|
this.ticksLeft = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.explosionTicks = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,12 +138,49 @@ namespace WulaFallenEmpire
|
|||||||
sustainer?.End();
|
sustainer?.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyPathExplosionDamage()
|
||||||
|
{
|
||||||
|
if (this.beamEnergy <= 0 || BeamProps.explosionDamageDef == null) return;
|
||||||
|
|
||||||
|
var pathCells = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEndPoint.ToIntVec3(), (int)verbProps.beamWidth);
|
||||||
|
var shotAngle = (beamEndPoint - caster.DrawPos).AngleFlat();
|
||||||
|
var explosionDamageDef = BeamProps.explosionDamageDef;
|
||||||
|
|
||||||
|
foreach (var cell in pathCells)
|
||||||
|
{
|
||||||
|
if (this.beamEnergy <= 0) break;
|
||||||
|
if (!cell.InBounds(caster.Map)) continue;
|
||||||
|
|
||||||
|
// Performance optimization: don't create explosions on every single cell of the path
|
||||||
|
if (cell.GetHashCode() % 2 != 0) continue;
|
||||||
|
|
||||||
|
var thingsToHit = cell.GetThingList(caster.Map).Where(t => CanHit(t)).ToList();
|
||||||
|
foreach (var thing in thingsToHit)
|
||||||
|
{
|
||||||
|
if (this.beamEnergy <= 0) break;
|
||||||
|
|
||||||
|
var dinfo = new DamageInfo(explosionDamageDef, explosionDamageDef.defaultDamage, explosionDamageDef.defaultArmorPenetration, shotAngle, caster, null, EquipmentSource?.def);
|
||||||
|
float damageDealt = Mathf.Min(thing.HitPoints, dinfo.Amount);
|
||||||
|
thing.TakeDamage(dinfo);
|
||||||
|
|
||||||
|
this.beamEnergy -= damageDealt * BeamProps.explosionEnergyCostRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(explosionDamageDef?.explosionCellMote != null)
|
||||||
|
{
|
||||||
|
FleckMaker.Static(cell, caster.Map, explosionDamageDef.explosionCellMote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void ExposeData()
|
public override void ExposeData()
|
||||||
{
|
{
|
||||||
base.ExposeData();
|
base.ExposeData();
|
||||||
Scribe_Values.Look(ref beamEndPoint, "beamEndPoint");
|
Scribe_Values.Look(ref beamEndPoint, "beamEndPoint");
|
||||||
Scribe_Values.Look(ref ticksLeft, "ticksLeft");
|
Scribe_Values.Look(ref ticksLeft, "ticksLeft");
|
||||||
Scribe_Values.Look(ref beamHitMapEdge, "beamHitMapEdge");
|
Scribe_Values.Look(ref beamHitMapEdge, "beamHitMapEdge");
|
||||||
|
Scribe_Values.Look(ref explosionTicks, "explosionTicks");
|
||||||
|
Scribe_Values.Look(ref beamEnergy, "beamEnergy");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanHit(Thing t)
|
private bool CanHit(Thing t)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace WulaFallenEmpire
|
|||||||
// --- Our custom state ---
|
// --- Our custom state ---
|
||||||
private int ticksLeft;
|
private int ticksLeft;
|
||||||
private int ticksToNextDamage;
|
private int ticksToNextDamage;
|
||||||
|
private int explosionTicks;
|
||||||
private Vector3 beamEnd;
|
private Vector3 beamEnd;
|
||||||
|
|
||||||
private VerbProperties_Wula_IonicBeam BeamProps => (VerbProperties_Wula_IonicBeam)verbProps;
|
private VerbProperties_Wula_IonicBeam BeamProps => (VerbProperties_Wula_IonicBeam)verbProps;
|
||||||
@@ -27,11 +28,9 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
base.WarmupComplete();
|
base.WarmupComplete();
|
||||||
|
|
||||||
// For sustained beam, it always reaches its max range
|
|
||||||
var shotAngle = (currentTarget.Cell - caster.Position).AngleFlat;
|
var shotAngle = (currentTarget.Cell - caster.Position).AngleFlat;
|
||||||
beamEnd = GetMapEdgePoint(caster.Position, shotAngle);
|
beamEnd = GetMapEdgePoint(caster.Position, shotAngle);
|
||||||
|
|
||||||
// --- Copied Effect Logic ---
|
|
||||||
if (verbProps.beamMoteDef != null)
|
if (verbProps.beamMoteDef != null)
|
||||||
{
|
{
|
||||||
mote = MoteMaker.MakeInteractionOverlay(verbProps.beamMoteDef, caster, new TargetInfo(beamEnd.ToIntVec3(), caster.Map));
|
mote = MoteMaker.MakeInteractionOverlay(verbProps.beamMoteDef, caster, new TargetInfo(beamEnd.ToIntVec3(), caster.Map));
|
||||||
@@ -44,10 +43,9 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
public override void BurstingTick()
|
public override void BurstingTick()
|
||||||
{
|
{
|
||||||
// This verb is not a standard "burst", but we use the state to manage the effect
|
|
||||||
if (ticksLeft > 0)
|
if (ticksLeft > 0)
|
||||||
{
|
{
|
||||||
// --- Copied Effect Logic ---
|
// --- Maintain Visual Effects ---
|
||||||
if (mote != null)
|
if (mote != null)
|
||||||
{
|
{
|
||||||
mote.UpdateTargets(new TargetInfo(caster.Position, caster.Map), new TargetInfo(beamEnd.ToIntVec3(), caster.Map), Vector3.zero, Vector3.zero);
|
mote.UpdateTargets(new TargetInfo(caster.Position, caster.Map), new TargetInfo(beamEnd.ToIntVec3(), caster.Map), Vector3.zero, Vector3.zero);
|
||||||
@@ -63,15 +61,26 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
sustainer?.Maintain();
|
sustainer?.Maintain();
|
||||||
|
|
||||||
// --- Custom Damage Logic ---
|
// --- Beam Damage Logic ---
|
||||||
ticksLeft--;
|
|
||||||
ticksToNextDamage--;
|
ticksToNextDamage--;
|
||||||
if (ticksToNextDamage <= 0)
|
if (ticksToNextDamage <= 0)
|
||||||
{
|
{
|
||||||
ApplyDamage();
|
ApplyBeamDamage();
|
||||||
ticksToNextDamage = BeamProps.tickInterval;
|
ticksToNextDamage = BeamProps.tickInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Path Explosion Logic ---
|
||||||
|
if (BeamProps.explosionEnabled)
|
||||||
|
{
|
||||||
|
explosionTicks--;
|
||||||
|
if (explosionTicks <= 0)
|
||||||
|
{
|
||||||
|
ApplyPathExplosionDamage();
|
||||||
|
explosionTicks = BeamProps.explosionTickInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ticksLeft--;
|
||||||
if (ticksLeft <= 0)
|
if (ticksLeft <= 0)
|
||||||
{
|
{
|
||||||
StopBeam();
|
StopBeam();
|
||||||
@@ -83,16 +92,25 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
this.state = VerbState.Bursting;
|
this.state = VerbState.Bursting;
|
||||||
this.ticksLeft = BeamProps.duration;
|
this.ticksLeft = BeamProps.duration;
|
||||||
this.ticksToNextDamage = 0; // First damage tick happens immediately
|
this.ticksToNextDamage = 0;
|
||||||
|
this.explosionTicks = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyDamage()
|
private void StopBeam()
|
||||||
|
{
|
||||||
|
this.state = VerbState.Idle;
|
||||||
|
mote?.Destroy();
|
||||||
|
endEffecter?.Cleanup();
|
||||||
|
sustainer?.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyBeamDamage()
|
||||||
{
|
{
|
||||||
var shotAngle = (beamEnd - caster.DrawPos).AngleFlat();
|
var shotAngle = (beamEnd - caster.DrawPos).AngleFlat();
|
||||||
var dinfo = new DamageInfo(verbProps.beamDamageDef ?? DamageDefOf.Burn, BeamProps.sustainedDamagePerTick, BeamProps.armorPenetration, shotAngle, caster, EquipmentSource);
|
var dinfo = new DamageInfo(verbProps.beamDamageDef ?? DamageDefOf.Burn, BeamProps.sustainedDamagePerTick, BeamProps.armorPenetration, shotAngle, caster, null, EquipmentSource?.def);
|
||||||
var cellsInBeam = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEnd.ToIntVec3(), verbProps.beamWidth);
|
var cellsInBeam = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEnd.ToIntVec3(), (int)verbProps.beamWidth);
|
||||||
|
|
||||||
foreach (var cell in cellsInBeam)
|
foreach (var cell in cellsInBeam)
|
||||||
{
|
{
|
||||||
@@ -106,12 +124,37 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopBeam()
|
private void ApplyPathExplosionDamage()
|
||||||
{
|
{
|
||||||
this.state = VerbState.Idle;
|
if (BeamProps.explosionDamageDef == null) return;
|
||||||
mote?.Destroy();
|
|
||||||
endEffecter?.Cleanup();
|
var pathCells = WulaBeamUtility.GetCellsInBeamArea(caster.Position, beamEnd.ToIntVec3(), (int)verbProps.beamWidth);
|
||||||
sustainer?.End();
|
var shotAngle = (beamEnd - caster.DrawPos).AngleFlat();
|
||||||
|
var explosionDamageDef = BeamProps.explosionDamageDef;
|
||||||
|
|
||||||
|
foreach (var cell in pathCells)
|
||||||
|
{
|
||||||
|
if (!cell.InBounds(caster.Map)) continue;
|
||||||
|
|
||||||
|
if (cell.GetHashCode() % 3 != 0) continue;
|
||||||
|
|
||||||
|
var thingsToHit = cell.GetThingList(caster.Map).Where(t => CanHit(t)).ToList();
|
||||||
|
foreach (var thing in thingsToHit)
|
||||||
|
{
|
||||||
|
var dinfo = new DamageInfo(explosionDamageDef, explosionDamageDef.defaultDamage, explosionDamageDef.defaultArmorPenetration, shotAngle, caster, null, EquipmentSource?.def);
|
||||||
|
thing.TakeDamage(dinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BeamProps.explosionCellFleck != null)
|
||||||
|
{
|
||||||
|
FleckMaker.Static(cell, caster.Map, BeamProps.explosionCellFleck);
|
||||||
|
}
|
||||||
|
if (BeamProps.soundExplosion != null)
|
||||||
|
{
|
||||||
|
BeamProps.soundExplosion.PlayOneShot(new TargetInfo(cell, caster.Map));
|
||||||
|
}
|
||||||
|
GenTemperature.PushHeat(cell, caster.Map, BeamProps.explosionHeatEnergyPerCell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ExposeData()
|
public override void ExposeData()
|
||||||
@@ -119,6 +162,7 @@ namespace WulaFallenEmpire
|
|||||||
base.ExposeData();
|
base.ExposeData();
|
||||||
Scribe_Values.Look(ref ticksLeft, "ticksLeft", 0);
|
Scribe_Values.Look(ref ticksLeft, "ticksLeft", 0);
|
||||||
Scribe_Values.Look(ref ticksToNextDamage, "ticksToNextDamage", 0);
|
Scribe_Values.Look(ref ticksToNextDamage, "ticksToNextDamage", 0);
|
||||||
|
Scribe_Values.Look(ref explosionTicks, "explosionTicks");
|
||||||
Scribe_Values.Look(ref beamEnd, "beamEnd");
|
Scribe_Values.Look(ref beamEnd, "beamEnd");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +175,7 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
float mapSize = Mathf.Max(caster.Map.Size.x, caster.Map.Size.z) * 1.5f;
|
float mapSize = Mathf.Max(caster.Map.Size.x, caster.Map.Size.z) * 1.5f;
|
||||||
Vector3 direction = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward;
|
Vector3 direction = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward;
|
||||||
return start.toVector3() + direction * mapSize;
|
return start.ToVector3() + direction * mapSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,12 +13,12 @@ namespace WulaFallenEmpire
|
|||||||
// A more advanced method to get all cells in a rectangular area
|
// A more advanced method to get all cells in a rectangular area
|
||||||
public static IEnumerable<IntVec3> GetCellsInBeamArea(IntVec3 start, IntVec3 end, int width)
|
public static IEnumerable<IntVec3> GetCellsInBeamArea(IntVec3 start, IntVec3 end, int width)
|
||||||
{
|
{
|
||||||
|
var beamLine = GenSight.PointsOnLineOfSight(start, end);
|
||||||
if (width <= 1)
|
if (width <= 1)
|
||||||
{
|
{
|
||||||
return GenGrid.PointsOnLine(start, end).Distinct();
|
return beamLine.Distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
var beamLine = GenGrid.PointsOnLine(start, end).ToList();
|
|
||||||
var allCells = new HashSet<IntVec3>(beamLine);
|
var allCells = new HashSet<IntVec3>(beamLine);
|
||||||
var halfWidth = (width - 1) / 2;
|
var halfWidth = (width - 1) / 2;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0"
|
||||||
|
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -190,6 +191,10 @@
|
|||||||
<Compile Include="CompForceTargetable.cs" />
|
<Compile Include="CompForceTargetable.cs" />
|
||||||
<Compile Include="Patch_ForceTargetable.cs" />
|
<Compile Include="Patch_ForceTargetable.cs" />
|
||||||
<Compile Include="Patch_ArmedShuttle_ForceTargetable.cs" />
|
<Compile Include="Patch_ArmedShuttle_ForceTargetable.cs" />
|
||||||
|
<Compile Include="VerbProperties_Wula_IonicBeam.cs" />
|
||||||
|
<Compile Include="Verb_Wula_BreachingBeam.cs" />
|
||||||
|
<Compile Include="Verb_Wula_SustainedBeam.cs" />
|
||||||
|
<Compile Include="WulaBeamUtility.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
Reference in New Issue
Block a user