-- 迎撃ミサイル多目標同時照準プログラム ver 1.1 2018/01/06 修正版 -- 作者:KD -- 使用条件: -- ・改造・配布は自由です。 -- ・作者はこのソースコードに関してなんら責任を負いません。自己責任で使用してください。 -- 使い方 -- 1. AI Mainframeを設置する -- 2. 機能するMunition WarnerまたはPassive RaderやPassive Sonarを設置する -- 3. ミサイルを設置。発射台にLUA Tranceiver、ミサイルにMissile InterceptorとLUA Receiverを取り付ける -- これらの内どれか一つでも欠けている場合は操作されない -- 4. 適当な場所にLUA Boxを置いて中にこのコードを書き込む -- 5. 手動、ACB、AMCCなどの方法で迎撃ミサイルを発射する -- 6. 敵を捕捉できていればコードが動作して自動で多目標に追尾する -- 7. 以下の設定項目を変更すれば挙動を変えられる -- 以下設定項目 AIIndex = -1 -- 索敵AIのインデックス("-1"ならすべてのAIを使う) PNMode = true -- "true"なら比例航法誘導、"false"なら標準誘導 PNGain = 10 -- 比例航法の比例ゲイン conf = { -- 迎撃ミサイル(迎撃弾)の標的を決定するパラメータ(AMCCの設定項目とほぼ同じ) -- (minRange) 最低射程(例:"50"ならば自艦から50m以下の標的は狙わない) -- (maxRange) 最大射程(例:"1000"ならば自艦から1000m以上の標的は狙わない) -- (maxRange2) 最大射程2(例:"1000"ならば迎撃弾から1000m以上の標的は狙わない) -- (minAlt) 最低高度(例:"-10"なら高度-10m以下の標的は狙わない) -- (maxAlt) 最大高度(例:"500"なら高度500m以上の標的は狙わない) minRange = 50 -- Minimum range to target ,maxRange = 1500 -- Maximum range to target ,maxRange2 = 1500 -- Maximum range from interceptor to target ,minAlt = -10 -- Minimum altitude to target ,maxAlt = 500 -- Maximum altitude to target -- (a) 許容照準数(例:"1"なら他に1つの迎撃弾が標的を照準していても優先度が減らない) -- (b) 同一目標への照準による優先度減少度 -- (c) 許容射角(例:"5"ならば迎撃弾から前方半径5度以内の標的で優先度の減少なし) -- (d) 射角による優先度減少度 -- (e) 許容入射角(例:"5"ならば自艦への標的ミサイルの入射角が半径5度以内で優先度減少なし) -- (f) 入射角による優先度減少度 -- (g) 許容射程(例:"200"ならば自艦から200m以内の標的は優先度減少なし) -- (h) 射程による優先度減少度 -- (i) 許容速度(例:"100"ならば100m/s以下の速度の標的は優先度減少なし) -- (j) 速度による優先度減少度 -- (k) 迎撃弾許容射程(例:"200"ならば迎撃弾から200m以内の標的は優先度減少なし) -- (l) 迎撃弾からの射程による優先度減少度 ,a = 0 -- Acceptable targets ,b = 1.8 -- Priority loss per extra targets ,c = 5 -- Acceptable angle to engage (0-180) ,d = 0.07 -- Priority loss per extra angle ,e = 1 -- Acceptable miss angle (0-180) ,f = 0.35 -- Priority loss per miss angle ,g = 200 -- Acceptable range ,h = 0.01 -- Priority loss per meter ,i = 0 -- Acceptable speed ,j = 0 -- Priority loss per speed ,k = 260 -- Acceptable missile range ,l = 0.01 -- Priority loss per missile range } -- 以上設定項目 function Main(I) -- AIの処理 local AIinc, AInum if(AIIndex == -1) then AIinc = 0 AInum = I:GetNumberOfMainframes() else AIinc = AIIndex AInum = AIIndex+1 end -- 敵ミサイル処理 local eMisData = {} for j=AIinc, AInum-1 do for i=1, I:GetNumberOfWarnings(j) do local inf = I:GetMissileWarning(j, i-1) local tv = I:GetConstructCenterOfMass() - inf.Position if(tv.magnitude > conf.minRange and tv.magnitude < conf.maxRange and inf.Position.y > conf.minAlt and inf.Position.y < conf.maxAlt and not isMissileDuplicated(eMisData, inf.Id)) then -- 条件を満たした標的をリストに入れる eMisData[#eMisData+1] = { info = inf ,targeted = 0 ,angle = calcVectorAngle(tv, inf.Velocity) ,range = tv.magnitude ,speed = inf.Velocity.magnitude ,AI = j ,index = i-1 } --I:Log("T#"..i.."-ID:"..inf.Id) end end end -- 迎撃ミサイル処理 for i=1, I:GetLuaTransceiverCount() do for j=1, I:GetLuaControlledMissileCount(i-1) do if(I:IsLuaControlledMissileAnInterceptor(i-1, j-1)) then local info = I:GetLuaControlledMissileInfo(i-1, j-1) -- 迎撃対象を決定 calcMissilePriority(eMisData, info) local target = getPriorityMissile(eMisData) if(target) then -- 迎撃対象が存在する if(j == I:GetLuaControlledMissileCount(i-1)) then -- 古い迎撃弾は捕捉数に含めない eMisData[target].targeted = eMisData[target].targeted + 1 end if(PNMode) then -- 比例航法の処理 I:SetLuaControlledMissileInterceptorStandardGuidanceOnOff(i-1, j-1, false) local tgtInfo = eMisData[target].info -- 目標と迎撃弾の距離 local range = tgtInfo.Position - info.Position -- 目標と迎撃弾の速度差 local vr = tgtInfo.Velocity - info.Velocity -- 角速度を求める local rv = Vector3.Cross(range, vr)/range.magnitude^2 -- 偏差ベクトル local va = Vector3.Cross(vr, rv)*PNGain -- 迎撃座標を決定 local aimPoint = tgtInfo.Position + va I:SetLuaControlledMissileAimPoint(i-1, j-1, aimPoint.x, aimPoint.y, aimPoint.z) else -- 標準誘導 local tgt = eMisData[target] I:SetLuaControlledMissileInterceptorStandardGuidanceOnOff(i-1, j-1, true) I:SetLuaControlledMissileInterceptorTarget(i-1, j-1, tgt.AI, tgt.index) end else -- 目標が捕捉できず I:SetLuaControlledMissileInterceptorStandardGuidanceOnOff(i-1, j-1, false) -- 目標を失ったミサイルはその場に打ち上げる local aimPoint = info.Position + Vector3(0, 100, 0) I:SetLuaControlledMissileAimPoint(i-1, j-1, aimPoint.x, aimPoint.y, aimPoint.z) target = "xxx" end --I:Log("M#"..i.."-"..j.."-Target:"..target.."-ID:"..info.Id) end end end --I:LogToHud("接近中:"..#eMisData.."個") end function calcMissilePriority(t, m) -- 敵ミサイルの迎撃優先度を計算する for i=1, #t do local tv = t[i].info.Position - m.Position if(tv.magnitude < conf.maxRange2) then t[i].priority = Mathf.Max(0, t[i].targeted-conf.a)*conf.b + Mathf.Max(0, calcVectorAngle(tv, m.Velocity)-conf.c)*conf.d + Mathf.Max(0, t[i].angle-conf.e)*conf.f + Mathf.Max(0, t[i].range-conf.g)*conf.h + Mathf.Max(0, t[i].speed-conf.i)*conf.j + Mathf.Max(0, tv.magnitude-conf.k)*conf.l else -- 最大射程外の標的は狙わない t[i].priority = -1 end end end function getPriorityMissile(d) -- 最も優先して狙うミサイルを返す local p1, p2 for i=1, #d do if((not p1 or p1 > d[i].priority) and d[i].priority ~= -1) then p1 = d[i].priority p2 = i end end return p2, p1 end function isMissileDuplicated(d, n) -- ID"n"の標的が重複しているかどうかを返す for i=1, #d do if(d[i].info.Id == n) then return true end end return false end function calcVectorAngle(v1, v2) -- v1とv2のなす角を求める local f = Mathf.Sqrt(v1.x^2 +v1.y^2 +v1.z^2)*Mathf.Sqrt(v2.x^2 +v2.y^2 +v2.z^2) if(f == 0) then return 180 end -- 0除算防止 return Mathf.Acos((v1.x*v2.x +v1.y*v2.y +v1.z*v2.z)/f)*Mathf.Rad2Deg end function Update(I) I:ClearLogs() Main(I) end