refactor: 密度阈值统一在引擎检查(ammo.EffectiveConcentration),去掉三个模型的硬编码

- SimulationEngine: 密度<EffectiveConcentration则跳过损伤
- InertGas/ActiveMaterial/ActiveFuel 移除各自的硬编码阈值
- CloudExpansionModel新增TurbulentRadius属性
- DefaultAmmunition ActiveMaterial EffectiveConcentration 0.0002→0.0001
This commit is contained in:
tian 2026-06-13 18:24:27 +08:00
parent cc3c7199c0
commit 1f092e8647
8 changed files with 16 additions and 13 deletions

View File

@ -27,7 +27,7 @@
"EdgeDensity": 0.2,
"InitialTemperature": 2400.0,
"BuoyancyFactor": 0.6,
"EffectiveConcentration": 0.0002,
"EffectiveConcentration": 0.0001,
"MaxRadius": 80.0,
"MaxDuration": 90.0,
"SourceStrength": 12.0,

View File

@ -14,10 +14,7 @@ namespace CounterDrone.Core.Algorithms
AerosolType aerosolType, float cloudDensity, float exposureTime, float deltaTime)
{
if (aerosolType != AerosolType.ActiveFuel) return 0f;
if (cloudDensity < EffectiveThreshold) return 0f;
// 伤害 = 基础速率 × e^(暴露时间 × 因子) × deltaTime
// 在云团中待得越久伤害指数增长
var exponential = (float)System.Math.Exp(exposureTime * ExpFactor);
var damage = BaseRate * exponential * deltaTime;

View File

@ -15,9 +15,7 @@ namespace CounterDrone.Core.Algorithms
AerosolType aerosolType, float cloudDensity, float exposureTime, float deltaTime)
{
if (aerosolType != AerosolType.ActiveMaterial) return 0f;
if (cloudDensity < TriggerThreshold) return 0f;
// 喷气发动机高温触发爆燃,更敏感
if (!_triggered)
{
_triggered = true;

View File

@ -17,6 +17,12 @@ namespace CounterDrone.Core.Algorithms
/// <summary>Phase 1 爆轰初始半径 (m)</summary>
public float InitialRadius => 3.3f * (float)Math.Pow(Math.Max(0.01, (float)_ammo.BurstChargeKg), 0.32f);
/// <summary>Phase 2 结束时的有效半径30s 湍流膨胀)</summary>
public float TurbulentRadius => RadiusAt(30f);
/// <summary>Phase 2 边界时间</summary>
public float Phase2Duration => 30f;
/// <summary>湍流膨胀系数 k</summary>
public float TurbulentExpansionK => (float)_ammo.TurbulentExpansionK;
/// <summary>指定时刻湍流膨胀半径 R(t) = R₀ + k√t</summary>
@ -64,7 +70,7 @@ namespace CounterDrone.Core.Algorithms
/// <summary>覆盖指定距离需要的云团数量(间距=2R</summary>
public int RoundsNeeded(float requiredCoverage)
{
float R = RadiusAt(30f);
float R = TurbulentRadius;
float spacing = 2f * R;
return Math.Max(1, (int)Math.Ceiling(requiredCoverage / spacing));
}

View File

@ -33,7 +33,7 @@ namespace CounterDrone.Core.Algorithms
InitialRadius = 5.0,
CoreDensity = 2.0, EdgeDensity = 0.2,
InitialTemperature = 2400, BuoyancyFactor = 0.6,
EffectiveConcentration = 0.0002,
EffectiveConcentration = 0.0001,
MaxRadius = 80.0, MaxDuration = 90.0,
SourceStrength = 12.0,
BurstChargeKg = 4.0, TurbulentExpansionK = 4.0,

View File

@ -396,7 +396,12 @@ namespace CounterDrone.Core.Algorithms
var mid = ThreatMidpoint(threat);
var cloudModel = new CloudExpansionModel(ammo, env);
float expansionTime = cloudModel.TimeToReach(cloudModel.RadiusAt(30f));
float expansionTime = cloudModel.TimeToReach(cloudModel.TurbulentRadius);
// 密度检查:云团在膨胀时间后密度是否仍达标
float densityAtPassage = cloudModel.DensityAt(expansionTime);
if (densityAtPassage < (float)ammo.EffectiveConcentration)
return events; // 云团到达时已稀释失效
// 编队 Y 偏移:按车道分布
float laneSpacingZ = yLanes > 1 ? formationWidth / (yLanes - 1) : 0f;

View File

@ -13,9 +13,6 @@ namespace CounterDrone.Core.Algorithms
AerosolType aerosolType, float cloudDensity, float exposureTime, float deltaTime)
{
if (aerosolType != AerosolType.InertGas) return 0f;
if (cloudDensity < EffectiveThreshold) return 0f;
// 活塞发动机对惰性气体最敏感
var sensitivity = powerType == PowerType.Piston ? 1.5f : 1.0f;
return DamageRate * sensitivity * deltaTime;
}

View File

@ -253,7 +253,7 @@ namespace CounterDrone.Core.Simulation
var dist = (float)System.Math.Sqrt(dx * dx + dy * dy + dz * dz);
bool inside = dist <= cloud.Dispersion.EffectiveRadius;
_hitLog.AppendLine($"{drone.PosX:F1},{drone.PosY:F1},{cloud.Dispersion.Center.X:F1},{cloud.Dispersion.Center.Y:F1},{dist:F1},{cloud.Dispersion.EffectiveRadius:F1},{inside}");
if (inside)
if (inside && cloud.Dispersion.CoreDensity >= (float)_ammoSpec.EffectiveConcentration)
{
drone.ExposureTime += scaledDt;
var dmg = _damageModel.CalculateDamage(drone.TargetType, drone.PowerType, cloud.AerosolType, cloud.Dispersion.CoreDensity, drone.ExposureTime, scaledDt);