Lua初心者講座

Last-modified: 2020-11-27 (金) 17:54:35

編集時Ver3.1.1.4

はじめに

本ページは、FtDのLUAをやってみたいけどプログラムとかさっぱりわからない、といった人に向けて
LUAの初歩を解説したものです。
随時サンプルコードを提示しているので、実際に動かしてみるのも良いと思います。

リンク

FtDのLUAのバージョンは不明。恐らく5.2
(table.maxnが無く、math.atan2が有る)

準備

FtDのLUA boxはエディタを持っていますが、長文だと全文が表示されなかったり、
改行がおかしくなったりするので、別途メモ帳などのテキストエディタで編集し
コピペでFtDのLUA boxに張り付けることを強くお勧めします。

LUA boxの使い方

LUA boxはインベントリのControlタブにあります。
設置し、Qキーを押すとエディタが開きます。
試しに下記のコードをコピペしてみてください。

function Update(I)
  I:ClearLogs()
  I:Log("hello world")
end

画面右側のApply changes (SAVE)(F8)を押して、画面下部にhello worldと表示されればOKです。
編集を終了する場合、画面右上のExit (don't save changes)を押します。
Tabキーを押すとエディタが一時的に消えます。何かキーを押したり、マウスを動かしたりすると戻ります。

Options

画面右側のOptionsについて

Stop running処理を一時停止します。再開する場合はRestart runningを押します
Apply changes (SAVE)(F8)現在のコードを適用します
Cahcelchanges (LOAD PREVIOUS)最後にApply changesした状態に戻します
Clear Log画面下部のErrors/Logsをクリアします(が、動いているとまたログで埋まります)
Select All (CTRL+A)コードを全選択します

Errors/Logs

エディタ画面下部の「Errors/Logs」の欄は、ログやエラーが出力されます。
最大100行です。
ログを出力するたびに1行目に挿入されるので、下が古く、上が新しいです。

エラーの確認

LUAのエラーが発生すると、「Errors/Logs」の欄に内容が出力されます。
エラーの内容は一番下に出力されるのでスクロールしましょう。
何かおかしいなと思ったら確認するのが完成への早道です。
ただし、アプデでエラーが出力されなくなった時期があるので、またあるかもしれません。

LUA boxの実行頻度

LUA boxに書かれたコードは1フレーム(1/40秒)ごとに実行されます。
具体的には、Update関数がFtDクライアントから呼ばれます。
つまり、Update関数は1秒間に40回実行されます。
関数については後述します。

プログラム言語「LUA」の基礎

プログラム言語LUAを扱うための基礎知識。
ビークルなどFtD的なことはこの項ではあまり関係ありません。

コメントアウト

ハイフン2つ(--)は、行末までの文字を無視します。
メモに使ったり、処理したくない行を一時的に無効化するのに使います。
自分が書いたコードでも1か月もすれば忘れるのでメモとしてよく使います。

function Update(I)
  I:ClearLogs()
  I:Log("hello world") -- ハイフン2つ以降のここは処理に関係ない
end

ハイフン2つと大かっこ2重で複数行コメントができます。

function Update(I)
  I:ClearLogs()
--[[
複数行コメント
大かっこで囲まれた部分がコメント
]]
  I:Log("hello world")
end

変数

変数とは箱のようなもので、値を入れることができます。
命名は英字で始まり、英字・数字・アンダーバー「_」を使用できます。
例)name, position1, from_the_depths

また、大文字小文字は区別されます。
例)name と Name は別物

変数は最初に登場した時(宣言時)に何らかの値を入れる必要があります。

function Update(I)
  I:ClearLogs()
  x -- 初期化していないのでエラー
end
function Update(I)
  I:ClearLogs()
  x = 0 -- 初期化しているのでエラーは出ない
  I:Log(x) -- ログ欄に0が出力される
end

FtDのLUAでは、値のデータ型には下記の6種類があります。

number数値0や1や1.1など数値なら何でも。例)x = 1
string文字列ダブルクォーテーションやシングルクォーテーションで囲みます。例)x = "test"
boolean真偽ture か false。有りか無しかのどちらか。
function関数LUAは関数を変数に入れられる。関数については後述。
tableテーブル複数の値をまとめて1つの変数に入れられる。
nilNULLやfalse。0ではない。ラテン語で「無」に由来する。RPGで例えると「無属性」ではなく「属性なし」

※プログラム言語習得者向け解説
LUAは変数が型を持たず、値が型を持つ動的型付け言語です。
型定義の構文はありません。
また、ユーザーデータとスレッドはFtDでは使えません。
つまり、メタテーブルとコルーチンがありません。

number

数値です。整数、小数、指数などがあります。

function Update(I)
  I:ClearLogs()
  x = 1 -- 変数xに1を代入
  I:Log(x) -- ログ欄に1が出力される
  y = 1.5 -- 変数yに1.5を代入
  I:Log(y) -- ログ欄に1.5が出力される
  z = -2 -- 変数zに-2を代入
  I:Log(z) -- ログ欄に-2が出力される
  e = 2e+1 -- 変数eに2e+1を代入
  I:Log(e) -- ログ欄に20が出力される
end

string

ダブルクォーテーションまたはシングルクォーテーションで囲みます。
また、大かっこ2つで囲むと複数行の文字列を扱えます。
FtDではログ出力に使ったり、名前付けしたブロックを扱う際に使います。

function Update(I)
  I:ClearLogs()
  x = "a" -- 変数xにaを代入
  I:Log(x) -- ログ欄にaが出力される
  y = 'b' -- 変数yにbを代入
  I:Log(y) -- ログ欄にbが出力される
  z = [[いろはに
ほへと]] -- 変数zに「いろはに[改行]ほへと」を代入。
  I:Log(z) -- ログ欄に「いろはに[改行]ほへと」が出力される
end

boolean

(シン)(true)か()(false)のどちらかを持つデータ型です。
後述するif文の条件判定に使ったり、状態を管理するのに使ったりします。
そのままではログ出力されません。

function Update(I)
  I:ClearLogs()
  x = true -- 変数xにtrueを代入
  if x == true then
    I:Log("true") -- ログ欄に文字列trueが出力される
  else
    I:Log("false") -- ここは通らない
  end
end

function

「関数」の項にて後述

table

テーブルを含む6種類のデータ型を複数持つデータ型です。
中かっこで囲みます。
「配列」と「連想配列」があります。

配列は、複数の値を順番に並べて持ちます。
複数の値のうち、どれを使うかを1以上の数字で指定します。
これらテーブルに入っている複数の値の事を「要素」といいます。

function Update(I)
  I:ClearLogs()
  x = {10, 11, 12, 13} -- 10~13の数値をまとめてxに代入
  y = x[1]
  I:Log(y) -- ログ欄に10が出力される
  I:Log(x[2]) -- ログ欄に11が出力される
  I:Log(x[3]) -- ログ欄に12が出力される
  I:Log(x[4]) -- ログ欄に13が出力される
end

連想配列は、キーと値のペアを複数持ちます。
複数の値のうち、どれを使うかをキーで指定します。

function Update(I)
  I:ClearLogs()
  x = {a = 10, b = "name", c = true}
  I:Log(x["a"]) -- ログ欄に10が出力される
  I:Log(x["b"]) -- ログ欄にnameが出力される
  I:Log(x["c"]) -- booleanなのでログ欄に出力されない
  I:Log(x.a) -- この書き方でもログ欄に10が出力される
end

配列と連想配列を混ぜてもOKです。

function Update(I)
  I:ClearLogs()
  x = {100, a = 10, b = "name", 200, c = true, 300, 400}
  I:Log(x["a"]) -- ログ欄に10が出力される
  I:Log(x["b"]) -- ログ欄にnameが出力される
  I:Log(x["c"]) -- booleanなのでログ欄に出力されない
  I:Log(x[1]) -- ログ欄に100が出力される
  I:Log(x[2]) -- ログ欄に200が出力される
  I:Log(x[3]) -- ログ欄に300が出力される
  I:Log(x[4]) -- ログ欄に400が出力される
end

テーブルを持つこともできるので、ツリー構造を作れます。

function Update(I)
  I:ClearLogs()
  x = {
    100,
    a = 10,
    b = "name",
    200,
    sub = {
      11, 12, 13
    },
    sub2 = {
      red = 1, blue = 0.5, green = 0.11
    },
  }
  I:Log(x["sub"][1]) -- ログ欄に11が出力される
  I:Log(x.sub[1]) -- ログ欄に11が出力される
  --I:Log(x.sub.1) -- この書き方はできない
  I:Log(x.sub2.red) -- ログ欄に1が出力される
end

宣言時に初期化せず、後から値を代入することもできます。

function Update(I)
  I:ClearLogs()
  x = {}
  x["a"] = 10
  I:Log(x["a"]) -- ログ欄に10が出力される
  x.b = "name"
  I:Log(x["b"]) -- ログ欄にnameが出力される
  x[1] = 20
  I:Log(x[1]) -- ログ欄に20が出力される
end

テーブル名の先頭に#を付けると、中身の件数(要素数)を返します。

function Update(I)
  I:ClearLogs()
  x = {10, 11, 12, 13} -- 10~13の数値をまとめてxに代入
  y = #x
  I:Log(y) -- ログ欄に4が出力される
end

nil

「値が無い」を表すデータ型です。
また値を設定していない事を明示するのに使ったりします。

function Update(I)
  I:ClearLogs()
  y = nil -- 変数yを宣言し、明示的にnilで初期化している
  I:Log(y) -- ログ欄に空行が出力される
  y = 1
  I:Log(y) -- ログ欄に1が出力される
end

テーブルで存在しない要素を指定するとnilが返ってきます。

function Update(I)
  I:ClearLogs()
  x = {1, 2, 3}
  I:Log(x[1]) -- ログ欄に1が出力される
  I:Log(x[4]) -- ログ欄に空行が出力される
  I:Log(x[2]) -- ログ欄に2が出力される
end

テーブルの要素にnilがあると、要素数が予期しない結果になる場合があります。

function Update(I)
  I:ClearLogs()
  x = {1, nil, 3}
  I:Log(#x) -- ログ欄に1が出力される
  x = {1, nil, 3, 4}
  I:Log(#x) -- ログ欄に4が出力される
  x = {1, 2, nil}
  I:Log(#x) -- ログ欄に2が出力される
  x = {1, 2, nil, 4}
  I:Log(#x) -- ログ欄に4が出力される
end

関数

関数は、箱を受け取って箱の中身を取り出し、
何かの処理をします。
書式はfunctionで始まり、endで終わります。

function 関数名(引数)
  -- 何か処理
end

関数名には英字・数字・アンダーバーを使えます。
LUA boxにデフォルトで書いてある、

function Update(I)
-- put your code here
end

もUpdateという名前の関数です。
関数は独自で作れ、Update(I)や作成した関数から呼び出すことができます。

function Update(I)
  I:ClearLogs()
  MyMethodAaa(I, 1, 2)
end
function MyMethodAaa(I, a, b)
  I:Log(a) -- ログ欄に1が出力される
  MyMethodBbb(I, b)
end
function MyMethodBbb(I, b)
  I:Log(b) -- ログ欄に2が出力される
end

引数

引数は、関数が呼び出し元から値を受け取ります。
引数はカンマ区切りで複数指定できます。

function Update(I)
  I:ClearLogs()
  MyMethodAaa(I, 10, "a")
end
function MyMethodAaa(I, arg1, arg2)
  I:Log(arg1) -- ログ欄に10が出力される
  I:Log(arg2) -- ログ欄にaが出力される
end

関数に渡すものがなければ引数は不要です。

api = nil
function Update(I)
  I:ClearLogs()
  api = I
  MyMethodAaa()
end
function MyMethodAaa()
  api:Log("aaa") -- ログ欄にaaaが出力される
end

呼び出し側で引数を渡し忘れると、関数にはnilが渡ります。

function Update(I)
  I:ClearLogs()
  MyMethodAaa(I)
end
function MyMethodAaa(I, arg)
  if arg == nil then
    I:Log("nil") -- ログ欄にnilと出力される
  end
end

戻り値

戻り値は、引数とは逆に呼び出し元に値を返します。
returnで指定します。

function Update(I)
  I:ClearLogs()
  x = GetAaa()
  I:Log(x) -- ログ欄にresultが出力される
end
function GetAaa()
  return "result"
end

変数への代入

関数は変数に匿名(関数名なし)で代入できます。

function Update(I)
  I:ClearLogs()
  x = function()
     return "result"
  end
  y = x()
  I:Log(y) -- ログ欄にresultが出力される
end

演算子

算術演算子

number型の値に使えます。

+加算
-減算
*乗算
/浮動小数点数除算
%剰余
^累乗
-単項マイナス
function Update(I)
  I:ClearLogs()
  x = 10
  I:Log(x + 1) -- ログ欄に11が出力される
  I:Log(x - 1) -- ログ欄に9が出力される
  I:Log(x * 2) -- ログ欄に20が出力される
  I:Log(x / 2) -- ログ欄に5が出力される
  I:Log(x % 7) -- ログ欄に3が出力される
  I:Log(x ^ 2) -- ログ欄に100が出力される
  I:Log(-x) -- ログ欄に-10が出力される
end

※切り捨て除算//はありません。

関係演算子

tureかfalseを返します。

==等しい

=

等しくない
<より小さい
>より大きい
<=小さいまたは等しい
>=大きいまたは等しい
function Update(I)
  I:ClearLogs()
  x = 10
  if x < 11 then
    I:Log("1") -- ログ欄に1が出力される
  end
  if x < 10 then
    I:Log("2") -- ここは通らない
  end
  x = false
  if x == false then
    I:Log("3") -- ログ欄に3が出力される
  end
  if x ~= false then
    I:Log("4") -- ここは通らない
  end
end

論理演算子

falseとnilを偽、それ以外を真とみなします。

and左項と右項が真のとき真を返す
or左項または右項が真のとき真を返す
not真(偽)のとき偽(真)を返す
function Update(I)
  I:ClearLogs()
  I:Log(10 or 20)       --> 10
  I:Log(nil or "a")     --> "a"
  if (false and nil) == false then --> false
    I:Log("false and nil")
  end
  I:Log(10 and 20)      --> 20
  if (nil and 10) == nil then --> nil
    I:Log("nil and 10")
  end
  if (false or nil) == nil then --> nil
    I:Log("false or nil")
  end
end

制御構文

if文

分岐。条件が真の時に中の処理を実行します。
条件はfalseとnilを偽、それ以外を真とみなします。
書式は以下の通り

if 条件 then
  何か処理
end
function Update(I)
  I:ClearLogs()
  x = true
  if x then
    I:Log("1") -- ログ欄に1が出力される
  end
  x = false
  if x then
    I:Log("2") -- ここは通らない
  end
end

if、else、elseifで分岐を増やせます。

function Update(I)
  I:ClearLogs()
  x = true
  if x then
    I:Log("1") -- ログ欄に1が出力される
  else
    I:Log("2") -- ここは通らない
  end
  x = false
  if x then
    I:Log("1") -- ここは通らない
  else
    I:Log("2") -- ログ欄に2が出力される
  end
  x = 2
  if x == 1 then
    I:Log("11") -- ここは通らない
  elseif x == 2 then
    I:Log("12") -- ログ欄に12が出力される
  else
    I:Log("13") -- ここは通らない
  end
end

for文

ループ。指定した回数、処理を繰り返します。

function Update(I)
  I:ClearLogs()
  for i = 1, 10, 2 do -- 変数iに1から10まで、2ずつ増やしながら繰り返す
    I:Log(i) -- 1, 3, 5, 7, 9 が出力される
  end
  for i = 11, 15 do -- 変数iに11から15まで、1ずつ増やしながら繰り返す。増分が1の場合省略できる
    I:Log(i) -- 11, 12, 13, 14, 15 が出力される
  end
  for i = 20, 25 do -- 変数iに20から25まで、1ずつ増やしながら繰り返す。増分が1の場合省略できる
    if i == 23 then
      break -- break文でループから抜け出す
    end
    I:Log(i) -- 21, 22 が出力される
  end
end

テーブルの中身をループで処理できます。

function Update(I)
  I:ClearLogs()
  x = {11, 12, 13, 14}
  for i = 1, #x do
    I:Log(x[i]) -- 11, 12, 13, 14 が出力される
  end
end

連想配列の中身を処理する書き方もあります。(ただし比較的重い)

function Update(I)
  I:ClearLogs()
  x = {a = 11, b = 12, c = 13, d = 14}
  for k,v in pairs(x) do
    I:Log(k) -- a, b, c, d が出力される
    I:Log(v) -- 11, 12, 13, 14 が出力される
  end
end

while文

ループ。条件が真の間、処理を繰り返します。

function Update(I)
  I:ClearLogs()
  i = 1
  while i < 10 do
    i = i + 1
    I:Log(i) -- 1から10が出力される
  end
  while i < 20 do
    i = i + 1
    if i == 13 then
      break -- break文でループから抜け出す
    end
    I:Log(i) -- 11, 12が出力される
  end
end

repeat文

条件の判定が処理の後に来るループです。

function Update(I)
  I:ClearLogs()
  i = 1
  repeat
    i = i + 1
    I:Log(i) -- 2から11が出力される
  until i > 10 -- ループから抜ける条件
end

スコープとlocal

function, if, while, forなどからendまで(とrepeat~until)をブロックと言います。
変数にはローカル変数とグローバル変数があります。
ローカル変数は、宣言されたブロック内でしか使えません。
グローバル変数はどこでも使えます。

ローカル変数

変数の宣言時、変数の前にlocal を付けるとローカル変数になります。

function Update(I)
  I:ClearLogs()
  if true then
    -- ブロック
    local a = 1
    I:Log(a) -- 1が出力される
  end
  I:Log(a) -- 出力されない
end

グローバル変数

x = 1 -- グローバル変数
function Update(I)
  I:ClearLogs()
  y = 2 -- グローバル変数
  if true then
    -- ブロック
    z = 3 -- グローバル変数
  end
  Log1(I)
end
function Log1(I)
  I:Log(x) -- 1が出力される
  I:Log(y) -- 2が出力される
  I:Log(z) -- 3が出力される
end

実行される順番

function Local_A(I) -- Updateから呼ばれる
  I:Log("loca_a")
end
global_a = "global_a" -- Updateより先に実行される
function Update(I) -- functionのうち最初に実行される
  I:ClearLogs()
  I:Log(global_a)
  I:Log(global_b)
  Local_A(I)
  Local_B(I)
end
global_b = "global_b" -- Updateより先に実行される
function Local_B(I) -- Updateから呼ばれる
  I:Log("loca_b")
end

関数を記述する順番に決まりは無いので、
Updateを最初に書く人と、最後に書く人がいます。

LUAの標準関数

LUAには自作しなくても使える標準の関数があります。
LUAのリファレンスマニュアルを参照してください。
一部がFtDで使用できます。
以下はよく使うかもしれません。

  • math.~
  • string.~
  • table.~

self

特殊な変数。
テーブルに関数を持たせた時、その関数がそのテーブルを参照するのに使います。
関数の引数の1個目にselfを定義します。

table = {
  id = 10,
  LogId = function (self, I)
    I:Log(self.id)
  end
}
function Update(I)
  I:ClearLogs()
  table.LogId(table, I) -- 10が出力される
  table:LogId(I) -- コロンを使うと第1引数のselfを省略できます
end

上記と同じ内容で別の書き方その1

table = {}
table.id = 10
table.LogId = function (self, I) -- 上記と同じ内容で別の書き方
  I:Log(self.id)
end
function Update(I)
  I:ClearLogs()
  table.LogId(table, I) -- 10が出力される
  table:LogId(I) -- コロンを使うと第1引数のselfを省略できます
end

上記と同じ内容で別の書き方その2

table = {}
table.id = 10
function table.LogId(self, I) -- 上記と同じ内容で別の書き方
  I:Log(self.id)
end
function Update(I)
  I:ClearLogs()
  table.LogId(table, I) -- 10が出力される
  table:LogId(I) -- コロンを使うと第1引数のselfを省略できます
end

上記と同じ内容で別の書き方その3

table = {}
table.id = 10
function table:LogId(I) -- 上記と同じ内容で別の書き方。コロンでselfを省略
  I:Log(self.id)
end
function Update(I)
  I:ClearLogs()
  table.LogId(table, I) -- 10が出力される
  table:LogId(I) -- コロンを使うと第1引数のselfを省略できます
end

FtDのAPI

ここからやっとLUA Boxの外と戯れることができます。
APIとは一般IT用語で、Application Programming Interfaceの略です。
FtDとLuaコードがやり取りをするための窓口です。

function Update(I)
end

の関数Updateの引数IがAPIにアクセスするためのインターフェイスです(多分InterfaceのI)
ここまで使って来たI:Log()もAPIです。
APIを使用するにはこのIが必要なので、関数の引数にはIを指定しておくことをお勧めします。

function Update(I)
  I:ClearLogs()
  LogAaa(I) -- Iを引数で渡す
end
function LogAaa(I) --Iを引数で受け取る
  I:Log("aaa")
end

詳しくはLUA_ヘルプドキュメントを参照してください。

I.とI:

I.Fleet などのI.(ドット)で始まるものと、
I:Log()などのI:(コロン)で始まるものがありますのでご注意ください。
I.~は変数(に似たプロパティというもの)
I:~は関数です。

ざっくりしたLUAでできること

LUA_ヘルプドキュメントのカテゴリごとに、それぞれどんなことができるのかをざっくりまとめてみました。

Logging/Debugging
ログ関連。LUA boxのエディタや、HUDにログを出力します。
Fleet Awareness
艦隊関連。艦隊を組んでいる時の僚艦の情報やどれが旗艦かなど。
FleetInfo
艦隊のビークル一つ分の情報
Resources
リソースゾーン関連。
ResourceZoneInfo
リソースゾーンの情報
ResourceInfo
自機のリソース情報。資源統合前のもので、今はもう使わない。
AI
AI関連。Cキーで開いた画面でON/OFFするのと同じことができる。
BlueprintSpawnerInfo
BlueprintSpawnerの情報
Propulsion
推進関連。AIと同じように、前進後退姿勢制御などの推進要求を出せる。
TargetInfo
敵関連。Mainframeが認識している敵の情報を取得できる。
TargetInfo
敵の情報
TargetPositionInfo
敵の位置情報。
Misc
その他。ゲーム時間や任意の位置の地表の高さ、ある高度の重力、風向きと風速などなど。
Self awareness
自機関連。位置、姿勢、資源、出力、BP名など。
Components
コンポーネント関連。バルーンやエアポン、ギャザラーにエンジン、ワープなど35種のパーツを操作できる。
components type and their logic
コンポーネントの種類。
BlockInfo
ブロックの情報。位置、向き、名前など。
Weapons
武装関連。狙ったり撃ったり。
WeaponInfo
武装情報。位置や弾速、武器種など。
WeaponConstraints
射角制限の情報。
Missile Warning
ミサイル関連。ワーナーで検知した敵ミサイル。
MissileWarningInfo
ミサイル情報。位置、速度、距離など。
MissileGuidance
自機のミサイル関連。LuaTranceiverを付けたミサイルを操作する。
SpinBlocks and pistons
スピブロ、ピストン、デディケイテッドブレード関連。回したり伸ばしたり。
SubConstructs
サブジェクト関連。サブオブジェクトの各種情報を取得する。
Friendlies
友軍関連。友軍の情報を取得する。
FriendlyInfo
友軍の情報。位置、姿勢、速さ、大きさ、資源など。
Math and Other
3次元情報をいじるのに便利な関数群

複数のLUA box

LUA boxはそれぞれ独立して実行されます。実行順は不明(多分置いた順)
独立しているので、複数のLUA boxで変数の共有などはできません。
別のLUA boxに同じ名前の変数があっても、上書きされることはありません。
LUA box間でデータをやり取りしたい場合、spotlightやair pumpなどのコンポーネントで中継すればできなくもないです。多分。

よくある命名規約

変数や関数の命名は何でも良いのですが、後から読みやすくしたり、他人が読みやすいように、
暗黙的なルールがあります。
ただし人によって異なります。

変数

略語を使うと半年後の自分が困ります。

スネークケース
小文字とアンダーバーで構成される。例)from_the_depths
キャメルケースまたはローワーキャメルケース
最初の単語は小文字で、以降の単語は大文字始まり。例)fromTheDepths

定数

LUAの仕様上定数はありませんが、処理の中で値が書き換わらない、つまり固定値のことを定数と呼んだりします。
大文字とアンダーバーで構成される。例)FROM_THE_DEPTHS

関数

パスカルケースまたはアッパーキャメルケース)
単語は大文字始まり。例)FromTheDepths
スネークケース
小文字とアンダーバーで構成される。例)from_the_depths
FtDのAPIは、一部アンダーバーがあるものの大体はパスカルケース。
恐らくマイクロソフトのガイドラインに準拠。

よくあるハマりポイント

indexが0始まりと1始まりがある

LUAのテーブルは数字指定でアクセスする際、1から始まる連番を指定しますが、
FtD APIの○○Index(I:GetNumberOfTargets(mainframeIndex)など)は0から始まる連番です。

function Update(I)
  I:ClearLogs()
  local a = {1, 2, 3}
  for i = 1, #a do
    I:Log(i) -- 1~3が出力される
  end
  local mainframeCount = I:GetNumberOfMainframes()
  for mainframeIndex = 0, mainframeCount - 1 do
    local targetCount = I:GetNumberOfTargets(mainframeIndex)
    I:Log(targetCount) -- Mainframeが認識しているターゲットの数が出力される
  end
end

if文で==のつもりが= / ~=のつもりが=~

function Update(I)
  I:ClearLogs()
  a = 10
  if a == 10 then -- OK
  end
  if a = 10 then -- NG。エラー
  end
  if a ~= 8 then -- OK
  end
  if a =~ 8 then -- NG。エラー
  end
end

F8押しても適用されていない?

気のせいなのかバグなのか、たまにF8を押してもコードが適用されていないような気がするときがあります。
その場合は、適当に空行を追加してF8を押しましょう。
何度かやればきっと適用されています。

その他

文字列連結

ピリオド2つ(..)で文字列を連結できます。

function Update(I)
  I:ClearLogs()
  a = "a"
  x = "name"
  I:Log(a .. ", " .. x) -- a, name と出力される
  -- 数値が混じってもOK
  b = 100
  I:Log(b .. "sec") -- 100sec と出力される
end

コメント