This commit is contained in:
2026-03-03 17:30:02 +08:00
parent e1dea4059c
commit 14c3654846
10 changed files with 711 additions and 86 deletions

View File

@@ -372,4 +372,75 @@
<li Class="HediffCompProperties_DisappearsOnDeath" />
</comps>
</HediffDef>
<HediffDef>
<defName>Wula_TerrainBlocked</defName>
<label>地形阻挡</label>
<description>虽然乌拉族的大部分构装体采用反重力悬浮可以无视崎岖地表,但是其庞大的身躯依然会导致其在狭窄地形中难以行动。</description>
<hediffClass>HediffWithComps</hediffClass>
<maxSeverity>1</maxSeverity>
<isBad>false</isBad>
<stages>
<li>
<minSeverity>0.1</minSeverity>
<statFactors>
<MoveSpeed>0.9</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.2</minSeverity>
<statFactors>
<MoveSpeed>0.8</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.3</minSeverity>
<statFactors>
<MoveSpeed>0.7</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.4</minSeverity>
<statFactors>
<MoveSpeed>0.6</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.5</minSeverity>
<statFactors>
<MoveSpeed>0.5</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.6</minSeverity>
<statFactors>
<MoveSpeed>0.4</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.7</minSeverity>
<statFactors>
<MoveSpeed>0.3</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.8</minSeverity>
<statFactors>
<MoveSpeed>0.2</MoveSpeed>
</statFactors>
</li>
<li>
<minSeverity>0.9</minSeverity>
<statFactors>
<MoveSpeed>0.1</MoveSpeed>
</statFactors>
</li>
</stages>
<comps>
<li Class="WulaFallenEmpire.HediffCompProperties_TerrainBlocked">
<maxSpeedPenalty>0.75</maxSpeedPenalty>
<checkIntervalTicks>60</checkIntervalTicks>
</li>
</comps>
</HediffDef>
</Defs>

View File

@@ -204,10 +204,13 @@
<weaponMoney>99999~99999</weaponMoney>
<controlGroupPortraitZoom>0.7</controlGroupPortraitZoom>
<weaponTags>
<li>Wula_AI_Heavy_Panzer_Weapon</li>
</weaponTags>
</PawnKindDef>
<PawnKindDef ParentName="HeavyMechanoidKind">
<defName>Wula_AI_Rocket_Panzer</defName> <!-- 修改了defName以避免冲突 -->
<label>HRp-3"喷火战车"</label>
<label>HRp-3"炎霖"</label>
<race>Wula_AI_Rocket_Panzer</race>
<combatPower>500</combatPower>
<allowInMechClusters>false</allowInMechClusters>
@@ -239,7 +242,7 @@
<controlGroupPortraitZoom>0.7</controlGroupPortraitZoom>
<weaponTags>
<li>Wula_AI_Heavy_Panzer_Weapon</li>
<li>Wula_AI_Rocket_Panzer_Weapon</li>
</weaponTags>
</PawnKindDef>
<PawnKindDef ParentName="HeavyMechanoidKind">

View File

@@ -438,14 +438,14 @@
<damageDef>WULA_RW_Handle_Cannon_Burn</damageDef>
<damageAmountBase>40</damageAmountBase>
<speed>130</speed>
<armorPenetrationBase>1</armorPenetrationBase>
<armorPenetrationBase>1.5</armorPenetrationBase>
<stoppingPower>1</stoppingPower>
</projectile>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>Wula_AI_Heavy_Panzer_Main_Weapon</defName>
<label>SDm-2"月长石"</label>
<description>HAp-6"战车"车体正面的突击炮,射程很短并且只能在静止状态开火,但是威力巨大,专门用于对付坚固的工事和成片的人群</description>
<label>目标标定器</label>
<description>HAp-6"巨戟"车体上的测距器,可以确保其炮塔在可以开火的最佳距离,被其瞄准的目标会成为炮塔的优先攻击目标</description>
<tickerType>Normal</tickerType>
<techLevel>Spacer</techLevel>
<tradeability>None</tradeability>
@@ -466,87 +466,43 @@
<AccuracyShort>1</AccuracyShort>
<AccuracyMedium>1</AccuracyMedium>
<AccuracyLong>1</AccuracyLong>
<RangedWeapon_Cooldown>3.5</RangedWeapon_Cooldown>
<RangedWeapon_Cooldown>0.1</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<verbClass>WulaFallenEmpire.Verb_RangeChecker</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<defaultProjectile>Bullet_Wula_AI_Heavy_Panzer_Main_Weapon</defaultProjectile>
<warmupTime>2</warmupTime>
<range>21</range>
<defaultProjectile>Bullet_ChargeRifle</defaultProjectile>
<minRange>5.9</minRange>
<range>60</range>
<warmupTime>0.2</warmupTime>
<burstShotCount>1</burstShotCount>
<forcedMissRadius>1</forcedMissRadius>
<soundCast>RocketswarmLauncher_Fire</soundCast>
<soundCastTail>GunTail_Heavy</soundCastTail>
<!-- <soundCast>RocketswarmLauncher_Fire</soundCast>
<soundCastTail>GunTail_Heavy</soundCastTail> -->
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<Steel>200</Steel>
<ComponentIndustrial>12</ComponentIndustrial>
<Steel>1</Steel>
</costList>
<weaponTags Inherit="False">
<li>Wula_AI_Heavy_Panzer_Weapon</li>
</weaponTags>
<thingCategories Inherit="False"/>
<comps>
<!-- <li Class="WulaFallenEmpire.CompProperties_MechOnlyWeapon">
<li Class="WulaFallenEmpire.CompProperties_MechOnlyWeapon">
<allowedMechRaces>
<li>Wula_AI_Heavy_Panzer</li>
</allowedMechRaces>
</li> -->
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_Wula_AI_Heavy_Panzer_Main_Weapon</defName>
<label>月长石炮弹</label>
<drawerType>RealtimeOnly</drawerType>
<graphicData>
<texPath>Wula/Projectile/WULA_Shrapnel</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>(2,2)</drawSize>
</graphicData>
<thingClass>WulaFallenEmpire.Projectile_NorthArcTrail</thingClass>
<tickerType>Normal</tickerType>
<neverMultiSelect>True</neverMultiSelect>
<projectile>
<damageDef>WULA_GiantBomb</damageDef>
<damageAmountBase>65</damageAmountBase>
<speed>25</speed>
<explosionRadius>6</explosionRadius>
<armorPenetrationBase>1.5</armorPenetrationBase>
<flyOverhead>true</flyOverhead>
<soundHitThickRoof>Artillery_HitThickRoof</soundHitThickRoof>
<soundExplode>MortarBomb_Explode</soundExplode>
<soundImpactAnticipate>MortarRound_PreImpact</soundImpactAnticipate>
<soundAmbient>MortarRound_Ambient</soundAmbient>
<stoppingPower>10</stoppingPower>
<preExplosionSpawnSingleThingDef>Filth_BlastMark</preExplosionSpawnSingleThingDef>
</projectile>
<modExtensions>
<li Class="WulaFallenEmpire.NorthArcModExtension">
<northOffsetDistance>5</northOffsetDistance>
<curveSteepness>1.0</curveSteepness>
<useArcTrajectory>true</useArcTrajectory>
</li>
<li Class="WulaFallenEmpire.TrackingBulletDef">
<tailFleckDef>WULA_Smoke_Tail</tailFleckDef>
<fleckMakeFleckTickMax>5</fleckMakeFleckTickMax>
<fleckDelayTicks>1</fleckDelayTicks>
<fleckMakeFleckNum>1~2</fleckMakeFleckNum>
<fleckScale>0.5~1.0</fleckScale>
<fleckSpeed>0.1~0.3</fleckSpeed>
<fleckAngle>-30~30</fleckAngle>
</li>
</modExtensions>
</ThingDef>
<ThingDef ParentName="BaseWeaponTurret">
<defName>Wula_AI_Rocket_Panzer_Turret_Weapon</defName>
<label>FRt-1"火欧泊"</label>
<description>HRp-3"喷火战车"的炮塔,可以一次性发射大量的火箭弹。</description>
<description>HRp-3"炎霖"的炮塔,可以一次性发射大量的火箭弹。</description>
<tradeability>None</tradeability>
<destroyOnDrop>true</destroyOnDrop>
<techLevel>Ultra</techLevel>
@@ -565,7 +521,7 @@
</statBases>
<verbs>
<li>
<verbClass>Verb_Shoot</verbClass>
<verbClass>WulaFallenEmpire.Verb_TurretOffestShoot</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<defaultProjectile>Bullet_Wula_AI_Rocket_Panzer_Turret_Weapon</defaultProjectile>
<warmupTime>0</warmupTime>
@@ -581,6 +537,14 @@
<muzzleFlashScale>18</muzzleFlashScale>
</li>
</verbs>
<modExtensions>
<li Class="WulaFallenEmpire.ModExtension_ShootWithOffset">
<offsets>
<li>(0.62, -4.1)</li>
<li>(-0.62, -4.1)</li>
</offsets>
</li>
</modExtensions>
</ThingDef>
<ThingDef ParentName="BaseBullet">
<defName>Bullet_Wula_AI_Rocket_Panzer_Turret_Weapon</defName>
@@ -610,7 +574,7 @@
</projectile>
<modExtensions>
<li Class="WulaFallenEmpire.NorthArcModExtension">
<northOffsetDistance>6</northOffsetDistance>
<northOffsetDistance>18</northOffsetDistance>
<curveSteepness>1.0</curveSteepness>
<useArcTrajectory>true</useArcTrajectory>
</li>
@@ -625,6 +589,64 @@
</li>
</modExtensions>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>Wula_AI_Rocket_Panzer_Main_Weapon</defName>
<label>目标标定器</label>
<description>HRp-3"炎霖"车体上的测距器,可以确保其炮塔在可以开火的最佳距离,被其瞄准的目标会成为炮塔的优先攻击目标。</description>
<tickerType>Normal</tickerType>
<techLevel>Spacer</techLevel>
<tradeability>None</tradeability>
<destroyOnDrop>true</destroyOnDrop>
<uiIconPath>Wula/Projectile/WULA_Shrapnel</uiIconPath>
<graphicData>
<texPath>Wula/Weapon/WULA_Weapon_Empty</texPath>
<graphicClass>Graphic_Single</graphicClass>
<drawSize>1.35</drawSize>
</graphicData>
<soundInteract>Interact_Rifle</soundInteract>
<recipeMaker Inherit="False" IsNull="True"/>
<statBases>
<WorkToMake>2500</WorkToMake>
<!-- <MarketValue>370</MarketValue> -->
<Mass>8</Mass>
<AccuracyTouch>1</AccuracyTouch>
<AccuracyShort>1</AccuracyShort>
<AccuracyMedium>1</AccuracyMedium>
<AccuracyLong>1</AccuracyLong>
<RangedWeapon_Cooldown>0.1</RangedWeapon_Cooldown>
</statBases>
<verbs>
<li>
<verbClass>WulaFallenEmpire.Verb_RangeChecker</verbClass>
<hasStandardCommand>true</hasStandardCommand>
<defaultProjectile>Bullet_ChargeRifle</defaultProjectile>
<minRange>12</minRange>
<range>79</range>
<warmupTime>0.2</warmupTime>
<burstShotCount>1</burstShotCount>
<requireLineOfSight>false</requireLineOfSight>
<!-- <soundCast>RocketswarmLauncher_Fire</soundCast>
<soundCastTail>GunTail_Heavy</soundCastTail> -->
<targetParams>
<canTargetLocations>true</canTargetLocations>
</targetParams>
</li>
</verbs>
<costList Inherit="False">
<Steel>1</Steel>
</costList>
<weaponTags Inherit="False">
<li>Wula_AI_Rocket_Panzer_Weapon</li>
</weaponTags>
<thingCategories Inherit="False"/>
<comps>
<li Class="WulaFallenEmpire.CompProperties_MechOnlyWeapon">
<allowedMechRaces>
<li>Wula_AI_Rocket_Panzer</li>
</allowedMechRaces>
</li>
</comps>
</ThingDef>
<ThingDef ParentName="BaseHumanMakeableGun">
<defName>Wula_Psi_Titan_Beam</defName>

View File

@@ -81,6 +81,8 @@
<ArmorRating_Sharp>1</ArmorRating_Sharp>
<ArmorRating_Blunt>1</ArmorRating_Blunt>
<ArmorRating_Heat>2</ArmorRating_Heat>
<WULA_MechArmor>3</WULA_MechArmor>
</statBases>
<costList Inherit="False">
<WULA_Alloy>300</WULA_Alloy>
@@ -118,7 +120,7 @@
<turretDef>Wula_AI_Heavy_Panzer_Turret_Weapon</turretDef>
<traverseSpeed>20</traverseSpeed>
<aimTicks>0</aimTicks>
<idleRotationSpeed>3</idleRotationSpeed>
<idleRotationSpeed>6</idleRotationSpeed>
<smoothRotation>true</smoothRotation>
<resetCooldownTime>1.2</resetCooldownTime>
<!-- <angleOffset>-90</angleOffset> -->
@@ -328,6 +330,12 @@
<knockbackFlyerDef>PawnFlyer</knockbackFlyerDef>
<!-- <flightEffecterDef>FlyerTakeoff</flightEffecterDef> -->
<landingSound>PawnFlyerLand</landingSound>
<!-- 地形阻挡配置 -->
<narrowTerrainBlocked>true</narrowTerrainBlocked>
<maxBlockPenalty>1</maxBlockPenalty>
<terrainCheckInterval>60</terrainCheckInterval>
<blockedHediff>Wula_TerrainBlocked</blockedHediff>
<!-- 调试 -->
<enableDebugLogging>false</enableDebugLogging>
@@ -338,8 +346,8 @@
</ThingDef>
<ThingDef ParentName="Wula_MechunitBase">
<defName>Wula_AI_Rocket_Panzer</defName>
<label>HRp-3"喷火战车"</label>
<description>乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,拥有车体臼炮和两具可以发射大量燃烧火箭弹的转轮导弹巢</description>
<label>HRp-3"炎霖"</label>
<description>乌拉帝国的中型战争机械,以悬浮的方式穿梭于战场之上,可以在远距离上使用火箭弹巢发射漫天的弹幕,用纯粹的火力淹没敌方集群</description>
<statBases>
<MoveSpeed>2</MoveSpeed>
<EnergyShieldEnergyMax>2</EnergyShieldEnergyMax>
@@ -351,6 +359,8 @@
<ArmorRating_Sharp>1</ArmorRating_Sharp>
<ArmorRating_Blunt>1</ArmorRating_Blunt>
<ArmorRating_Heat>2</ArmorRating_Heat>
<WULA_MechArmor>3</WULA_MechArmor>
</statBases>
<costList Inherit="False">
<WULA_Alloy>300</WULA_Alloy>
@@ -390,7 +400,7 @@
<aimTicks>0</aimTicks>
<idleRotationSpeed>8</idleRotationSpeed>
<smoothRotation>true</smoothRotation>
<resetCooldownTime>10</resetCooldownTime>
<resetCooldownTime>12.2</resetCooldownTime>
<!-- <angleOffset>-90</angleOffset> -->
<!-- <angleOffset>-90</angleOffset> -->
<renderNodeProperties>
@@ -463,7 +473,7 @@
<repairEffect>ConstructMetal</repairEffect>
</li>
<li Class="WulaFallenEmpire.CompProperties_MechInherentWeapon">
<weaponDef>Wula_AI_Heavy_Panzer_Main_Weapon</weaponDef>
<weaponDef>Wula_AI_Rocket_Panzer_Main_Weapon</weaponDef>
</li>
<li Class="WulaFallenEmpire.CompProperties_MechDefaultPilot">
<enableForNonPlayerFaction>true</enableForNonPlayerFaction>

View File

@@ -0,0 +1,115 @@
using RimWorld;
using Verse;
using UnityEngine;
namespace WulaFallenEmpire
{
/// <summary>
/// 地形阻挡Hediff组件用于调整移动速度
/// </summary>
public class HediffComp_TerrainBlocked : HediffComp
{
public HediffCompProperties_TerrainBlocked Props => (HediffCompProperties_TerrainBlocked)props;
/// <summary>
/// 当前地形阻挡严重度0-1之间
/// </summary>
public float currentBlockSeverity = 0f;
/// <summary>
/// 上一次更新时间ticks
/// </summary>
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<CompHighSpeedCollision>();
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;
}
/// <summary>
/// 获取移动速度乘数
/// </summary>
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);
}
}
/// <summary>
/// 地形阻挡Hediff组件属性
/// </summary>
public class HediffCompProperties_TerrainBlocked : HediffCompProperties
{
/// <summary>
/// 最大速度惩罚0-1之间
/// </summary>
public float maxSpeedPenalty = 0.5f;
/// <summary>
/// 检查间隔ticks - 降低判断频率
/// </summary>
public int checkIntervalTicks = 60;
public HediffCompProperties_TerrainBlocked()
{
compClass = typeof(HediffComp_TerrainBlocked);
}
}
}

View File

@@ -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;
}
}
/// <summary>
/// 更新地形阻挡状态
/// </summary>
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}");
}
}
/// <summary>
/// 检查单元格是否被不可通行建筑占据
/// </summary>
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;
}
/// <summary>
/// 计算阻挡严重度
/// </summary>
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;
}
/// <summary>
/// 平滑过渡
/// </summary>
private float SmoothTransition(float current, float target, float speed)
{
if (Mathf.Abs(current - target) < 0.01f)
return target;
return Mathf.Lerp(current, target, speed);
}
/// <summary>
/// 更新阻挡Hediff
/// </summary>
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;
}
/// <summary>
/// 获取当前地形阻挡严重度供HediffComp使用
/// </summary>
public float GetCurrentTerrainBlockSeverity()
{
return currentTerrainBlockSeverity;
}
/// <summary>
/// 处理每帧逻辑
/// </summary>
@@ -846,7 +990,28 @@ namespace WulaFallenEmpire
/// 绘制速度历史图
/// </summary>
public bool debugDrawSpeedHistory = false;
// === 狭窄地形阻挡配置 ===
/// <summary>
/// 是否启用狭窄地形阻挡
/// </summary>
public bool narrowTerrainBlocked = false;
/// <summary>
/// 最高阻挡减益值0-1之间
/// </summary>
public float maxBlockPenalty = 0.5f;
/// <summary>
/// 地形检查间隔ticks
/// </summary>
public int terrainCheckInterval = 60;
/// <summary>
/// 阻挡减益Hediff定义
/// </summary>
public HediffDef blockedHediff;
public CompProperties_HighSpeedCollision()
{
compClass = typeof(CompHighSpeedCollision);

View File

@@ -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;

View File

@@ -0,0 +1,237 @@
// File: Verb_RangeChecker.cs
using RimWorld;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace WulaFallenEmpire
{
/// <summary>
/// 用于距离判断的Verb不发射任何射弹不造成伤害仅用于距离计算和AI判断
/// 当发射成功时会设置Pawn身上所有Comp_MultiTurretGun的focusTarget为目标
/// </summary>
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<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);
}
}
}
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)
{
// 这里不实际发射射弹,只返回成功
// 销毁之前创建的射弹对象,因为我们不需要它
return true;
}
/// <summary>
/// 模拟最终射击成功的情况
/// </summary>
private bool SimulateFinalShotSuccess(Vector3 drawPos, IntVec3 targetCell, LocalTargetInfo target, ProjectileHitFlags hitFlags, bool preventFriendlyFire, Thing equipmentSource, ThingDef targetCoverDef = null)
{
// 这里不实际发射射弹,只返回成功
// 销毁之前创建的射弹对象,因为我们不需要它
return true;
}
/// <summary>
/// 更新Pawn身上所有Comp_MultiTurretGun的focusTarget
/// </summary>
private void UpdateTurretFocusTargets()
{
if (caster is Pawn pawn && pawn.Spawned)
{
// 获取Pawn身上所有的Comp_MultiTurretGun组件
var turretComps = pawn.GetComps<Comp_MultiTurretGun>();
foreach (var turretComp in turretComps)
{
// 设置集中火力目标
Comp_MultiTurretGun.focusTarget = currentTarget;
Comp_MultiTurretGun.lastFocusSetTick = Find.TickManager.TicksGame;
Comp_MultiTurretGun.lastFocusPawn = pawn;
// 强制炮塔立即重新索敌,以便它们能检测到新的集中火力目标
turretComp.TryAcquireTarget();
}
}
}
}
/// <summary>
/// 用于距离判断的Verb属性
/// </summary>
public class VerbProperties_RangeChecker : VerbProperties
{
public VerbProperties_RangeChecker()
{
verbClass = typeof(Verb_RangeChecker);
// 默认设置为不发射射弹
defaultProjectile = null;
}
}
}

View File

@@ -97,6 +97,7 @@
<Compile Include="HediffComp\WULA_RegenerateBackstory\HediffComp_RegenerateBackstory.cs" />
<Compile Include="HediffComp\WULA_SwitchableHediff\HediffCompProperties_SwitchableHediff.cs" />
<Compile Include="HediffComp\WULA_SyncedWithMech\HediffCompProperties_SyncedWithMech.cs" />
<Compile Include="HediffComp\WULA_TerrainBlocked\HediffComp_TerrainBlocked.cs" />
<Compile Include="HediffComp\WULA_TimedExplosion\HediffComp_TimedExplosion.cs" />
<Compile Include="ITab\ITab_MechSkills.cs" />
<Compile Include="MentalState\MentalState_MechNoPilot.cs" />
@@ -105,6 +106,7 @@
<Compile Include="Pawn_Comps\MechCrewHolder\CompProperties_MechCrewHolder.cs" />
<Compile Include="Pawn_Comps\PawnRenderExtra\Comp_PawnRenderExtra.cs" />
<Compile Include="Pawn_Comps\HighSpeedCollision\CompHighSpeedCollision.cs" />
<Compile Include="Verb\Verb_RangeChecker.cs" />
<Compile Include="Verb\Verb_TurretOffestShoot.cs" />
<Compile Include="Work\BoardMech\FloatMenuOptionProvider_BoardMech.cs" />
<Compile Include="Work\BoardMech\JobDriver_BoardMech.cs" />