1
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// File: Verb_RangeChecker.cs
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
@@ -7,194 +6,60 @@ using Verse;
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于距离判断的Verb,不发射任何射弹,不造成伤害,仅用于距离计算和AI判断
|
||||
/// 用于距离判断的Verb,不发射任何射弹,不造成伤害,不产生噪音
|
||||
/// 仅用于距离计算、视线检查和AI判断
|
||||
/// 当发射成功时,会设置Pawn身上所有Comp_MultiTurretGun的focusTarget为目标
|
||||
/// </summary>
|
||||
public class Verb_RangeChecker : Verb_LaunchProjectile
|
||||
public class Verb_RangeChecker : Verb
|
||||
{
|
||||
// 重写瞄准相关方法,使其不产生视觉或声音效果
|
||||
public override void WarmupComplete()
|
||||
{
|
||||
base.WarmupComplete();
|
||||
|
||||
// 不播放射击声音
|
||||
// 不产生射击效果
|
||||
}
|
||||
|
||||
protected override bool TryCastShot()
|
||||
{
|
||||
// 基础检查
|
||||
if (currentTarget.HasThing && currentTarget.Thing.Map != caster.Map)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ThingDef projectile = Projectile;
|
||||
if (projectile == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ShootLine resultingLine;
|
||||
bool flag = TryFindShootLineFromTo(caster.Position, currentTarget, out resultingLine);
|
||||
if (verbProps.stopBurstWithoutLos && !flag)
|
||||
{
|
||||
return false;
|
||||
|
||||
// 检查视线
|
||||
ShootLine shootLine;
|
||||
if (!TryFindShootLineFromTo(caster.Position, currentTarget, out shootLine))
|
||||
{
|
||||
if (verbProps.stopBurstWithoutLos)
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新设备状态(如果有)
|
||||
if (base.EquipmentSource != null)
|
||||
{
|
||||
base.EquipmentSource.GetComp<CompChangeableProjectile>()?.Notify_ProjectileLaunched();
|
||||
base.EquipmentSource.GetComp<CompApparelVerbOwner_Charged>()?.UsedOnce();
|
||||
}
|
||||
|
||||
// 记录射击时间
|
||||
lastShotTick = Find.TickManager.TicksGame;
|
||||
Thing manningPawn = caster;
|
||||
Thing equipmentSource = base.EquipmentSource;
|
||||
CompMannable compMannable = caster.TryGetComp<CompMannable>();
|
||||
if (compMannable?.ManningPawn != null)
|
||||
{
|
||||
manningPawn = compMannable.ManningPawn;
|
||||
equipmentSource = caster;
|
||||
}
|
||||
|
||||
Vector3 drawPos = caster.DrawPos;
|
||||
Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, resultingLine.Source, caster.Map);
|
||||
if (equipmentSource.TryGetComp(out CompUniqueWeapon comp))
|
||||
{
|
||||
foreach (WeaponTraitDef item in comp.TraitsListForReading)
|
||||
{
|
||||
if (item.damageDefOverride != null)
|
||||
{
|
||||
projectile2.damageDefOverride = item.damageDefOverride;
|
||||
}
|
||||
|
||||
if (!item.extraDamages.NullOrEmpty())
|
||||
{
|
||||
Projectile projectile3 = projectile2;
|
||||
if (projectile3.extraDamages == null)
|
||||
{
|
||||
projectile3.extraDamages = new List<ExtraDamage>();
|
||||
}
|
||||
projectile2.extraDamages.AddRange(item.extraDamages);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新炮塔焦点目标
|
||||
UpdateTurretFocusTargets();
|
||||
|
||||
if (verbProps.ForcedMissRadius > 0.5f)
|
||||
{
|
||||
float num = verbProps.ForcedMissRadius;
|
||||
if (manningPawn is Pawn pawn)
|
||||
{
|
||||
num *= verbProps.GetForceMissFactorFor(equipmentSource, pawn);
|
||||
}
|
||||
|
||||
float num2 = VerbUtility.CalculateAdjustedForcedMiss(num, currentTarget.Cell - caster.Position);
|
||||
if (num2 > 0.5f)
|
||||
{
|
||||
IntVec3 forcedMissTarget = GetForcedMissTarget(num2);
|
||||
if (forcedMissTarget != currentTarget.Cell)
|
||||
{
|
||||
ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld;
|
||||
if (Rand.Chance(0.5f))
|
||||
{
|
||||
projectileHitFlags = ProjectileHitFlags.All;
|
||||
}
|
||||
|
||||
if (!canHitNonTargetPawnsNow)
|
||||
{
|
||||
projectileHitFlags &= ~ProjectileHitFlags.NonTargetPawns;
|
||||
}
|
||||
|
||||
// 模拟发射成功,但不实际发射
|
||||
bool shotResult = SimulateShotSuccess(drawPos, forcedMissTarget, currentTarget, projectileHitFlags, preventFriendlyFire, equipmentSource);
|
||||
if (shotResult)
|
||||
{
|
||||
UpdateTurretFocusTargets();
|
||||
}
|
||||
return shotResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShotReport shotReport = ShotReport.HitReportFor(caster, this, currentTarget);
|
||||
Thing randomCoverToMissInto = shotReport.GetRandomCoverToMissInto();
|
||||
ThingDef targetCoverDef = randomCoverToMissInto?.def;
|
||||
|
||||
if (verbProps.canGoWild && !Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture))
|
||||
{
|
||||
bool flyOverhead = projectile2?.def?.projectile != null && projectile2.def.projectile.flyOverhead;
|
||||
resultingLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget, flyOverhead, caster.Map);
|
||||
ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld;
|
||||
if (Rand.Chance(0.5f) && canHitNonTargetPawnsNow)
|
||||
{
|
||||
projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns;
|
||||
}
|
||||
|
||||
// 模拟发射成功,但不实际发射
|
||||
bool shotResult = SimulateShotSuccess(drawPos, resultingLine.Dest, currentTarget, projectileHitFlags2, preventFriendlyFire, equipmentSource, targetCoverDef);
|
||||
if (shotResult)
|
||||
{
|
||||
UpdateTurretFocusTargets();
|
||||
}
|
||||
return shotResult;
|
||||
}
|
||||
|
||||
if (currentTarget.Thing != null && currentTarget.Thing.def.CanBenefitFromCover && !Rand.Chance(shotReport.PassCoverChance))
|
||||
{
|
||||
ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld;
|
||||
if (canHitNonTargetPawnsNow)
|
||||
{
|
||||
projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns;
|
||||
}
|
||||
|
||||
// 模拟发射成功,但不实际发射
|
||||
bool shotResult = SimulateShotSuccess(drawPos, randomCoverToMissInto, currentTarget, projectileHitFlags3, preventFriendlyFire, equipmentSource, targetCoverDef);
|
||||
if (shotResult)
|
||||
{
|
||||
UpdateTurretFocusTargets();
|
||||
}
|
||||
return shotResult;
|
||||
}
|
||||
|
||||
ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget;
|
||||
if (canHitNonTargetPawnsNow)
|
||||
{
|
||||
projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns;
|
||||
}
|
||||
|
||||
if (!currentTarget.HasThing || currentTarget.Thing.def.Fillage == FillCategory.Full)
|
||||
{
|
||||
projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld;
|
||||
}
|
||||
|
||||
// 模拟发射成功,但不实际发射
|
||||
bool finalShotResult = SimulateFinalShotSuccess(drawPos, resultingLine.Dest, currentTarget, projectileHitFlags4, preventFriendlyFire, equipmentSource, targetCoverDef);
|
||||
if (finalShotResult)
|
||||
{
|
||||
UpdateTurretFocusTargets();
|
||||
}
|
||||
return finalShotResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟射击成功的情况
|
||||
/// </summary>
|
||||
private bool SimulateShotSuccess(Vector3 drawPos, IntVec3 targetCell, LocalTargetInfo target, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null)
|
||||
{
|
||||
// 这里不实际发射射弹,只返回成功
|
||||
// 销毁之前创建的射弹对象,因为我们不需要它
|
||||
// 返回成功,但不实际射击
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟射击成功的情况(带目标)
|
||||
/// 重写射击效果,确保不产生任何视觉或声音效果
|
||||
/// </summary>
|
||||
private bool SimulateShotSuccess(Vector3 drawPos, Thing target, LocalTargetInfo originalTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null)
|
||||
public override void DrawHighlight(LocalTargetInfo target)
|
||||
{
|
||||
// 这里不实际发射射弹,只返回成功
|
||||
// 销毁之前创建的射弹对象,因为我们不需要它
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模拟最终射击成功的情况
|
||||
/// </summary>
|
||||
private bool SimulateFinalShotSuccess(Vector3 drawPos, IntVec3 targetCell, LocalTargetInfo target, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null)
|
||||
{
|
||||
// 这里不实际发射射弹,只返回成功
|
||||
// 销毁之前创建的射弹对象,因为我们不需要它
|
||||
return true;
|
||||
base.DrawHighlight(target);
|
||||
|
||||
// 可以绘制距离指示,但不绘制射击预览
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,14 +74,89 @@ namespace WulaFallenEmpire
|
||||
|
||||
foreach (var turretComp in turretComps)
|
||||
{
|
||||
// 设置集中火力目标
|
||||
Comp_MultiTurretGun.focusTarget = currentTarget;
|
||||
Comp_MultiTurretGun.lastFocusSetTick = Find.TickManager.TicksGame;
|
||||
Comp_MultiTurretGun.lastFocusPawn = pawn;
|
||||
|
||||
// 强制炮塔立即重新索敌,以便它们能检测到新的集中火力目标
|
||||
turretComp.TryAcquireTarget();
|
||||
if (turretComp != null)
|
||||
{
|
||||
// 设置集中火力目标
|
||||
Comp_MultiTurretGun.focusTarget = currentTarget;
|
||||
Comp_MultiTurretGun.lastFocusSetTick = Find.TickManager.TicksGame;
|
||||
Comp_MultiTurretGun.lastFocusPawn = pawn;
|
||||
|
||||
// 强制炮塔立即重新索敌,以便它们能检测到新的集中火力目标
|
||||
turretComp.TryAcquireTarget();
|
||||
}
|
||||
}
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[Verb_RangeChecker] {pawn.LabelShort} set focus target to {currentTarget}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写可用性检查,确保只有符合条件的Pawn才能使用
|
||||
/// </summary>
|
||||
public override bool Available()
|
||||
{
|
||||
if (!base.Available())
|
||||
return false;
|
||||
|
||||
// 额外的检查:确保有炮塔组件
|
||||
if (caster is Pawn pawn)
|
||||
{
|
||||
var turretComps = pawn.GetComps<Comp_MultiTurretGun>();
|
||||
if (turretComps == null )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写验证方法,添加额外的距离检查
|
||||
/// </summary>
|
||||
public override bool CanHitTarget(LocalTargetInfo targ)
|
||||
{
|
||||
if (!base.CanHitTarget(targ))
|
||||
return false;
|
||||
|
||||
// 检查距离
|
||||
float distance = caster.Position.DistanceTo(targ.Cell);
|
||||
if (distance > verbProps.range)
|
||||
return false;
|
||||
|
||||
// 检查最小距离
|
||||
if (distance < verbProps.minRange)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写目标高亮显示
|
||||
/// </summary>
|
||||
public override void OrderForceTarget(LocalTargetInfo target)
|
||||
{
|
||||
if (CanHitTarget(target))
|
||||
{
|
||||
base.OrderForceTarget(target);
|
||||
UpdateTurretFocusTargets();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写,确保不产生任何射击效果
|
||||
/// </summary>
|
||||
public override void Notify_EquipmentLost()
|
||||
{
|
||||
base.Notify_EquipmentLost();
|
||||
|
||||
// 清理焦点目标
|
||||
if (caster is Pawn pawn)
|
||||
{
|
||||
Comp_MultiTurretGun.lastFocusPawn = null;
|
||||
Comp_MultiTurretGun.focusTarget = LocalTargetInfo.Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,8 +170,21 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
verbClass = typeof(Verb_RangeChecker);
|
||||
|
||||
// 默认设置为不发射射弹
|
||||
// 设置为不发射射弹
|
||||
defaultProjectile = null;
|
||||
|
||||
// 设置无噪音
|
||||
soundCast = null;
|
||||
soundCastTail = null;
|
||||
|
||||
// 无视觉效果
|
||||
muzzleFlashScale = 0f;
|
||||
|
||||
// 无预热时间
|
||||
warmupTime = 0f;
|
||||
|
||||
// 无冷却时间
|
||||
defaultCooldownTime = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user