FtDのLuaで敵の位置を知る

* この記事は「From The Depths」というゲーム（以下FtD）で使用できるLuaに関する記事です。
* Luaに関心のあるFtDプレイヤーを対象としています。
* 敵の位置、方向の取得の仕方を解説します。

## 敵の位置を知る
`TargetInfo`と`TagetPositionInfo`の中に敵の各種情報が詰まっています。

```lua
function Update(I)
  I:ClearLogs()
  local mainframe_count = I:GetNumberOfMainframes()
  if mainframe_count == 0 then
     -- mainframeが無い場合は処理終了
     I:Log('mainframe nothing')
    return
  end

  local target_count = I:GetNumberOfTargets(0)
  if target_count == 0 then
     -- 敵がいない場合は処理終了
     I:Log('target not found')
     return
  end

  local mainframeIndex = 0 -- 0は最初に置いたmainframe
  local targetIndex = 0 -- 0は攻撃対象にしている敵。スコアが最も高い敵
  local target_info = I:GetTargetInfo(mainframeIndex, targetIndex)
  local target_position_info = I:GetTargetPositionInfo(mainframeIndex, targetIndex)
  local target_global_position = target_info.Position -- 敵のワールド座標(Vector3)
  I:Log('global position'..target_global_position:ToString())

  local target_direction = target_position_info.Direction -- 敵への向き(Vector3)
  I:Log('direction '..target_direction:ToString())

  local com = I:GetConstructCenterOfMass() -- 自機の重心のワールド座標(Vector3)
  local target_local_posotion = target_global_position - com -- 敵のローカル座標(Vector3) target_directionに同じ
  I:Log('local position '..target_local_posotion:ToString())

  local target_range = target_position_info.Range -- 敵までの3次元距離(float)
  I:Log('range '..target_range)

  local target_distance = target_position_info.GroundDistance -- 敵までの2次元距離（高さを考慮しない地図上での距離）(float)
  I:Log('distance '..target_distance)
end
```

実行結果
![20190529214317_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/6d61e0e0-a782-4161-475b-60f02c04d4d4.jpeg)

## 敵の角度を知る
`TagetPositionInfo`の中に敵の各種情報が詰まっています。

```lua
function Update(I)
  I:ClearLogs()
  local mainframe_count = I:GetNumberOfMainframes()
  if mainframe_count == 0 then
     -- mainframeが無い場合は処理終了
     I:Log('mainframe nothing')
    return
  end

  local target_count = I:GetNumberOfTargets(0)
  if target_count == 0 then
     -- 敵がいない場合は処理終了
     I:Log('target not found')
     return
  end

  local mainframeIndex = 0 -- 0は最初に置いたmainframe
  local targetIndex = 0 -- 0は攻撃対象にしている敵。スコアが最も高い敵
  local target_position_info = I:GetTargetPositionInfo(mainframeIndex, targetIndex)

  local azimuth = target_position_info.Azimuth -- 自機から見て敵の水平角度
  I:Log('azimuth '..azimuth)

  local elevation = target_position_info.Elevation -- 自機から見て敵の垂直角度
  I:Log('elevation '..elevation)

  local alt_angle = target_position_info.ElevationForAltitudeComponentOnly -- 自機や敵の姿勢は無視したワールド座標での敵の垂直角度（多分）
  I:Log('alt_angle '..alt_angle)

  I:SetSpinBlockRotationAngle(1, -elevation)
  I:SetSpinBlockRotationAngle(2, -azimuth)
end
```

実行結果
![20190529220532_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/2a4f775a-91f8-0baa-3ce4-0617efed9954.jpeg)

赤いレーザーエミッターがazimuth
![20190529220253_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/95d5b06c-1651-2df9-c0e4-b85945baaf43.jpeg)

緑のレーザーエミッターがelevation
![20190529221122_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/48652124-dcee-ac3b-2373-93fccb03a264.jpeg)

## 複数の敵の情報を得る
mainframeindexやtargetindexでforループを回すと、mainframeが認識している敵の情報を全て取得できます。

```lua

function Update(I)
  I:ClearLogs()
  local mainframe_count = I:GetNumberOfMainframes()
  for mainframeIndex = 0, mainframe_count - 1 do
    local target_count = I:GetNumberOfTargets(mainframeIndex)
    for targetIndex = 0, target_count - 1 do
      local target_info = I:GetTargetInfo(mainframeIndex, targetIndex)
      local target_global_position = target_info.Position -- 敵のワールド座標(Vector3)
      I:Log('global position'..target_global_position:ToString())
    end
  end
end
```

実行結果
![20190529221532_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/27e24485-3e54-2012-1409-253b3478b8d6.jpeg)
![20190529221539_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379954/b1271330-e2a0-aa24-00a3-aaecdd0d4f4e.jpeg)



以上。