LuaからNScripterのネイティブ命令を簡単に実行する。

exec.lua

Lua側から、NScripterのネイティブ命令を簡単に実行、その結果も取得できるようにしたライブラリ。
Exと言うグローバル変数を導入し、それに命令名を追加することでネイティブ命令を実行する。

exec.lua

-- exec.lua
-- Lua側から、NScripterのネイティブ命令を実行するためのライブラリ
do
	-- lua側とNScripter側の値を交換するためのワークエリア領域の定義
	local variable_min = 980
	local variable_max = 999

	-- ワーク領域の定義
	local variable_int_list = {}
	local variable_str_list = {}
	for i = variable_min, variable_max do
		variable_int_list[1+#variable_int_list] = i
		variable_str_list[1+#variable_str_list] = i
	end
	
	local get_next_int = function()
		local res = table.remove(variable_int_list, 1)
		variable_int_list[1+#variable_int_list] = res
		return res
	end
	
	local get_next_str = function()
		local res = table.remove(variable_str_list, 1)
		variable_str_list[1+#variable_str_list] = res
		return res
	end

	local exec_list = {}

	-- 引数用特殊関数定義
	iRet = function() end
	sRet = function() end

	-- ラベル定義
	local label_list = {}
	local lbmt = {}
	lbmt.__index = function(t, k)
		label_list[k] = label_list[k] or function() return "*"..k end
		return label_list[k]
	end
	lbmt.__newindex = function(t, k, v)
		NSOkBox("代入はできません。", "Lb")
		NSEnd()
	end
	Lb = setmetatable({}, lbmt)

	local id_list = {}
	local idmt = {}
	idmt.__index = function(t, k)
		id_list[k] = id_list[k] or function() return k end
		return id_list[k]
	end
	idmt.__newindex = function(t, k, v)
		NSOkBox("代入はできません。", "Id")
		NSEnd()
	end
	Id = setmetatable({}, idmt)
	
	-- メインの定義
	local mt = {}

	mt.__index = function(t, k)
		if not(exec_list[k]) then
			local com = "_"..k:lower()
			exec_list[k] = function(...)
				local str = com
				local res = {}
				for i, v in ipairs({...}) do
					if i==1 then str = str.." " else str = str.."," end
					    if type(v)=="number" then str = str..tostring(v)
					elseif type(v)=="string" then
						local c = get_next_str()
						NSSetStrValue(c, v)
						str = str.."$"..tostring(c)
					elseif type(v)=="function" then
						    if v==iRet then
							local c = get_next_int()
							str = str.."%"..tostring(c)
							res[1+#res] = function () return NSGetIntValue(c) end
						elseif v==sRet then
							local c = get_next_str()
							str = str.."$"..tostring(c)
							res[1+#res] = function () return NSGetStrValue(c) end
						else
							str = str..v()
						end
					elseif type(v)=="boolean" then
						if v then str = str.."1" else str = str.."0" end
					else
						NSOkBox("無効な型の引数が指定されました。", "exec")
						NSEnd()
					end
				end
				NSExec(str)
				if 0<#res then for i=1, #res do res[i] = res[i]() end end
				return unpack(res)
			end
		end
		return exec_list[k]
	end

	-- 代入時の動作定義。代入はできない。
	mt.__newindex = function(t, k, v)
		NSOkBox(k.."命令を再定義しようとしました。", "exec")
		NSEnd()
	end
	
	Ex = setmetatable({}, mt)
end

注意点

動作を少しでも早くするため、NScripter側の変数のうち、980〜999までをこのライブラリで専有します。
この部分をいじってしまうと、動作の保証はありません。
なお、この変数の範囲は、ライブラリ本文の冒頭、variable_minとvariable_maxによって変更できます。

使い方

Exの後に、.と命令名を追加、最後に()をつけると、NScripterのその命令が実行されます。
Ex.texthide()
-- 上記は、下記と同様の動作をする。
NSExec("_texthide")
引数の必要な命令の場合、括弧内に記述することができます。
Ex.movemousecursor(100, 100)
-- 上記は、下記と同様の動作をする。
NSExec("_movemousecursor 100,100")

単純な数値や文字列であれば、それをそのまま記述すれば大丈夫です。
また、bookean(true/false)を記述すると、自動的に1/0に変換します。

もし、返り値を取得する命令であれば、以下のように記述します。
local mouse_x, mouse_y = Ex.getmousepos(iRet, iRet)

返り値を取得した変数部分に、数値変数ならばiRetを、文字列変数ならばsRetを置いてください。そうすると、関数が実行時に返り値を返すようになります。

引数にラベルを取る場合は以下のように記述します。
Ex.gosub(Lb.gosub_label)
-- 上記は、下記と同様の動作をする。
NSExec("_gosub *gosub_label")

gosubはNSGosubを使うべきなので、例としてはあまり適当ではないですが。

引数にIDを取る場合は以下のように記述します。
Ex.ld(Id.c, ":a;tatie.jpg", 1)
-- 上記は、下記と同様の動作をする。
NSExec("_ld c,\":a;tatie.jpg\",1")
もっと使いやすくするには。
local short_cut = Ex.command -- 括弧無しで呼び出す。
short_cut() -- 任意に実行できる。
-- 命令名を簡略化したりするのに使える。