This commit is contained in:
2025-09-22 14:20:36 +08:00
parent 0b555a7d3a
commit 23b1b6dd3b
4 changed files with 211 additions and 0 deletions

View File

@@ -202,6 +202,7 @@
<Compile Include="Verbs\Verb_ShootMeltBeam.cs" />
<Compile Include="Verbs\Verb_ShootShotgun.cs" />
<Compile Include="Verbs\VerbProperties_Excalibur.cs" />
<Compile Include="Verbs\Verb_ShootSprayMulti.cs" />
<Compile Include="Verbs\WeaponStealBeam\Verb_ShootWeaponStealBeam.cs" />
<Compile Include="Verbs\WeaponStealBeam\VerbProperties_WeaponStealBeam.cs" />
<Compile Include="Building_ARANutrientDispenser.cs" />

View File

@@ -0,0 +1,134 @@
using RimWorld;
using System.Collections.Generic;
using UnityEngine;
using Verse;
using Verse.Sound;
namespace ArachnaeSwarm
{
public class Verb_ShootSprayMulti : Verb_Shoot
{
public VerbProperties_ShootSprayMulti SprayProps => verbProps as VerbProperties_ShootSprayMulti;
protected override bool TryCastShot()
{
if (currentTarget.HasThing && currentTarget.Thing.Map != caster.Map)
{
return false;
}
List<IntVec3> cells = AffectedCells(currentTarget);
if (cells.Count == 0)
{
return false;
}
// A single "shot" from the verb will fire projectiles at all affected cells.
// The base verb's burst fire mechanism will handle firing multiple "shots".
bool shotFired = false;
foreach (var cell in cells)
{
if (CanHitTarget(cell))
{
ShootLine shootLine;
if (TryFindShootLineFromTo(caster.Position, cell, out shootLine))
{
Projectile projectile = (Projectile)GenSpawn.Spawn(verbProps.defaultProjectile, shootLine.Source, caster.Map);
// Corrected Launch call without targetCover
projectile.Launch(caster, caster.DrawPos, cell, cell, ProjectileHitFlags.IntendedTarget, equipment: (caster as Pawn)?.equipment?.Primary);
shotFired = true;
}
}
}
if (shotFired)
{
// Corrected sound calls based on MCP knowledge
if (verbProps.soundCast != null)
{
verbProps.soundCast.PlayOneShot(SoundInfo.InMap(new TargetInfo(caster.Position, caster.Map)));
}
if (verbProps.soundCastTail != null)
{
verbProps.soundCastTail.PlayOneShotOnCamera();
}
if (caster is Pawn pawn)
{
if (pawn.records != null)
{
pawn.records.Increment(RecordDefOf.ShotsFired);
}
if (pawn.skills != null)
{
pawn.skills.Learn(SkillDefOf.Shooting, 0.5f);
}
}
}
return shotFired;
}
// This logic is adapted from CompAbilityEffect_SprayLiquidMulti
private List<IntVec3> AffectedCells(LocalTargetInfo target)
{
List<Pair<IntVec3, float>> tmpCellDots = new List<Pair<IntVec3, float>>();
List<IntVec3> tmpCells = new List<IntVec3>();
tmpCellDots.Clear();
tmpCells.Clear();
tmpCellDots.Add(new Pair<IntVec3, float>(target.Cell, 999f));
int numCellsToHit = SprayProps?.numCellsToHit ?? 1;
if (numCellsToHit > 1)
{
Vector3 vector = caster.Position.ToVector3Shifted().Yto0();
Vector3 vector2 = target.Cell.ToVector3Shifted().Yto0();
IntVec3[] array;
int num;
if (numCellsToHit < 10)
{
array = GenAdj.AdjacentCells;
num = 8;
}
else
{
array = GenRadial.RadialPattern;
num = numCellsToHit + 5;
}
for (int i = 0; i < num; i++)
{
IntVec3 first = target.Cell + array[i];
Vector3 vector3 = first.ToVector3Shifted().Yto0();
float second = Vector3.Dot((vector3 - vector).normalized, (vector3 - vector2).normalized);
tmpCellDots.Add(new Pair<IntVec3, float>(first, second));
}
tmpCellDots.SortByDescending(x => x.Second);
}
Map map = caster.Map;
int num2 = Mathf.Min(tmpCellDots.Count, numCellsToHit);
for (int j = 0; j < num2; j++)
{
IntVec3 first2 = tmpCellDots[j].First;
if (!first2.InBounds(map)) continue;
if (first2.Filled(map))
{
Building_Door door = first2.GetDoor(map);
if (door == null || !door.Open) continue;
}
if (TryFindShootLineFromTo(caster.Position, first2, out var _))
{
tmpCells.Add(first2);
}
}
return tmpCells;
}
}
public class VerbProperties_ShootSprayMulti : VerbProperties
{
public int numCellsToHit = 1;
}
}