134 lines
4.7 KiB
C#
134 lines
4.7 KiB
C#
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;
|
|
}
|
|
} |