Steamで配信している早期アクセスゲーム「From The Depths」の情報サイトです。日本語非対応のゲームなのでみんなで情報を載せあってプレイが捗るようにしましょう!


ミサイル/魚雷系

魚雷安全信管プログラム

単純な魚雷用の信管プログラムです。
※現環境では正常に動作しません。誰か直してくれると作成者は信じています。

前提条件
1.ミサイルPOTにLUAトランスミッタがくっついている
2.ミサイルの構成にLUAレシーバがある
3.メインフレームがある


で,この状態でLuaBoxに以下のコードを書き込む。

---
---
-- 魚雷制御ループ
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)
  seftySystem(I, missileInfo, selfPosition,transceiver, missile)
end

---
-- 自爆システム用の安全距離。これ以下の距離かつ下の時間経過で自爆する
seftyRange = 100

---
-- 自爆用の時間。上記同様
seftyOverTime = 20

---
-- 自爆システム
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function seftySystem(I, missileInfo, selfPosition,transceiver, missile)
  if missileInfo.Valid then
    if missileInfo.Range<seftyRange and missileInfo.TimeSinceLaunch>seftyOverTime then
      I:Log('execute self Detonation')
      I:Log("Range2:"..missileInfo.Range)
      I:Log("Time:"..missileInfo.TimeSinceLaunch)
      I:DetonateLuaControlledMissile(transceiver,missile)
    end
  end
end


---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  selfPosition = I:GetConstructCenterOfMass()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)
    end
  end
end

ロックオン追尾/近接信管

単純な追尾を行い、指定距離で爆発するミサイル・魚雷プログラムです。
垂直ミサイルにするなら、追尾開始を少しずらした方が良いかも。
メインフレームが認識する最寄りの敵へ追尾します。

前提条件
1.ミサイルPOTにLUAトランスミッタがくっついている
2.ミサイルの構成にLUAレシーバがある
3.メインフレームがある

---
-- 魚雷制御ループ
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)
  targetSystem(I, missileInfo, selfPosition,transceiver, missile)
end


---
-- 2点間計測
-- @param target1[1..3]: 開始位置
-- @param target2[1..3]: 終了位置
function calcRange(target1, target2)
  return math.sqrt((target1[1] - target2[1])^2 + (target1[2] - target2[2])^2 + (target1[3] - target2[3])^2)
end


---
-- 近接信管の距離
explodeRange = 0
---
-- 使うメインフレームブロックのIndex
useMainFrame = 0
---
-- 追尾/信管システム.
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function targetSystem(I, missileInfo, selfPosition,transceiver, missile)
  if I:GetNumberOfMainframes() == 0 or I:GetNumberOfTargets(useMainFrame) == 0 then
    return
  end
  
  --メインフレームの最優先ターゲットの情報取得 最優先の設定はAIカードで決定されてる
  target = I:GetTargetInfo(useMainFrame, 0)
  
  -- メインフレームの最優先ターゲットを取得し、ミサイルとの距離を取る
  targetRange = calcRange(target.Position, missileInfo.Position)
  
  --近接信管
  if targetRange < explodeRange then
  I:Log("execute Detonation System")
  I:DetonateLuaControlledMissile(transceiver,missile)
  end
  --誘導
  I:Log("execute targetSystem")
  I:SetLuaControlledMissileAimPoint(transceiver,missile,target.AimPointPosition[1], target.AimPointPosition[2],target.AimPointPosition[3])
end

---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  selfPosition = I:GetConstructCenterOfMass()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)    
    end
  end
end

ロックオン追尾/近接信管/予想誘導(潜水艦VLS対応)


ロックオン追尾、近接信管プログラムに、更にTargetPredictionGuidance機能を追加したもの。
また、潜水艦VLSのミサイルが安定して水上まで出る様になっている。

---
-- ミサイル制御ループ
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function lanuncherControl(I, missileInfo, selfPosition, transceiver, missile)
  targetSystem(I, missileInfo, selfPosition,transceiver, missile)
end

---
-- 2点間計測
-- @param target1[1..3]: 開始位置
-- @param target2[1..3]: 終了位置
function calcRange(target1, target2)
  return math.sqrt((target1.x - target2.x)^2 + (target1.y - target2.y)^2 + (target1.z - target2.z)^2)
end

---
-- ベロシティから速度へ変換
-- @param vel[1..3]: ベロシティ値
function velocityToSpeed(vel)
    return math.sqrt(vel.x^2 + vel.y^2 + vel.z^2)
end

---
-- 衝突予想地点の算出
-- @param missilePos[1..3]: ミサイルポジション
-- @param missileVel[1..3]: ミサイルベロシティ
-- @param targetPos[1..3]: ターゲットポジション
-- @param targetVel[1..3]: ターゲットベロシティ
function predict(missilePos, missileVel, targetPos, targetVel)
    --距離測定
    range = calcRange(missilePos,targetPos)
    --速度差検出
    speed = velocityToSpeed(missileVel - targetVel)
    --衝突予想時間
    hitTime = range/speed
    --衝突予想地点の算出
    return targetPos + targetVel*hitTime
end

---
-- 近接信管の距離
explodeRange = 0
---
-- 使うメインフレームブロックのIndex
useMainFrame = 0
---
-- 予想誘導を開始する距離 (注)あまりに遠距離から予想誘導を開始すると効率の悪い経路になる 0の場合は予想誘導をしなくなる
predictionRange = 400
---
-- 潜水艦VLSが誘導を開始する高度。これ以下では海面に向かって垂直に進む (注)0以上は非推奨
guidanceStartAltitude = -20
---
-- 追尾/信管システム.
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function targetSystem(I, missileInfo, selfPosition,transceiver, missile)
  if I:GetNumberOfMainframes() == 0 or I:GetNumberOfTargets(useMainFrame) == 0 then
    return
  end

  target = I:GetTargetInfo(useMainFrame, 0)
  targetRange = calcRange(target.Position, missileInfo.Position)

  if missileInfo.Position.y > guidanceStartAltitude then
   --近接信管
   if targetRange < explodeRange then 
     I:DetonateLuaControlledMissile(transceiver,missile)
   end
   --予想誘導開始範囲内の場合、予想誘導開始
   if targetRange < predictionRange or predictionRange ~= 0 then
     --衝突予想地点の取得
     predictHitPosition = predict(missileInfo.Position, missileInfo.Velocity, target.AimPointPosition, target.Velocity)
     I:SetLuaControlledMissileAimPoint(transceiver,missile,predictHitPosition.x, predictHitPosition.y, predictHitPosition.z)
   else
     I:SetLuaControlledMissileAimPoint(transceiver,missile,target.AimPointPosition.x, target.AimPointPosition.y,target.AimPointPosition.z)
   end
  else
     --海面まで垂直上昇
     I:SetLuaControlledMissileAimPoint(transceiver,missile,missileInfo.Position.x, missileInfo.Position.y+10,missileInfo.Position.z)
  end
end

---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  selfPosition = I:GetConstructCenterOfMass()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)    
    end
  end
end

地形追従ミサイル(巡行ミサイル向け)

島ばっかりな上、地面に当たってもミサイルが爆発したり壊れない現状だと趣味の域を出ないかも……?
あまりに急な地形が多いと追従が追い付かなる事も。
ミサイルのFinが2個程度必要。VLSに対応。

一応参考程度にミサイルの構成部品のサンプルを



---
-- ミサイル制御ループ
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function lanuncherControl(I, missileInfo, selfPosition, transceiver, missile)
  targetSystem(I, missileInfo, selfPosition,transceiver, missile)
end

---
-- 2点間計測
-- @param target1[1..3]: 開始位置
-- @param target2[1..3]: 終了位置
function calcRange(target1, target2)
  return math.sqrt((target1.x - target2.x)^2 + (target1.y - target2.y)^2 + (target1.z - target2.z)^2)
end

---
-- 使うメインフレームブロックのIndex
useMainFrame = 0
---
-- 終端誘導を開始する距離
predictionRange = 300
---
-- 巡行高度
cruiseHight = 15
---
-- スタートフェーズの時間この時間でおおよその敵の方向へ向く
startPhaseTime = 2
---
-- 地形高度の確認の試行回数 増やすと遠い地形まで考慮する
terrainAltCheckCount = 10
---
-- 追尾/信管システム.
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function targetSystem(I, missileInfo, selfPosition,transceiver, missile)
  if I:GetNumberOfMainframes() == 0 or I:GetNumberOfTargets(useMainFrame) == 0 then
    return
  end

  target = I:GetTargetInfo(useMainFrame, 0)
  targetRange = calcRange(target.Position, missileInfo.Position)

  --軌道準備フェーズ
  if missileInfo.TimeSinceLaunch < startPhaseTime then
   I:SetLuaControlledMissileAimPoint(transceiver,missile, target.Position.x, target.Position.y, target.Position.z)
  --巡行モード
  elseif targetRange > predictionRange then
   --中間誘導目標 適当に距離を50分割くらいで
   targetDirectionVector = (target.Position - missileInfo.Position) / 50
   guidancePosition = missileInfo.Position + targetDirectionVector
   guidanceHight = 0
   
   for i = 1, terrainAltCheckCount do
    terrainAltCheck = I:GetTerrainAltitudeForPosition(missileInfo.Position + targetDirectionVector * i)
    guidanceHight = math.max(guidanceHight, terrainAltCheck + cruiseHight)
    guidanceHight = math.max(guidanceHight, cruiseHight)
   end

   if missileInfo.Position.y > guidanceHight then
    --急に下に誘導しない様に適当にcruiseHight程度のオフセットを足す 適当
    I:SetLuaControlledMissileAimPoint(transceiver,missile, guidancePosition.x , guidanceHight + cruiseHight, guidancePosition.z)
   else
    I:SetLuaControlledMissileAimPoint(transceiver,missile, guidancePosition.x , guidanceHight, guidancePosition.z)
   end
  --終端誘導モード
  else
   I:SetLuaControlledMissileAimPoint(transceiver,missile, target.AimPointPosition.x , target.AimPointPosition.y, target.AimPointPosition.z)
  end
end

---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  selfPosition = I:GetConstructCenterOfMass()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)    
    end
  end
end

船底攻撃魚雷

少し深めの深度を魚雷が航行した後、一定距離内に近づくと浮上を開始し、船底を狙う魚雷
ミサイルのパーツにBallast tanksが必須。
Float depthを0にし、Buoyancy change に-0.1を入れる必要がある。
また、命中に難が出る為、Finの数も複数必要
ミサイルのパーツにONETURNがあるとなぜか誘導されなくなるので注意




魚雷のサイズによっては結構調整がシビアかも


---
-- ミサイル制御ループ
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function lanuncherControl(I, missileInfo, selfPosition, transceiver, missile)
  targetSystem(I, missileInfo, selfPosition,transceiver, missile)
end

---
-- 2点間計測
-- @param target1[1..3]: 開始位置
-- @param target2[1..3]: 終了位置
function calcRange(target1, target2)
  return math.sqrt((target1.x - target2.x)^2 + (target1.y - target2.y)^2 + (target1.z - target2.z)^2)
end

---
-- 近接信管の距離
explodeRange = 0
---
-- 使うメインフレームブロックのIndex
useMainFrame = 0
---
-- 敵船底へ誘導を開始する距離
trackingRange = 150
---
-- 魚雷の巡行深度 0=海面
cruiseAltitude = -50
---
-- 魚雷が通り過ぎる場合は数を負に小さくする 魚雷が手前で浮上してしまう場合は数を正に大きくする 0で補正無し
guidanceOffset = -0.5

---
-- 追尾/信管システム.
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param selfPosition 自身の位置情報
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function targetSystem(I, missileInfo, selfPosition,transceiver, missile)
  if I:GetNumberOfMainframes() == 0 or I:GetNumberOfTargets(useMainFrame) == 0 then
    return
  end

  target = I:GetTargetInfo(useMainFrame, 0)
  targetRange = calcRange(target.Position, missileInfo.Position)

  --近接信管
  if targetRange < explodeRange then 
     I:DetonateLuaControlledMissile(transceiver,missile)
  end

  --基本的に回頭の反応が遅いので、目標位置にオフセットをつける
  if targetRange < trackingRange then
    velocityOffset = missileInfo.Velocity * guidanceOffset
    I:SetLuaControlledMissileAimPoint(transceiver,missile,target.AimPointPosition.x + velocityOffset.x, target.AimPointPosition.y - velocityOffset.y, target.AimPointPosition.z + velocityOffset.z)
  else
    I:SetLuaControlledMissileAimPoint(transceiver,missile,target.AimPointPosition.x, cruiseAltitude,target.AimPointPosition.z)
  end
end

---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  selfPosition = I:GetConstructCenterOfMass()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      lanuncherControl(I, missileInfo, selfPosition,transceiver, missile)    
    end
  end
end



その他

フィンスタビライザー

船の傾きを能動的に制御します。
回頭時の横揺れや、推進装置による縦揺れ防止に。

HYDROFOIL=8
pitch_I=0
roll_I=0

-- ピッチ方向
P_Kp=2
P_Ti=1 -- 無限大を設定するにはnilを指定してください
P_Td=5

-- ロール方向
R_Kp=0.1
R_Ti=1
R_Td=20

-- PID制御で検索してください
-- 船のサイズなどによって適正値は大きく異なります
-- Lpが大きいほど強く制御します
-- Tiが小さいほど残留偏差の収束が速くなります
-- Tdが大きいほど急激な変動へ素早く対応します
-- ただし極端に設定すると逆に不安定になります

V0=1  -- コントロールする最低スピードです (0除算防止)
V1=10 -- 基準となるスピードです (最大速度や巡航速度を入れればいいんじゃないかな)

-- 翼に角度を入れるとどちらへ回転するのかを指定する関数です
function PitchDownFactor(I,index)
  return 0
end

function RollLeftFactor(I,index)
  pos=I:Component_GetBlockInfo(HYDROFOIL,index).LocalPositionRelativeToCom
 
  if (pos.x>0) then return 1
  else return -1 end
end

function Update(I)
  I:ClearLogs()
  time=I:GetTimeSinceSpawn()
  dt = last_time and time-last_time or 0
  
  pitch=I:GetConstructPitch()
  roll=I:GetConstructRoll()
  if (pitch>180) then pitch=pitch-360 end
  if (roll>180) then roll=roll-360 end
  
  pitch_I=pitch_I+pitch*dt
  roll_I=roll_I+roll*dt
  
  pitch_D=I:GetLocalAngularVelocity().x
  roll_D=I:GetLocalAngularVelocity().z

  if (math.abs(I:GetForwardsVelocityMagnitude())<V0) then
    vel_factor=0
  else
    vel_factor=V1/I:GetForwardsVelocityMagnitude()
  end
  pitch_input=-P_Kp*(pitch+(P_Ti and pitch_I/P_Ti or 0)+pitch_D*P_Td)*vel_factor
  roll_input=-R_Kp*(roll+(R_Ti and roll_I/R_Ti or 0)+roll_D*R_Td)*vel_factor

  
  pitch_input=math.min(pitch_input,45)
  pitch_input=math.max(pitch_input,-45)
  roll_input=math.min(roll_input,45)
  roll_input=math.max(roll_input,-45)
  
  for i=0,I:Component_GetCount(HYDROFOIL)-1 do
    local angle=PitchDownFactor(I,i)*pitch_input+RollLeftFactor(I,i)*roll_input;
    I:Component_SetFloatLogic(HYDROFOIL,i,angle)
  end
  last_time=time
end

艦艇用サンプルコード2

別ページにリンクします
http://seesaawiki.jp/from_the_depths/d/%a5%b5%a5%f...

このページへのコメント

CIWSの件について

CIWSをゲーム内で完全実現しようとすれば、確かに信管まわりに問題があるのかもしれません。
 それでも、現実的に撃墜できるかどうかはさておき、CIWSぽい動きをするモノを載せたい艦長は居るのではないでしょうか?
 一定距離以内の移動目標に対して、弾幕を張るというものです。

Posted by 栗林 2015年12月31日(木) 14:53:39

スクリプト部分畳むようにすると見やすいと思った(小並感)

Posted by 名無し 2015年12月12日(土) 18:58:39

ほとんどのミサイルはほぼまっすぐ来るから、信管設定さえできれば航空機迎撃より簡単そうなんだけどねー

Posted by  Z 2015年11月23日(月) 22:38:27

現状CIWSが実用的になってないのは、砲弾の信管起爆がLUAで制御できないからなんだよね。
KE弾もミサイルへの当たり判定が無いしね。
MissileIntercepterみたいな当たり判定のある弾頭か、砲弾の起爆まわりがLUAで制御できる様になればすぐ作れる。

Posted by 通りすがり 2015年11月23日(月) 15:45:06

あらら、信管制御がまだ良くわかってないのか・・・

ミサイルの耐久力自体はそれほどでもない筈なので
(事実Flak弾で航空機を虐めているとちょくちょくミサイルが誘爆を起こす)
弾道計算とかが問題でしょうか・・・

フォーラムを機械翻訳でざっくり見て回るとMD用CIWSあるじゃん!と思ったら動かなかったり・・・。
あとAdv砲のAIM改善とかもあったのでイケるかなーと思ったけど難しいのですね(´;ω;)

早い回答有難うございます〜!

Posted by びんせんとー 2015年11月23日(月) 14:29:55

コメントをかく


ユーザーIDでかく場合はこちら

画像に記載されている文字を下のフォームに入力してください。

「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

どなたでも編集できます