整理一下

This commit is contained in:
2025-08-29 16:10:25 +08:00
parent d759562b83
commit dce9a31cd6
51 changed files with 52 additions and 52 deletions

View File

@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
namespace WulaFallenEmpire
{
public class Thing_ExcaliburBeam : Mote
{
public IntVec3 targetCell;
public Pawn caster;
public ThingDef weaponDef;
public float damageAmount;
public float armorPenetration;
public float pathWidth;
public DamageDef damageDef;
// Burst shot support
public int burstShotsTotal = 1;
public int currentBurstShot = 0;
// Path cells for this burst
private List<IntVec3> currentBurstCells;
private int ticksToDetonate = 0;
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref targetCell, "targetCell");
Scribe_References.Look(ref caster, "caster");
Scribe_Defs.Look(ref weaponDef, "weaponDef");
Scribe_Values.Look(ref damageAmount, "damageAmount");
Scribe_Values.Look(ref armorPenetration, "armorPenetration");
Scribe_Values.Look(ref pathWidth, "pathWidth");
Scribe_Defs.Look(ref damageDef, "damageDef");
Scribe_Values.Look(ref burstShotsTotal, "burstShotsTotal", 1);
Scribe_Values.Look(ref currentBurstShot, "currentBurstShot", 0);
}
public void StartStrike(List<IntVec3> allCells, int burstIndex, int totalBursts)
{
if (allCells == null || !allCells.Any())
{
Destroy();
return;
}
currentBurstCells = new List<IntVec3>(allCells);
currentBurstShot = burstIndex;
burstShotsTotal = totalBursts;
// Add a small delay before detonation for visual effect
ticksToDetonate = 10; // 10 ticks delay before detonation
}
protected override void TimeInterval(float deltaTime)
{
base.TimeInterval(deltaTime);
if (ticksToDetonate > 0)
{
ticksToDetonate--;
if (ticksToDetonate == 0)
{
Detonate();
}
}
}
private void Detonate()
{
if (currentBurstCells == null || !currentBurstCells.Any() || Map == null)
{
Destroy();
return;
}
// Create a copy of the list to avoid modification during iteration
List<IntVec3> cellsToDetonate = new List<IntVec3>(currentBurstCells);
// Clear the current burst cells to prevent reuse
currentBurstCells.Clear();
foreach (IntVec3 cell in cellsToDetonate)
{
if (cell.InBounds(Map))
{
// Apply explosion effect, but ignore the caster
List<Thing> ignoredThings = new List<Thing>();
if (caster != null)
{
ignoredThings.Add(caster);
}
DamageDef explosionDamageType = damageDef ?? DamageDefOf.Bomb;
// Create explosion parameters with more precise settings
GenExplosion.DoExplosion(
center: cell,
map: Map,
radius: 1.2f, // Slightly larger radius for better visual effect
damType: explosionDamageType,
instigator: caster,
damAmount: (int)damageAmount,
armorPenetration: armorPenetration,
explosionSound: null,
weapon: weaponDef,
projectile: null,
intendedTarget: null,
postExplosionSpawnThingDef: null,
postExplosionSpawnChance: 0f,
postExplosionSpawnThingCount: 1,
postExplosionGasType: null,
applyDamageToExplosionCellsNeighbors: true, // Apply damage to neighbor cells
preExplosionSpawnThingDef: null,
preExplosionSpawnChance: 0f,
preExplosionSpawnThingCount: 1,
chanceToStartFire: 0.1f, // Small chance to start fire
damageFalloff: true, // Add damage falloff
direction: null,
ignoredThings: ignoredThings,
affectedAngle: null,
doVisualEffects: true,
propagationSpeed: 0.5f, // Add some propagation speed for visual effect
screenShakeFactor: 0.3f, // Add screen shake
doSoundEffects: true,
postExplosionSpawnThingDefWater: null,
flammabilityChanceCurve: null,
overrideCells: null,
postExplosionSpawnSingleThingDef: null,
preExplosionSpawnSingleThingDef: null);
}
}
// Check if there are more bursts to come
if (currentBurstShot < burstShotsTotal - 1)
{
// Prepare for next burst
ticksToDetonate = 15; // Wait 15 ticks before next burst
currentBurstShot++;
}
else
{
// All bursts completed, destroy the mote
Destroy();
}
}
}
}

View File

@@ -0,0 +1,15 @@
using Verse;
using RimWorld;
namespace WulaFallenEmpire
{
public class VerbProperties_Excalibur : VerbProperties
{
public float pathWidth = 1f; // Default path width
public DamageDef damageDef; // Custom damage type
public float damageAmount = -1f; // Custom damage amount
public float armorPenetration = -1f; // Custom armor penetration
public float maxRange = 1000f; // Default max range for beams
public string beamDefName = "ExcaliburBeam"; // Default beam def name
}
}

View File

@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
namespace WulaFallenEmpire
{
public class Verb_Excalibur : Verb
{
private new Pawn CasterPawn
{
get
{
return base.CasterPawn;
}
}
private ThingWithComps weapon
{
get
{
return this.CasterPawn.equipment.Primary;
}
}
private QualityCategory quality
{
get
{
return this.weapon.TryGetComp<CompQuality>().Quality;
}
}
private float damageAmountBase
{
get
{
return this.weapon.def.tools.First<Tool>().power;
}
}
private float armorPenetrationBase
{
get
{
return this.weapon.def.tools.First<Tool>().armorPenetration;
}
}
private float damageAmount
{
get
{
if (this.ExcaliburProps.damageAmount > 0)
{
return this.ExcaliburProps.damageAmount;
}
return 1.0f * this.damageAmountBase;
}
}
private float armorPenetration
{
get
{
if (this.ExcaliburProps.armorPenetration >= 0)
{
return this.ExcaliburProps.armorPenetration;
}
return 1.0f * this.armorPenetrationBase;
}
}
private VerbProperties_Excalibur ExcaliburProps
{
get
{
return (VerbProperties_Excalibur)this.verbProps;
}
}
protected override int ShotsPerBurst
{
get
{
return this.verbProps.burstShotCount;
}
}
protected override bool TryCastShot()
{
// Calculate all affected cells once
List<IntVec3> allAffectedCells = this.AffectedCells(this.currentTarget);
// Create a beam for this specific burst
Thing_ExcaliburBeam beam = (Thing_ExcaliburBeam)GenSpawn.Spawn(DefDatabase<ThingDef>.GetNamed(this.ExcaliburProps.beamDefName, true), this.CasterPawn.Position, this.CasterPawn.Map);
beam.caster = this.CasterPawn;
beam.targetCell = this.currentTarget.Cell;
beam.damageAmount = this.damageAmount;
beam.armorPenetration = this.armorPenetration;
beam.pathWidth = this.ExcaliburProps.pathWidth;
beam.weaponDef = this.CasterPawn.equipment.Primary.def;
beam.damageDef = this.ExcaliburProps.damageDef;
beam.StartStrike(allAffectedCells, this.ShotsPerBurst, this.ShotsPerBurst);
return true;
}
public override void DrawHighlight(LocalTargetInfo target)
{
GenDraw.DrawFieldEdges(this.AffectedCells(target));
}
private List<IntVec3> AffectedCells(LocalTargetInfo target)
{
this.tmpCells.Clear();
Vector3 vector = this.CasterPawn.Position.ToVector3Shifted().Yto0();
IntVec3 endCell = this.TargetPosition(this.CasterPawn, target);
this.tmpCells.Clear();
foreach (IntVec3 cell in GenSight.BresenhamCellsBetween(this.CasterPawn.Position, endCell))
{
if (!cell.InBounds(this.CasterPawn.Map))
{
break;
}
if (cell.GetEdifice(this.CasterPawn.Map) != null && cell.GetEdifice(this.CasterPawn.Map).def.passability == Traversability.Impassable)
{
break;
}
// Add cells around the current cell based on pathWidth
// Convert pathWidth to proper radius for GenRadial
float radius = Math.Max(0.5f, this.ExcaliburProps.pathWidth - 0.5f);
foreach (IntVec3 radialCell in GenRadial.RadialCellsAround(cell, radius, true))
{
if (radialCell.InBounds(this.CasterPawn.Map) && !this.tmpCells.Contains(radialCell))
{
this.tmpCells.Add(radialCell);
}
}
}
return this.tmpCells;
}
public IntVec3 TargetPosition(Pawn pawn, LocalTargetInfo currentTarget)
{
IntVec3 position = pawn.Position;
IntVec3 cell = currentTarget.Cell;
Vector3 direction = (cell - position).ToVector3().normalized;
// Define a maximum range to prevent infinite loops or excessively long beams
float maxRange = this.ExcaliburProps.maxRange; // Use configurable max range
for (float i = 0; i < maxRange; i += 1f)
{
IntVec3 currentCell = (position.ToVector3() + direction * i).ToIntVec3();
if (!currentCell.InBounds(pawn.Map))
{
return currentCell; // Reached map boundary
}
// Check for walls or other impassable terrain
if (currentCell.GetEdifice(pawn.Map) != null && currentCell.GetEdifice(pawn.Map).def.passability == Traversability.Impassable)
{
return currentCell; // Hit an impassable wall
}
}
return (position.ToVector3() + direction * maxRange).ToIntVec3(); // Reached max range
}
private bool CanUseCell(IntVec3 c)
{
return c.InBounds(this.CasterPawn.Map) && c != this.CasterPawn.Position;
}
private List<IntVec3> tmpCells = new List<IntVec3>();
}
}