LUAお役立ちサンプルコード

Last-modified: 2023-09-26 (火) 18:14:34

(旧Wikiからベタ移植。正常に動作しない件は、おそらくFtDまわりの関数。現在の仕様と照らし合わせると修正するべき点が見えてくる、かもしれない by 移植した人)

ミサイル/魚雷系

魚雷安全信管プログラム

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

 

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

 

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

 
コード
-- 自爆システム用の安全距離。これ以上の距離かつ下の時間経過で自爆する
seftyRange = 100
---
-- 自爆用の時間。上記同様
seftyOverTime = 20
---
-- 自爆システム
-- @param I FromTheDepths用のクラス
-- @param missileInfo ミサイル情報クラス
-- @param transceiver 使用するLUAレシーバ
-- @param missile 制御する対象ミサイル
function seftySystem(I, missileInfo, transceiver, missile)
    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
---
-- メイン.
-- @param I FromTheDepthsクラス呼び出し用
function Update(I)
  transceiverCount = I:GetLuaTransceiverCount()
  for transceiver = 0,transceiverCount-1,1 do
    missileCount = I:GetLuaControlledMissileCount(transceiver)
    for missile = 0,missileCount-1,1 do
      missileInfo = I:GetLuaControlledMissileInfo(transceiver, missile)
      seftySystem(I, missileInfo, 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
 

複数体同時ロックオン追尾/近接信管/予測誘導(潜水艦VLS対応)

上のプログラムに更に複数体同時ロックオン機能を追加したもの。
自ビークルのLUA Receiverで制御されるミサイルを、LUA Transceiverごとに各ターゲットに対してほぼ均等に分配し誘導します。
ターゲットとする敵を選別するために、使用するミサイルの射程に合わせてコンフィグを設定して使ってください。
また、ミサイルをAIに発射させる場合はLocal Weapon Controllerもコンフィグと同じように設定してください。
このスクリプトはメインコンストラクト(船体)上のコンフィグtransceiverPositionに設定された座標の範囲内にあるLUA Transceiver付きのLaunch Pad、
及びコンフィグsubConstructIdsに設定されたIDのサブコンストラクト(スピンブロックやターレット等)上のLUA Transceiver付きのLaunch Padから発射される
LUA Receiverを搭載したミサイルを制御します。
コンフィグtransceiverPositionもしくはコンフィグsubConstructIdsを適切に設定しないとミサイルが誘導されません!!!
コンフィグのspotlightPositionをtrueにすると、一番最後に設置したspotlightがメインコンストラクタ(船体)上にある場合は座標が、
サブコンストラクト(スピンブロックやターレット等)上にある場合はそのサブコンストラクトのIDが表示されますのでそれを参考に設定してください。
ちなみにFtD(Unity)は左手系の座標なので、ビークルの前方方向を向いて右に行くほどxが、上に行くほどyが、奥に行くほどzが増加し、逆方向へは減少します。
また、Missile InterceptorがついているLUA Receiver搭載ミサイルは制御から外すので迎撃LUAミサイルとも同時使用できると思います。
再配布、改造ともに自由です。使用については自己責任でお願いします。

fileFtD_MultiLockOnLuaMissile_v1.10..txt

船底攻撃魚雷

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

 

95eb103f1d3d4114.png
5fc87c3eda5e257a.png

 

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

 
コード
---
-- ミサイル制御ループ
-- @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

ミサイル及び魚雷の複数体同時ロックオン追尾/近接信管/予測誘導(潜水艦VLS/船底誘導対応)

二つ上のマルチロックオンシステムを魚雷にも適応し、さらに上の船底誘導機能を追加したもの。
自ビークルのLUA Receiverで制御されるミサイル及び魚雷を、LUA Transceiverごとに各ターゲットに対してほぼ均等に分配し誘導します。
ターゲットとする敵を選別するために、使用するミサイル及び魚雷の射程に合わせてコンフィグを設定して使ってください。
また、ミサイル及び魚雷をAIに発射させる場合はLocal Weapon Controllerもコンフィグと同じように設定してください。
このスクリプトはメインコンストラクト(船体)上のコンフィグtransceiverPositionに設定された座標の範囲内にあるLUA Transceiver付きのLaunch Pad、
およびコンフィグsubConstructIdsに設定されたIDのサブコンストラクト(スピンブロックやターレット等)上のLUA Transceiver付きのLaunch Pad、から発射される
LUA Receiverを搭載したミサイル及び魚雷を制御します。
コンフィグtransceiverPositionもしくはコンフィグsubConstructIdsを適切に設定しないとミサイル及び魚雷が誘導されません!!!
コンフィグのspotlightPositionをtrueにすると、一番最後に設置したspotlightがメインコンストラクタ(船体)上にある場合は座標が、
サブコンストラクト(スピンブロックやターレット等)上にある場合はそのサブコンストラクトのIDが表示されますのでそれを参考に設定してください。
コンフィグはミサイル及び魚雷用にそれぞれあるので両方のtransceiverPositionもしくはsubConstructIdsを適切に設定してください。
ちなみにFtD(Unity)は左手系の座標なので、ビークルの前方方向を向いて右に行くほどxが、上に行くほどyが、奥に行くほどzが増加し、逆方向へは減少します。
また、Missile InterceptorがついているLUA Receiver搭載ミサイル及び魚雷は制御から外すので迎撃LUAミサイル及び魚雷とも同時使用できると思います。
再配布、改造ともに自由です。使用については自己責任でお願いします。

fileFtD_MultiLockOnLuaMissileAndTorpedo_v1.13..txt

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

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

 

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

 

990ce33eb8078c5a.png

 
コード
---
-- ミサイル制御ループ
-- @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

迎撃ミサイル多目標同時照準プログラム

AMCCと似たような優先度付けによって迎撃ミサイルを適切な敵ミサイルに誘導するLUAです。
命中率向上のための比例航法誘導付き。
fileMissile_Interceptor_multi-targeting_LUA_v11.txt

絶対索敵ミサイル

索敵装置なしでも絶対に相手の重心点のワールド座標に向けて飛んでいくミサイルです。ジャミング/デコイを無視します。
最新dev環境下で動作することを確認済み

 
コード
function Update(I)
for i = 0, I:GetLuaTransceiverCount() ,1 do
MC = I:GetLuaControlledMissileCount(i)
for i2 = 0 , MC-1 , 1 do
       I:SetLuaControlledMissileAimPoint(i,i2,I:GetTargetInfo(0,0).Position.x,I:GetTargetInfo(0,0).Position.y,I:GetTargetInfo(0,0).Position.z)
       I:SetLuaControlledMissileInterceptorStandardGuidanceOnOff(i,i2,false)
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
 

推力偏向+尾翼制御システム

指定したスピブロで推力偏向と尾翼制御を行い、機動力を高めるLUAです。
事前にイルミネーションライトを2つ設置する必要があります。
また、ACBでx軸とy軸用のイルミネーションライトをピッチとロールで右が10、左が5、機首上げが10,下げが5になるよう設定も必要となります。
※カスジェ航空機向け

 
コード
function Update(I)
--可動スピブロ指定動かしたいスピブロの番号を入れてください
Tail_L = 22 --左尾翼
Tail_R = 24 --右尾翼
Thur_L = 15 --左スラスター
Thur_R = 16 --右スラスター
Stop_pos = 0 --初期角度
IL1 = --x軸用イルミネーションライト番号
IL2 = --y軸用イルミネーションライト番号
--可動範囲設定0~180度までが選択可能
TailAngleLim = 30 --尾翼最大角度
ThurAngleLim = 30 --スラスター最大角度
--各コントロール ON/OFF(ON=1,OFF=0)
Pitch = 1 --ピッチ時操作するか
Roll = 1 --ロール時操作するか
Stp = 1 --初期化するか
--こっから下はいじらないで!
--初期化
function Stop()
I:SetSpinBlockRotationAngle(Tail_L,Stop_pos)--左尾翼
I:SetSpinBlockRotationAngle(Tail_R,Stop_pos)--右尾翼
I:SetSpinBlockRotationAngle(Thur_L,Stop_pos)--Lスラスター
I:SetSpinBlockRotationAngle(Thur_R,Stop_pos)--Rスラスター
end
--初期化
--尾翼両上げ
function TailDup()
I:SetSpinBlockRotationAngle(Tail_L,TailAngleLim)--左尾翼
I:SetSpinBlockRotationAngle(Tail_R,-TailAngleLim)--右尾翼
end
--尾翼両上げ
--尾翼両下げ
function TailDdn()
I:SetSpinBlockRotationAngle(Tail_L,-TailAngleLim)--左尾翼
I:SetSpinBlockRotationAngle(Tail_R,TailAngleLim)--右尾翼
end
--尾翼両下げ
--スラスター両上げ
function ThuDup()
I:SetSpinBlockRotationAngle(Thur_L,ThurAngleLim)--Lスラスター
I:SetSpinBlockRotationAngle(Thur_R,-ThurAngleLim)--Rスラスター
end
--スラスター両上げ
--スラスター両下げ
function ThuDdn()
I:SetSpinBlockRotationAngle(Thur_L,-ThurAngleLim)--Lスラスター
I:SetSpinBlockRotationAngle(Thur_R,ThurAngleLim)--Rスラスター
end
--スラスター両下げ
--尾翼右上げ左下げ
function TailRupLdn()
I:SetSpinBlockRotationAngle(Tail_L,-TailAngleLim)--左尾翼
I:SetSpinBlockRotationAngle(Tail_R,-TailAngleLim)--右尾翼
end
--尾翼右上げ左下げ
--尾翼右下げ左上げ
function TailRdnLup()
I:SetSpinBlockRotationAngle(Tail_L,TailAngleLim)--左尾翼
I:SetSpinBlockRotationAngle(Tail_R,TailAngleLim)--右尾翼
end
--尾翼右下げ左上げ
--スラスター右上げ左下げ
function ThuRupLdn()
I:SetSpinBlockRotationAngle(Thur_L,-ThurAngleLim)--Lスラスター
I:SetSpinBlockRotationAngle(Thur_R,-ThurAngleLim)--Rスラスター
end
--スラスター右上げ左下げ
--スラスター右下げ左上げ
function ThuRdnLdn()
I:SetSpinBlockRotationAngle(Thur_L,ThurAngleLim)--Lスラスター
I:SetSpinBlockRotationAngle(Thur_R,ThurAngleLim)--Rスラスター
end
--スラスター右下げ左上げ
--保存ステイタス確認
x = I:Component_GetFloatLogic_1(30,IL1,0)--参照先1
y = I:Component_GetFloatLogic_1(30,IL2,0)--参照先2
--保存ステイタス確認
--ピッチ判定
function JudgePitch()
if (x == 10) then --機首上げ
TailDdn()
ThuDup()
elseif (x == 5) then --機首下げ
TailDup()
ThuDdn()
else --停止
end
end
--ピッチ判定
--ロール判定
function JudgeRoll()
if (y == 10) then --右ロール
TailRdnLup()
ThuRdnLdn()
elseif (y == 5) then --左ロール
TailRupLdn()
ThuRupLdn()
else --停止
end
end
--ロール判定
--停止判定
function JudgeStop()
if (x==0) then
if(y==0) then
Stop()
end
end
end
--停止判定
--管理用
if(Pitch == 1) then
JudgePitch()
end
if(Roll == 1) then
JudgeRoll()
end
if(Stp == 1) then
JudgeStop()
end
end
 

Dedicated helibladeによるロール・ピッチ・高度制御PID-LUA

ソースコード
filePID_1.txt
サンプルブループリント
fileDediblade PID-LUA.blueprint
Dedicated heliblade spinnerの姿勢でロール用・ピッチ用・高度維持用を判別している。
下図の矢印の向きにスピナーの正面を配置することで制御できる。PIDのパラメータは機体に合わせて調整したほうがいいかも?
Motor driveはとりあえず最大で設定して、過剰なようであれば減らしていくとよい。
スピナーの正面方向を艦前方に、推進方向を上方にするとピッチアップ用(艦首に配置する)。
正面方向を艦後方に、推進方向を上方にするとピッチダウン用(艦尾に配置する)。
正面方向を艦左方に、推進方向を上方にするとロールアップ用(左舷に配置する)。
正面方向を艦右方に、推進方向を上方にするとロールダウン用(右舷に配置する)。
正面方向を艦前方に、推進方向を下方に、Upwards force fractionを最大すると高度維持用(重心付近に配置する)。
Ctrl+Gキーでブロックの正面方向をカメラの向きにすることができるのでそうして設置するといい。
pid.png

 

UI

HP表示

ゲーム画面にビークルのHPを表示します。
※AI接続は不要です。適当なところにLUAboxを置いて、コードを移すだけで機能します。タブン。

 
コード
function Update(I)
i=1
while (I.Fleet.Members[i].CenterOfMass~=I:GetConstructCenterOfMass()) do
 i=i+1
 I:Log(i)
end
myname = I:GetFriendlyInfoById(I.Fleet.Members[i].Id).BlueprintName
myhp = math.floor(I:GetHealthFraction()*100)
I:LogToHud(myname.."HP"..myhp..[[%]])
end
 

Otome-Plugin(戦闘アシストHUD)

ゲーム画面に次ビークルの残燃料と残弾薬、敵の方角と距離、方向と速度を表示します。
※索敵装置、AIが必要となります。ご注意ください。

 
コード
 --OTOME-Plugin Ver1.0!
 --起動開始
if I:GetNumberOfTargets(0) > 0 then
I:LogToHud('OTOME Plugin System ....Run')
I:LogToHud('乙女戦闘アシストプログラム機動!')
I:LogToHud('敵までの距離や方位等自艦のガイドを行うわ!')
I:LogToHud('しっかりついてきなさい!!')
end
 --起動開始
 --最も近い敵との距離
if I:GetNumberOfTargets(0) > 0 then
TR = I:GetTargetInfo(0,0).AimPointPosition - I:GetConstructCenterOfMass()
I:LogToHud('最接近中の攻撃目標距離まで'..math.floor(TR.magnitude)..'mよ!')
 --最も近い敵との方位
enemy = I:GetTargetPositionInfo(0,0)
TD = enemy.Azimuth
I:LogToHud('最接近中の攻撃目標は方位'..math.floor(TD)..'度よ!!')
 --敵艦の速度
TS = I:GetTargetInfo(0,0).Velocity
I:LogToHud('最接近中の速度は'..math.floor(TS.magnitude)..'m/sよ!')
end
 --
 --燃料ガイド
if I:GetFuelFraction(0) < 0.01 then
I:LogToHud('燃料完全喪失!ちょっとぉおおお!これじゃあ只のボートよ!!')
elseif I:GetFuelFraction(0) < 0.2 then
I:LogToHud('残り燃料僅か!戦闘機動が困難よ!')
elseif I:GetFuelFraction(0) < 0.5 then
I:LogToHud('燃料残り半分よ!気をつけなさい!!')
else
FP = I:GetFuelFraction(0)
FP = FP*100
I:LogToHud('燃料残量残り'..math.floor(FP)..'%よ!')
end
 --燃料ガイド
 --弾薬ガイド
if I:GetAmmoFraction(0) < 0.01 then
I:LogToHud('弾薬完全損失!このままじゃダメよ!!さっさと補給しなさい!')
elseif I:GetAmmoFraction(0) < 0.1 then
I:LogToHud('弾薬欠乏寸前よ!なにやってるの!?')
elseif I:GetAmmoFraction(0) < 0.5 then
I:LogToHud('弾薬残り半分よ!気をつけなさい!!')
else
AP = I:GetAmmoFraction(0)
AP = AP*100
I:LogToHud('弾薬残量残り'..math.floor(AP)..'%よ!')
end
 --弾薬ガイド
 --敵判定
if I:GetNumberOfTargets(0) > 0 then
enemy = I:GetTargetPositionInfo(0,0)
TD = enemy.Azimuth
if TD >= -60 and TD <= 60 then
I:LogToHud('敵は正面よ!')
elseif TD >= 120 or TD <= -120 then
I:LogToHud('敵は後方よ!')
elseif TD >= 61 and TD <= 119 then
I:LogToHud('敵は左舷よ!')
elseif TD >= -121 and TD <= -61 then
I:LogToHud('敵は右舷よ!')
else
I:LogToHud('敵機は未確認よ')
end
end
 --敵判定
 

攻撃制御

置くだけ迎撃LUA

ACB置くのがだるい時、対魚雷、対ミサイルの打ち分けがしたい時にどうぞ。
・ミサイル、魚雷用の武器スロット(ALLが0で後は数字通り)
・メインフレーム番号(1個しかないなら0のまま)
・迎撃距離の設定
の編集は各自用途に合わせて設定してネ。

注意:Munition warnerやPassive Sonar 360の配置を忘れずに!
リンク

 

ガトリング制御LUA

使い方:
1:スピブロやらピストンやらを駆使してガトリング砲を作成する
この際、砲身を1本ずつスピブロやピストンに乗せておく事(ファイヤリングピースにLWCを設置するのを忘れずに!)

2:LUA箱を置いて中心になるスピブロと各砲身が乗ってるサブオブジェクトのIDを登録する

備考:マントルは無しの方が砲身わさわさ動かなくて良いと思うな!

ガトリング.jpg

コード
	----ガトリング砲用LUAスクリプト ver1.0
	--中心になる(回転する)スピンブロックのSubConstructId
	CENTER_SPINNER = 89
	--砲の乗っているSubConstructId(発射する順番で指定)
	CannonIDs = {92,98,96,94}
	--使用する武器スロット(ALLの場合は0)
	WEAPON_SLOT = 0
	----ヨクワカラナイならこっからさわらない
	function EulerAngles(q1)
	  local sqw = q1.w*q1.w
	  local sqx = q1.x*q1.x
	  local sqy = q1.y*q1.y
	  local sqz = q1.z*q1.z
	  local unit = sqx + sqy + sqz + sqw --if normalised is one, otherwise is correction factor
	  local test = q1.x*q1.y + q1.z*q1.w
	  local heading, attitude, bank
	  if (test > 0.499*unit) then --singularity at north pole
	    heading = 2 * math.atan2(q1.x,q1.w)
	    attitude = math.pi/2;
	    bank = 0
	  elseif (test < -0.499*unit) then --singularity at south pole
	    heading = -2 * math.atan2(q1.x,q1.w)
	    attitude = -math.pi/2
	    bank = 0
	  else
	    heading = math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw)
	    attitude = math.asin(2*test/unit)
	    bank = math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
	  end
	  return math.deg(heading), math.deg(attitude), math.deg(bank)
	end
	function Update(I)
		I:ClearLogs()
		center = I:GetSubConstructInfo(CENTER_SPINNER)
		rotation = center.LocalRotation
		local Angle = EulerAngles(Quaternion.Inverse(rotation))
		Angle = Angle + 180
		I:Log(Angle)
		--I:Log(up.x..","..up.y..","..up.z)
		Num = #CannonIDs
		oneRot = 360/Num
		for cNo = 0, Num-1 do
			if Angle < oneRot * cNo or Angle > oneRot * (cNo+1) then
				--武器取得
				--制限角度
				wepinfo = I:GetWeaponInfoOnSubConstruct(CannonIDs[cNo+1],WEAPON_SLOT)
				v = -wepinfo.CurrentDirection
				I:AimWeaponInDirectionOnSubConstruct(CannonIDs[cNo+1],0,v.x,v.y,v.z,WEAPON_SLOT)
			end
		end
	end
 

LuaAI系

FAI1.8 BMC HC

空戦用スクリプト(Fighter AI v1.8)をベースに地形追随機能、AIモード排他処理機能を付け足しました。

fileFAI1_0.8_BMC_HC.txt

 

装飾系

SpotLight首振り

ExtentDegreeで首振る角度を変更、Elevationを任意の値から0.1,0.2ずらすと首振りのON/OFFを切り替えられます。
(Elevation × 10 を3で割った値が2のとき首を振らない。)

コード
 function Update(I)
 --SearchLightMover v2.0 by kuramubon
 --change this value to limit the spotlight’s movable degree
 ExtentDegree = 60
   lightNum = I:Component_GetCount(12) - 1;
   for i = 0, lightNum, 1 do
   --each spotlight
     nowaz = I:Component_GetFloatLogic_1(12, i, 1);
     nowel = I:Component_GetFloatLogic_1(12, i, 2);
     if Mathf.Floor(nowel * 10) % 3 == 0 then
       if nowaz >= ExtentDegree then
         I:Component_SetFloatLogic_1(12, i, 2, nowel + 0.1);
       else
         I:Component_SetFloatLogic_1(12, i, 1, nowaz + 0.5);
       end
     elseif Mathf.Floor(nowel * 10) % 3 == 1 then
       if nowaz <= -ExtentDegree then
         I:Component_SetFloatLogic_1(12, i, 2, nowel - 0.1);
       else
         I:Component_SetFloatLogic_1(12, i, 1, nowaz - 0.5);
       end
     end
   end
 end
 

スピブロとかピストンとか系

サブコントラクトID取得

適当に名前を付けたサブコントラクトのIDをログに表示します。
SB1とかが名前なんで自分でつけた名前に置き換えてください。

コード
SpinBlocks={
    {name="SB1"},--サブコントラクトにつけた名前
    {name="SB2"},
    {name="SB3"},
}
function GetSubConstructsID (I,Table)
    subconst_table = I:GetAllSubConstructs()
    for index = 1 ,#subconst_table ,1 do
        id = subconst_table[index]  --現在のインデックスのサブコンストラクトIDを取得
        name = I:GetSubConstructInfo(id).CustomName --現在のインデックスのサブコンストラクトの名前を取得
        for index = 1 ,#Table ,1 do
            if name == Table[index].name then
                Table[index].id = id
            end
        end
    end
end
function Update(I)
    I:ClearLogs()
    GetSubConstructsID(I,SpinBlocks)
    for i=1,#SpinBlocks do
        I:Log(SpinBlocks[i].name.." "..SpinBlocks[i].id)
    end
end
 

コメント

  • 何でLuaが分かるのにWikiの記述方法は分からないんだ・・・!とかと思いつつコンテンツ部分から飛ぶ際のIDを再配置、これで該当部分に飛べるはず。 -- 管理人/びんせんとー? 2017-01-29 (日) 20:45:28
    • アリガトウゴザイマース!! -- Weavel? 2018-01-27 (土) 01:30:34
  • Otome-Pluginが動かない・・・ ログとかってどこにでるんですか? Luaとかさっぱりわかんない・・・ -- 2018-04-06 (金) 18:23:46
    • function Update(I)
      (ココにコードをコピペすると動くと思います)
      end -- 2018-04-07 (土) 17:09:07
  • でぃすこだと流れそうだったのでこちらでも報告をば。 -- Arisawa? 2018-08-21 (火) 22:08:17
    • ↑誤送信 ガトリング制御LUAのリンクが切れてました -- Arisawa? 2018-08-21 (火) 22:09:27
    • とりあえず作者に一報入れてみましょうか… -- 管理人/びんせんとー? 2018-08-21 (火) 23:20:50
      • 対応完了ナリ。 -- 管理人/びんせんとー? 2018-08-21 (火) 23:38:58
  • Otome-Pluginですがコメントの行に全角スペースが入ってて、そのままコピペしたらエラーになりました -- 2020-06-03 (水) 23:23:53