diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index caddfe47..c09b2360 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/HediffDefs/WULA_Misc_Hediffs.xml b/1.6/1.6/Defs/HediffDefs/WULA_Misc_Hediffs.xml index 01fecea4..c9469457 100644 --- a/1.6/1.6/Defs/HediffDefs/WULA_Misc_Hediffs.xml +++ b/1.6/1.6/Defs/HediffDefs/WULA_Misc_Hediffs.xml @@ -372,4 +372,75 @@
  • + + + Wula_TerrainBlocked + + 虽然乌拉族的大部分构装体采用反重力悬浮可以无视崎岖地表,但是其庞大的身躯依然会导致其在狭窄地形中难以行动。 + HediffWithComps + 1 + false + +
  • + 0.1 + + 0.9 + +
  • +
  • + 0.2 + + 0.8 + +
  • +
  • + 0.3 + + 0.7 + +
  • +
  • + 0.4 + + 0.6 + +
  • +
  • + 0.5 + + 0.5 + +
  • +
  • + 0.6 + + 0.4 + +
  • +
  • + 0.7 + + 0.3 + +
  • +
  • + 0.8 + + 0.2 + +
  • +
  • + 0.9 + + 0.1 + +
  • + + +
  • + 0.75 + 60 +
  • +
    + \ No newline at end of file diff --git a/1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml b/1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml index 7752c73e..8fe1b576 100644 --- a/1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml +++ b/1.6/1.6/Defs/PawnKinds/PawnKinds_Wula.xml @@ -204,10 +204,13 @@ 99999~99999 0.7 + +
  • Wula_AI_Heavy_Panzer_Weapon
  • +
    Wula_AI_Rocket_Panzer - + Wula_AI_Rocket_Panzer 500 false @@ -239,7 +242,7 @@ 0.7 -
  • Wula_AI_Heavy_Panzer_Weapon
  • +
  • Wula_AI_Rocket_Panzer_Weapon
  • diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Machine_Weapon.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Machine_Weapon.xml index 0577b16a..f93e5bba 100644 --- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Machine_Weapon.xml +++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Machine_Weapon.xml @@ -438,14 +438,14 @@ WULA_RW_Handle_Cannon_Burn 40 130 - 1 + 1.5 1 Wula_AI_Heavy_Panzer_Main_Weapon - - HAp-6"战车"车体正面的突击炮,射程很短并且只能在静止状态开火,但是威力巨大,专门用于对付坚固的工事和成片的人群。 + + HAp-6"巨戟"车体上的测距器,可以确保其炮塔在可以开火的最佳距离,被其瞄准的目标会成为炮塔的优先攻击目标。 Normal Spacer None @@ -466,87 +466,43 @@ 1 1 1 - 3.5 + 0.1
  • - Verb_Shoot + WulaFallenEmpire.Verb_RangeChecker true - Bullet_Wula_AI_Heavy_Panzer_Main_Weapon - 2 - 21 + Bullet_ChargeRifle + 5.9 + 60 + 0.2 1 - 1 - RocketswarmLauncher_Fire - GunTail_Heavy + true
  • - 200 - 12 + 1
  • Wula_AI_Heavy_Panzer_Weapon
  • - +
    - - Bullet_Wula_AI_Heavy_Panzer_Main_Weapon - - RealtimeOnly - - Wula/Projectile/WULA_Shrapnel - Graphic_Single - (2,2) - - WulaFallenEmpire.Projectile_NorthArcTrail - Normal - True - - WULA_GiantBomb - 65 - 25 - 6 - 1.5 - true - Artillery_HitThickRoof - MortarBomb_Explode - MortarRound_PreImpact - MortarRound_Ambient - 10 - Filth_BlastMark - - -
  • - 5 - 1.0 - true -
  • -
  • - WULA_Smoke_Tail - 5 - 1 - 1~2 - 0.5~1.0 - 0.1~0.3 - -30~30 -
  • -
    -
    Wula_AI_Rocket_Panzer_Turret_Weapon - HRp-3"喷火战车"的炮塔,可以一次性发射大量的火箭弹。 + HRp-3"炎霖"的炮塔,可以一次性发射大量的火箭弹。 None true Ultra @@ -565,7 +521,7 @@
  • - Verb_Shoot + WulaFallenEmpire.Verb_TurretOffestShoot true Bullet_Wula_AI_Rocket_Panzer_Turret_Weapon 0 @@ -581,6 +537,14 @@ 18
  • + +
  • + +
  • (0.62, -4.1)
  • +
  • (-0.62, -4.1)
  • + + +
    Bullet_Wula_AI_Rocket_Panzer_Turret_Weapon @@ -610,7 +574,7 @@
  • - 6 + 18 1.0 true
  • @@ -625,6 +589,64 @@
    + + Wula_AI_Rocket_Panzer_Main_Weapon + + HRp-3"炎霖"车体上的测距器,可以确保其炮塔在可以开火的最佳距离,被其瞄准的目标会成为炮塔的优先攻击目标。 + Normal + Spacer + None + true + Wula/Projectile/WULA_Shrapnel + + Wula/Weapon/WULA_Weapon_Empty + Graphic_Single + 1.35 + + Interact_Rifle + + + 2500 + + 8 + 1 + 1 + 1 + 1 + 0.1 + + +
  • + WulaFallenEmpire.Verb_RangeChecker + true + Bullet_ChargeRifle + 12 + 79 + 0.2 + 1 + false + + + true + +
  • +
    + + 1 + + +
  • Wula_AI_Rocket_Panzer_Weapon
  • +
    + + +
  • + +
  • Wula_AI_Rocket_Panzer
  • + + +
    +
    Wula_Psi_Titan_Beam diff --git a/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml b/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml index be604906..87f7d407 100644 --- a/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml +++ b/1.6/1.6/Defs/ThingDefs_Races/WULA_Mechunit_Race.xml @@ -81,6 +81,8 @@ 1 1 2 + + 3 300 @@ -118,7 +120,7 @@ Wula_AI_Heavy_Panzer_Turret_Weapon 20 0 - 3 + 6 true 1.2 @@ -328,6 +330,12 @@ PawnFlyer PawnFlyerLand + + + true + 1 + 60 + Wula_TerrainBlocked false @@ -338,8 +346,8 @@ Wula_AI_Rocket_Panzer - - 乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,拥有车体臼炮和两具可以发射大量燃烧火箭弹的转轮导弹巢。 + + 乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,可以在远距离上使用火箭弹巢发射漫天的弹幕,用纯粹的火力淹没敌方集群。 2 2 @@ -351,6 +359,8 @@ 1 1 2 + + 3 300 @@ -390,7 +400,7 @@ 0 8 true - 10 + 12.2 @@ -463,7 +473,7 @@ ConstructMetal
  • - Wula_AI_Heavy_Panzer_Main_Weapon + Wula_AI_Rocket_Panzer_Main_Weapon
  • true diff --git a/Source/WulaFallenEmpire/HediffComp/WULA_TerrainBlocked/HediffComp_TerrainBlocked.cs b/Source/WulaFallenEmpire/HediffComp/WULA_TerrainBlocked/HediffComp_TerrainBlocked.cs new file mode 100644 index 00000000..069aef8b --- /dev/null +++ b/Source/WulaFallenEmpire/HediffComp/WULA_TerrainBlocked/HediffComp_TerrainBlocked.cs @@ -0,0 +1,115 @@ +using RimWorld; +using Verse; +using UnityEngine; + +namespace WulaFallenEmpire +{ + /// + /// 地形阻挡Hediff组件,用于调整移动速度 + /// + public class HediffComp_TerrainBlocked : HediffComp + { + public HediffCompProperties_TerrainBlocked Props => (HediffCompProperties_TerrainBlocked)props; + + /// + /// 当前地形阻挡严重度(0-1之间) + /// + public float currentBlockSeverity = 0f; + + /// + /// 上一次更新时间(ticks) + /// + private int lastUpdateTick = -1; + + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + + // 降低更新频率:每Props.checkIntervalTicks检查一次 + if (Find.TickManager.TicksGame % Props.checkIntervalTicks != 0) + return; + + // 如果Pawn已死亡或无法移动,清除效果 + if (Pawn == null || Pawn.Dead || Pawn.Downed || !Pawn.Spawned) + { + currentBlockSeverity = 0f; + severityAdjustment = 0f; + return; + } + + // 获取CompHighSpeedCollision组件 + var collisionComp = Pawn.GetComp(); + if (collisionComp == null) + { + currentBlockSeverity = 0f; + severityAdjustment = 0f; + return; + } + + // 获取当前阻挡严重度 + float newSeverity = collisionComp.GetCurrentTerrainBlockSeverity(); + + // 立即设置阻挡严重度(移除平滑过渡) + currentBlockSeverity = newSeverity; + + // 更新Hediff严重度(立即变化) + severityAdjustment = currentBlockSeverity - Pawn.health.hediffSet.GetFirstHediffOfDef(parent.def).Severity; + + lastUpdateTick = Find.TickManager.TicksGame; + } + + /// + /// 获取移动速度乘数 + /// + public float GetMoveSpeedMultiplier() + { + if (currentBlockSeverity <= 0f) + return 1f; + + // 应用严重度对应的速度惩罚(线性) + return 1f - currentBlockSeverity * Props.maxSpeedPenalty; + } + + public override string CompTipStringExtra + { + get + { + if (currentBlockSeverity > 0.01f) + { + float speedMultiplier = GetMoveSpeedMultiplier(); + float speedPenalty = (1f - speedMultiplier) * 100f; + return $"地形阻挡: {currentBlockSeverity:P0}\n移动速度: -{speedPenalty:F0}%"; + } + return null; + } + } + + public override void CompExposeData() + { + base.CompExposeData(); + Scribe_Values.Look(ref currentBlockSeverity, "currentBlockSeverity", 0f); + Scribe_Values.Look(ref lastUpdateTick, "lastUpdateTick", -1); + } + } + + /// + /// 地形阻挡Hediff组件属性 + /// + public class HediffCompProperties_TerrainBlocked : HediffCompProperties + { + /// + /// 最大速度惩罚(0-1之间) + /// + public float maxSpeedPenalty = 0.5f; + + /// + /// 检查间隔(ticks) - 降低判断频率 + /// + public int checkIntervalTicks = 60; + + public HediffCompProperties_TerrainBlocked() + { + compClass = typeof(HediffComp_TerrainBlocked); + } + } +} diff --git a/Source/WulaFallenEmpire/Pawn_Comps/HighSpeedCollision/CompHighSpeedCollision.cs b/Source/WulaFallenEmpire/Pawn_Comps/HighSpeedCollision/CompHighSpeedCollision.cs index 91ab5cce..fd80e26f 100644 --- a/Source/WulaFallenEmpire/Pawn_Comps/HighSpeedCollision/CompHighSpeedCollision.cs +++ b/Source/WulaFallenEmpire/Pawn_Comps/HighSpeedCollision/CompHighSpeedCollision.cs @@ -36,7 +36,11 @@ namespace WulaFallenEmpire // === 缓存 === private CellRect collisionAreaCache = default; private int lastAreaRecalculationTick = -1; - + + // === 地形阻挡相关 === + private float currentTerrainBlockSeverity = 0f; + private int lastTerrainCheckTick = -1; + public CompProperties_HighSpeedCollision Props => (CompProperties_HighSpeedCollision)props; public override void PostSpawnSetup(bool respawningAfterLoad) @@ -53,29 +57,169 @@ namespace WulaFallenEmpire lastPosition = parent.Position; lastPositionTick = Find.TickManager.TicksGame; } - + + public override void CompTick() { base.CompTick(); - + if (!parent.Spawned || parent.Destroyed) return; - + Pawn pawn = parent as Pawn; if (pawn == null || pawn.Dead || pawn.Downed) - return; - - // 检查是否死亡或不能移动 - if (!CanMove(pawn)) { ResetToStage0(); return; } - + // 每帧更新 ProcessFrame(pawn); + + // 地形阻挡检查(降低频率) + if (Props.narrowTerrainBlocked && + (Find.TickManager.TicksGame - lastTerrainCheckTick >= Props.terrainCheckInterval)) + { + UpdateTerrainBlockStatus(pawn); + lastTerrainCheckTick = Find.TickManager.TicksGame; + } } - + /// + /// 更新地形阻挡状态 + /// + private void UpdateTerrainBlockStatus(Pawn pawn) + { + if (!Props.narrowTerrainBlocked || Props.maxBlockPenalty <= 0f) + { + currentTerrainBlockSeverity = 0f; + UpdateBlockedHediff(pawn, 0f); + return; + } + // 获取碰撞区域 + CellRect collisionArea = GetCollisionArea(pawn); + // 统计空闲格子和被占据格子 + int totalCells = 0; + int occupiedCells = 0; + foreach (IntVec3 cell in collisionArea) + { + if (!cell.InBounds(pawn.Map)) + continue; + totalCells++; + // 检查是否被不可通行建筑占据 + if (IsCellBlockedByImpassable(cell, pawn.Map)) + { + occupiedCells++; + } + } + // 计算阻挡严重度 + float blockSeverity = CalculateBlockSeverity(totalCells, occupiedCells); + // 立即设置阻挡严重度(移除平滑过渡) + currentTerrainBlockSeverity = blockSeverity; + // 更新Hediff + UpdateBlockedHediff(pawn, currentTerrainBlockSeverity); + // 调试日志 + if (Props.enableDebugLogging && currentTerrainBlockSeverity > 0.01f) + { + Log.Message($"[HighSpeedCollision] Terrain Block: {pawn.Label}, " + + $"Occupied: {occupiedCells}/{totalCells}, " + + $"Severity: {currentTerrainBlockSeverity:P0}"); + } + } + + /// + /// 检查单元格是否被不可通行建筑占据 + /// + private bool IsCellBlockedByImpassable(IntVec3 cell, Map map) + { + // 获取单元格内的所有建筑 + var things = cell.GetThingList(map); + foreach (var thing in things) + { + if (thing is Building building) + { + // 检查是否可通行 + if (building.def.passability == Traversability.Impassable) + { + return true; + } + } + } + + return false; + } + + /// + /// 计算阻挡严重度 + /// + private float CalculateBlockSeverity(int totalCells, int occupiedCells) + { + if (totalCells == 0 || occupiedCells == 0) + return 0f; + + int freeCells = totalCells - occupiedCells; + float freeRatio = (float)freeCells / totalCells; + + // 使用公式:(1 - maxBlockPenalty) + maxBlockPenalty * (空闲格子/(空闲格子+被占据格子)) + // 简化后:1 - maxBlockPenalty + maxBlockPenalty * (freeCells / totalCells) + // 但实际上,我们应该计算减速比例,然后转换为严重度 + float speedMultiplier = (1f - Props.maxBlockPenalty) + + Props.maxBlockPenalty * (freeRatio); + + // 严重度 = 1 - 速度乘数 + return 1f - speedMultiplier; + } + + /// + /// 平滑过渡 + /// + private float SmoothTransition(float current, float target, float speed) + { + if (Mathf.Abs(current - target) < 0.01f) + return target; + + return Mathf.Lerp(current, target, speed); + } + + /// + /// 更新阻挡Hediff + /// + private void UpdateBlockedHediff(Pawn pawn, float severity) + { + if (Props.blockedHediff == null) + return; + + // 获取或添加Hediff + Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.blockedHediff); + + if (severity <= 0.01f) + { + // 移除Hediff + if (hediff != null) + { + pawn.health.RemoveHediff(hediff); + } + return; + } + + // 添加或更新Hediff + if (hediff == null) + { + hediff = HediffMaker.MakeHediff(Props.blockedHediff, pawn); + pawn.health.AddHediff(hediff); + } + + // 更新严重度 + hediff.Severity = severity; + } + + /// + /// 获取当前地形阻挡严重度(供HediffComp使用) + /// + public float GetCurrentTerrainBlockSeverity() + { + return currentTerrainBlockSeverity; + } + /// /// 处理每帧逻辑 /// @@ -846,7 +990,28 @@ namespace WulaFallenEmpire /// 绘制速度历史图 /// public bool debugDrawSpeedHistory = false; - + + // === 狭窄地形阻挡配置 === + /// + /// 是否启用狭窄地形阻挡 + /// + public bool narrowTerrainBlocked = false; + + /// + /// 最高阻挡减益值(0-1之间) + /// + public float maxBlockPenalty = 0.5f; + + /// + /// 地形检查间隔(ticks) + /// + public int terrainCheckInterval = 60; + + /// + /// 阻挡减益Hediff定义 + /// + public HediffDef blockedHediff; + public CompProperties_HighSpeedCollision() { compClass = typeof(CompHighSpeedCollision); diff --git a/Source/WulaFallenEmpire/Pawn_Comps/MultiTurretGun/CompMultiTurretGun.cs b/Source/WulaFallenEmpire/Pawn_Comps/MultiTurretGun/CompMultiTurretGun.cs index cb2077b4..ee05d3b1 100644 --- a/Source/WulaFallenEmpire/Pawn_Comps/MultiTurretGun/CompMultiTurretGun.cs +++ b/Source/WulaFallenEmpire/Pawn_Comps/MultiTurretGun/CompMultiTurretGun.cs @@ -48,9 +48,9 @@ namespace WulaFallenEmpire private int lastAttackTargetTick; // 集中火力目标 - private static LocalTargetInfo focusTarget = LocalTargetInfo.Invalid; - private static int lastFocusSetTick = 0; - private static Thing lastFocusPawn = null; + public static LocalTargetInfo focusTarget = LocalTargetInfo.Invalid; + public static int lastFocusSetTick = 0; + public static Thing lastFocusPawn = null; // Gizmo 缓存 private Command_Toggle cachedGizmo; @@ -278,8 +278,8 @@ namespace WulaFallenEmpire } } } - - private void TryAcquireTarget() + + public void TryAcquireTarget() { // 1. 首先检查是否有集中火力目标且可以对其开火 if (focusTarget.IsValid && focusTarget.Thing != null && focusTarget.Thing.Spawned) @@ -690,7 +690,7 @@ namespace WulaFallenEmpire if (IsMasterTurret) { // 如果有集中火力目标,添加清除按钮 - if (focusTarget.IsValid && lastFocusPawn == parent) + if (focusTarget.IsValid && focusTarget != null && lastFocusPawn == parent) { cachedFocusGizmo.defaultLabel = "Wula_ClearFocus".Translate(); cachedFocusGizmo.defaultDesc = "Wula_ClearFocusDesc".Translate(); @@ -713,7 +713,7 @@ namespace WulaFallenEmpire private void ShowTargetSelectMenu() { // 如果已经有集中火力目标,清除它 - if (focusTarget.IsValid && lastFocusPawn == parent) + if (focusTarget.IsValid && focusTarget != null && lastFocusPawn == parent) { focusTarget = LocalTargetInfo.Invalid; return; diff --git a/Source/WulaFallenEmpire/Verb/Verb_RangeChecker.cs b/Source/WulaFallenEmpire/Verb/Verb_RangeChecker.cs new file mode 100644 index 00000000..a9632de3 --- /dev/null +++ b/Source/WulaFallenEmpire/Verb/Verb_RangeChecker.cs @@ -0,0 +1,237 @@ +// File: Verb_RangeChecker.cs +using RimWorld; +using System.Collections.Generic; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + /// + /// 用于距离判断的Verb,不发射任何射弹,不造成伤害,仅用于距离计算和AI判断 + /// 当发射成功时,会设置Pawn身上所有Comp_MultiTurretGun的focusTarget为目标 + /// + public class Verb_RangeChecker : Verb_LaunchProjectile + { + 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; + } + + if (base.EquipmentSource != null) + { + base.EquipmentSource.GetComp()?.Notify_ProjectileLaunched(); + base.EquipmentSource.GetComp()?.UsedOnce(); + } + + lastShotTick = Find.TickManager.TicksGame; + Thing manningPawn = caster; + Thing equipmentSource = base.EquipmentSource; + CompMannable compMannable = caster.TryGetComp(); + 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(); + } + projectile2.extraDamages.AddRange(item.extraDamages); + } + } + } + + 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; + } + + /// + /// 模拟射击成功的情况 + /// + private bool SimulateShotSuccess(Vector3 drawPos, IntVec3 targetCell, LocalTargetInfo target, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null) + { + // 这里不实际发射射弹,只返回成功 + // 销毁之前创建的射弹对象,因为我们不需要它 + return true; + } + + /// + /// 模拟射击成功的情况(带目标) + /// + private bool SimulateShotSuccess(Vector3 drawPos, Thing target, LocalTargetInfo originalTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null) + { + // 这里不实际发射射弹,只返回成功 + // 销毁之前创建的射弹对象,因为我们不需要它 + return true; + } + + /// + /// 模拟最终射击成功的情况 + /// + private bool SimulateFinalShotSuccess(Vector3 drawPos, IntVec3 targetCell, LocalTargetInfo target, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null) + { + // 这里不实际发射射弹,只返回成功 + // 销毁之前创建的射弹对象,因为我们不需要它 + return true; + } + + /// + /// 更新Pawn身上所有Comp_MultiTurretGun的focusTarget + /// + private void UpdateTurretFocusTargets() + { + if (caster is Pawn pawn && pawn.Spawned) + { + // 获取Pawn身上所有的Comp_MultiTurretGun组件 + var turretComps = pawn.GetComps(); + + foreach (var turretComp in turretComps) + { + // 设置集中火力目标 + Comp_MultiTurretGun.focusTarget = currentTarget; + Comp_MultiTurretGun.lastFocusSetTick = Find.TickManager.TicksGame; + Comp_MultiTurretGun.lastFocusPawn = pawn; + + // 强制炮塔立即重新索敌,以便它们能检测到新的集中火力目标 + turretComp.TryAcquireTarget(); + } + } + } + } + + /// + /// 用于距离判断的Verb属性 + /// + public class VerbProperties_RangeChecker : VerbProperties + { + public VerbProperties_RangeChecker() + { + verbClass = typeof(Verb_RangeChecker); + + // 默认设置为不发射射弹 + defaultProjectile = null; + } + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 8f87a12f..c32753b3 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -97,6 +97,7 @@ + @@ -105,6 +106,7 @@ +