NSLaマニュアル


※まだ目次作りの段階です

1.1 - このマニュアルに関して

★想定する用途書いた方が良くない?

1.1.1 - 想定する利用者の練度

NSLaおよびこのマニュアルは、素のNScripterに関する知識(Luaと狭義のシステムカスタマイズは含みません)を暗黙の前提としています。言い換えると、読み手が以下のどちらかの状態にあることを想定しています。

@NScripterは分かるがLuaは分からない
ANScripterもLuaも分かる

この暗黙の前提に基づき、NSLa独自の文法を解説する際に「NScripterではmov $0,""のように値を代入しますが…」といった書き方をせず、「従来の命令に加え…」とだけ書くかもしれません。

その上で@・A両方の層に対応するために、本マニュアルは以下のような記述形態を採ることにします。

1.1.2 - マニュアル内の表記ルール

「できることならLuaの知識を踏まえて読んで欲しい解説」には青色のマーカーを用います。
たとえば、「NSLaではローカル変数を利用できます」といった具合です。 「Luaは一切分からない」という人は青色マーカーの記述を読み飛ばしてください。

「オプションから変更できる挙動、およびNScripter目線(配布状態の動作サンプル)では正しいがLua目線(およびNSLaの実際の仕様)としては間違っている解説」には緑色のマーカーを用います。
たとえば、「NSLaは000.txt〜255.txtを読み込みます」といった具合です。

NSLaの実体は配列に読み込んだスクリプトを実行する(NSExec()やloadstring()のような)関数です[3.1](実際、関数としてLuaから実行できます)が、 混乱を避ける目的から、ある項目(追加/変更される文法や機能)についてNScripterの延長で解説できる限り、NScripter目線で記述することにします。

★は思いっきり書きかけの項目に付けている目印です。あと一か月くらいかかりそうです…

1.1.3 - マニュアルで使用する用語

「素のNScripter」「NScripter本体」と書いた場合、NSLaを導入していない本来のNScripter(における文法ルール)を指します。
このマニュアル執筆時点ではバージョン3.03が最新版です。

「生の文字」と書いた場合、原則として""で括られた文字列を意味します。「生の数字」と書いた場合も、同様に、変数記述ではない数字そのものを意味します。

「命令」と書いた場合、NScripterの命令全般を指します(Luaに命令という概念は(誤解を恐れずに言えば)存在しません)。

「引数」と書いた場合、命令または関数に渡される文字や数字などの値を意味します。
lsp 1,"foo.png",0,0なら4つの引数がlspに渡されており、alert("text","title")なら2つの引数がalertに渡されています。n番目の引数は一般に第n引数と呼ばれます。

「評価する」と書いた場合、「(該当する文字列を)処理・実行する」と読み替えて構いません。
たとえば「“$0,$1=$1,$0”の右辺を評価し、それから代入する」という文章は、
@右辺の「$1,$0」が具体的な値に置き換わる A$0に$1の中身が、$1に$0の中身が代入される(→$0,$1の値が入れ替わる)
という二段階の操作を意味します。

「深度」または「gosub深度」と書いた場合、「(スクリプトの開始位置を基準に)何重にgosubしているか」を表す数値を指します。
一度もgosubしていない状態は深度1、3回gosubしていれば深度4です。
「あと何回returnすればスクリプトを抜け出せるか」と言い換えることもできます。

「ネスト」または「ifネスト」と書いた場合、「(該当深度の開始位置を基準に)何重にifが記述されているか」を表す数値を指します。
NSLaにおけるifの文法に関しては当該項目を参照してください[2.7](NSLaではLua方式のifを使用できます。)

Lua変数のうち、関数型については文中でhoge()のように表記することがあります。これは純粋に視認性を目的とした表記であり、当該関数が引数を持たないこと・関数呼び出しであることを即座に意味するものではありません。

1.2 - NScripterの何が変わるのか?

1.2.1 - NScripterへの文法の追加

★ こそLuaですが、Nスク拡張ライブラリとしての面が大きく ノベル用途 「結局何が新しくできるようになるのか、既存のスクリプト文法に何か影響・変化はあるのか」に絞って説明し、「それがいかなる原理で動いているのか(Luaです!)」に関する説明はほとんど全て後回しする事にしました Lua(や他の似たような言語)が頭に入っている人間にとって相当大きな違和感のある(または回りくどい)記述が混ざるかもしれません 一通りNScripter視点で要素を解説し 然る後にLuaの関連するギミックを種明かしするという順番

1.2.2 - Luaとの密な連携

たとえば、「文字変数$0に文字$1は含まれているか?」を確かめるために、検索&抽出を行いたいとします。Luaにはstring.matchという関数(≒命令)が用意されています。
これをNScripterから使用する場合、標準ではこうです。

--【Lua側】 function NSCOM_match() local num, str, key = NSGetStrRef(), NSGetPopInt(NSPopComma()), NSPopStr(NSPopComma()) NSSetStrValue(num, (str:match(key) or '×')) end NSExec("luasub match") ;【NScripter側(00.txt)】 match $0,$0,$1

「標準関数を一つ呼びたいだけなのに別ファイルを用意し、標準関数を呼ぶだけの関数を作り、luasubする」という手順は、作業効率の上でも見かけの上でもスマートではありません。サウンドノベル用途に限れば文字列操作をする機会は皆無ですが、そうでない用途においては不便さが残ります。
拡張スクリプトではこうです。

;【拡張スクリプト(000.txt)】 $0=^^string.match("文字列","チェックするキーワード") or '×'^^

1.2.3 - LuaからNScripterのコードを利用する

1.3 - NSLaが必要とする(予約する)リソース

NSLaが使用(または予約)するNScripter/Luaの変数、luasub命令、コールバックについて、以下に載せておきます。
既存のスクリプトをNSLa用にコンバートする場合変数に関しては恐らく問題になりませんが、既存の命令乗っ取りやコールバックと衝突する場合は個別に調整が必要になります[2.16.6]。

1.3.1 - Lua変数

「語頭が『NSNS』であるLuaグローバル変数」を予約させてください。
NSLaの挙動を設定するオプションについては、全てNSNS〜という名前で定義されています[4.1]。それ以外の変数は内部処理に用いています。
たとえば拡張スクリプトはNSNSgyoに格納されており、NSNSsaveonがsaveon状態か否かを管理しています。
既にLuaスクリプトを使用している等の理由からグローバル変数を好まず、かつrequire等で調整出来る人は必要に応じて調整してください(名前が衝突する可能性は低いと思いますが…)

NSNSでは始まらない変数として、以下の関数を定義しています。
string.split() alert() ensafe()
これらは内部動作に使用していないため、必要に応じて上書きしても構いません。

デフォルトのLua関数のうち、error()のみ上書きしています(拡張スクリプトにおけるエラー発生箇所を表示するため)。 内部ではNSNSerror()の形で処理しているため、不都合なら再上書きしても構いません。

上記以外に、NSLaの実行そのものが定義された関数として以下を使用しています。 nsload() nsloadfile() ns() nsfile() nsboot()
詳細については拡張スクリプトの動的な読み込みと実行[3.2]を参照してください。

1.3.2 - NScripter変数

Lua変数NSNSSaveHensuで指定した番号の文字変数(通常変数が望ましい)を1つ使用します。
デフォルトではNSNSSaveHensu=199と定義されていますが、極力通常変数末尾に近い(使わない)番号を指定してあげてください。
この変数は内部情報(ロード時戻り行など)の記録場所として利用され、一部の内部処理でも予約されています。

NScripter変数のローカル化機能(localalias/setvar命令)[2.5]を利用する場合、指定した範囲の文字・数字変数がNSLa側の処理で使用されます。これも通常変数を指定してください。同梱の000.txtでは以下のように設定されています。

localalias 1000,1255 setvar 1256,1511


また、同梱の00.txtでは;$V4095G2000S640,480L10000、つまり2000番以降をグローバル変数に割り当てています。

1.3.3 - 予約語(luasub/defsubできない命令)

以下の命令はNSLa内部で個別に処理されており、defsubluasubは出来なくなっています。 defsub mov if elseif else end outif killif for next break continue do while repeat until switch case default fallthrough reset nsbreak nsend goto gosub return tablegoto skip jumpf jumpb trap rtrap lrtrap select selgosub--selnumは可 local var
これらは主にスクリプト位置やNSLaの命令実行そのものに干渉する語(制御文)です。
素のNScripterではテキスト表示以外のあらゆる記述が等しく「命令」として扱われ、defsubで乗っ取り可能になっています(結果として、NScripterではifやforを上書きすることもできます)。
Luaを含む多くの言語ではそのようになっていません。

1.3.4 - 乗っ取り済みのluasub命令

★以下の命令がluasubされています。ロード後復帰用にログを取っているだけのものから内部動作に深く関わるものまで様々です。 main domain english savedir savegame savepoint saveon saveoff loadgame systemcall setwindow setwindow2 setwindow3 puttext clickstr linepage trap r_trap lr_trap rmode loadgosub textcolor textclear numalias stralias automode_time --新旧ボタン関連全て セーブデータに用いるログ取り用途・環境の記録 btnwait bclear btndef spbtn cellcheckspbtn btnex btncellcheck exbtn btnarea getcursor getenter getfunction getinsert getmclick getpage gettab getzxc spclclk bsp bcursor bdown btrans btndown bdef btime btntime btntime2 exbtn_d -- kidokumode filelog labelexist ld cl bg textspeed textspeeddefault indent texton textoff texthide textshow bgm bgmstop nsnsaliasnakami--デフォルト命令ではない(上に内部的にも必然性はない(古い)が許して) localalias --デフォルト命令ではない。通常変数内部にローカルエイリアス領域を予約する setvar --デフォルト命令ではない。通常変数内部にvar変数領域を予約する

1.3.5 - コールバックに関して

以下のコールバックを利用しています。自分で定義する場合は案内に従ってください。
NScall_animation() NScall_load() NScall_end() NScall_savepoint() 内部からそれぞれ NSNScall_animation() NSNScall_load() NSNScall_end() NSNScall_savepoint() を呼び出してください(つまりNSを一つ余分に書いたものを呼びます)。
たとえばNSLaデフォルトのloadコールバックは function NSCALL_load() NSNSCALL_load() end と定義されています。
NScall_close() 終了前にNSNSsafeend=trueと代入しておいてください。

以下のコールバックはデフォルトで定義されていませんが、定義されている場合のみ内部から呼び出されます。
NSCALL_text0() 文頭で呼び出されます。
文字列を返すとテキストがすり替わり、falseを返すとテキスト表示を中止します。
NSCALL_tag() 文頭で呼び出されます。
NSCALL_tagにラベル名または関数が代入されていた場合、
pretextgosub/zenkakko命令相当の処理を期待してタグ内部のテキストが渡されます。
※Nスク本来の挙動(クリック待ち毎の判定)と異なるため注意してください。

NSCALL_textは使用できません。入力待ちをカスタマイズする関数としてNSNSclickwait()が用意されています[2.6.6]。

2.1 - NSLaの導入方法

2.1.1 - NSLaの最小構成

NSLua主体のプロジェクトにNSLaを組み込む手順に関しては、[3.1.1]を参照してください。

「NScripter風に動く」スクリプトを新規に作成する場合は、同梱ファイルをそのまま利用できます。 動作に最低限必要なファイルは以下の通りです。

NSLA.lua NSLaの実体です。同梱のsystem.luaからdofileされています。
関数等の定義はこのファイルで行われています。
system.lua NSLaを呼び出しています。
同梱のsystem.luaには「NScripterであるかのように」動かすためのコードが書かれてあります[3.1.2]。
00.txt NSLAの処理そのものには基本的に用いられません。
現在のNScripterは00.txt〜99.txt抜きでも(system.luaのみで)動作しますが、 その状態ではセーブ処理やrmenuが不安定になるようです。
また、処理順の関係から上部メニュー設定(insertmenu/resetmenu等)のみは00.txtで処理する必要があります。
そうした理由から、NSLaでは(実際の動作上はほとんど無関係であるにも関わらず)00.txtの存在を推奨しています。
同梱サンプルでは1行目の初期定義と上部メニュー設定、NSLaの開始処理(NSCOM_main()の呼び出し処理)のみ行っています。
000.txt〜255.txt ここに拡張スクリプトを記述します。同梱したsystem.luaでは起動時に「能動的に」000.txt〜255.txtを読み込み、その後*defineと*startから実行しています。
具体的にはNSNSinitializing()関数によって連番スクリプトを読み込み[3.2.1]その後nsboot("*define")とnsboot("*start")を実行しています[3.2.3]。
読み込むファイルや実行するラベルは任意に変更可能です。したがってLua視点においてこれらのファイルは必須ではありません。

既存のスクリプトをNSLaに対応させたい場合、NScripterと仕様が異なる部分を修正する必要があります。 コンバートツールでは自動変換されない内容について、手作業で確認する必要があります。
適用したいスクリプトが以下の条件にあてはまっていないか確認してください。
★コンバートツールの警告検知機能をもう少し更新する ★リンク貼る

システムカスタマイズ(※)している
(※…クリック待ちの乗っ取り)
NSLaではクリック待ちの乗っ取り方が異なります。
若干量を手作業で修正する必要があります。
既存の命令をdefsubしている 予約語やluasub命令との衝突を確認する必要があります。
既にNSLuaを利用している コールバックやluasub命令の衝突を確認する必要があります。
自動変換できない非互換性を含む 手作業でスクリプトを修正する必要があるかもしれません。
NSLa非対応文法(※)を含む
(※…主にテキストボタン)
NSLaを適用することはできません。

2.1.2 - 同梱dllフォルダの中身について(前提プラグイン)

公式同梱のdll以外については、NScripterプラグインに関するまとめ[別ページ]を参照してください。

nslua.dll NScripter公式サイトで提供されています。NSLa以前にLuaの利用で必須です。
nspng.dll
nsogg2.dll
NScripter公式サイトで提供されています。NScripter本体に付属するdllです。
deffontd.dll
dpshadow.dll
サンプルコード(ノベル向け追加コード)内部でテキスト表示乗っ取りに使用しています。
NSLa本体で直接使用はしていません。

以下のdllは同梱していませんが、利用(exeと同じ階層またはdllフォルダに存在する状態)を想定したコードを含んでいます。

NScripterDS.dll ogg形式のファイルを高度に再生することが出来ます。オートモード時のボイス待ちは「このプラグインかつラッパーのnds関数」または「NSOgg2.dll」を前提にしています。
fileutil.dll 「フォルダ作成・削除、ファイル読み書き名前変更プラグイン」という名称で配布されています。NSLaはセーブ・ログ用のフォルダが存在しない場合にこのプラグインを使って自動作成しようとします。

2.1.3 - 同梱の00.txtがやっていること

NSLaの最小構成[2.1.1]で説明した通り、ここでは初期定義(;$V4095G2000S640,480L10000)と上部メニューの操作(に関する説明、実際には何も操作していません)とNSCOM_main関数の呼び出しのみ行っています。
その他の「定義節で行うべき処理」は000.txt(拡張スクリプトの*defineラベル以下)に記述されています。

2.1.4 - 同梱の000.txtがやっていること

NScripterの定義節で一般に呼ばれる命令(numaliasやeffectなど)に加え、ローカル変数[2.5]の使用準備やオプションの指定(主にログ利用に関する宣言)を行っています。個々に説明を付けているので、詳しくは中を覗いてみてください。

2.2 - 起動とスクリプトの読み込み

2.2.1 - スクリプトのファイル名と置き場所

配布状態のNSLaは、起動時に000.txt〜255.txtをスクリプトとして読み込むようにしています。 これについてはフォルダ位置・ファイル名ともにオプションから変更可能です。
ファイルアーカイブ(テキストアーカイブではない点に注意してください)からも問題なく読み込みます。

2.2.2 - コメントアウト/複数行コメントアウト(; -- ;[[〜]] --[[〜]])

複数の行をまとめてコメントアウトできます。 ;[[ ここから ここまで ;]]

入れ子にすることもできます。 ;[[ 入れ子にする場合は ;[=[ このように任意個のイコールを挟むことで ;]=] 多重に記述できます。 ;]]

Luaの書き方(--、ハイフン2つ)も利用できます。 --このように --[[ まったくのLua風な表記も --[==[ 通るように --]==] なっています。 --]] ただし、 %0--と記述した場合のみdec %0と認識されます[2.3.4]。

2.2.3 - 大文字・小文字に関する注意

NSLaでは原則として小文字で命令を記述してください。
特にfor/gotoなどの予約語[1.3.3]は大文字を認識しません。(ns関数内部をmeirehead=meirehead:lower()するように書き換えればその限りではありませんが…)
本来のNScripterは命令の大文字・小文字を問わない(正確には全て小文字に置き換えて実行しる)ため、この仕様はNSLaにおける非互換性の一つとなっています(この差異はコンバートツールによって自動変換されます[2.17.1])。

2.3 - 変数と四則演算

2.3.1 - 代入の略記($0,%0="あいう",100)

一括代入処理は、内部的にはNSNSmov()関数への文字列渡しです。

代入の略記が用意されています。

以下はmov %0,10の略記です。
%0=10

以下は%0=10 :$0="あいうえお"の略記です。
%0,$0=10,"あいうえお"

変数の範囲指定も行えます。以下は%0=0 :%1=1 :%2=2の略記です(複合ボタンの記述を思い出してください)。
%0-2=0,1,2
右辺で範囲指定を用いる場合は「-」の代わりに「#」を使います(右辺には式が来るかもしれず、-は使えないため)。 %0-2=%10#12

同じ型の変数を連続で指定する場合は変数記号($%)を省略しても構いません。
%0-2,4,10,$15=0,1,2,4,10,"15"

左右の辺で型が合わない場合は変換を試みます。 %0,%1,$2="123","あいうえお",456 -->%0=123 %1=0(変換失敗) $2="456"

右辺が不足している(項が左辺より少ない)場合、自動的に0または""が補われます。
%0,%1,%2,$3=0,1 -->%0=0 %1=1 %2=0 $3=""
反対に右辺が余った(項が左辺より多い)場合、余分な項は用いられません。
%0,%1=0,1,2,3 -->%0=0 %1=1 2,3は破棄

文字変数に全角文字を代入する場合のみ、文字を括る""を省略できます。
$0=あいうえお

右辺に式を記述しても構いませんが、文字列に計算式を結合する場合は()で括らないとエラーになります。
$0="あいう"+(15-1) -->"あいう14"
$0="あいう"+15-1 -->エラー!

代入略記における文字列の結合には、+(NScripter式)..(Lua式)のどちらを用いても構いません。
$0="あ"+"い".."う" -->"あいう"
代入略記以外のほとんどの箇所ではNScripter本来の結合表記(+での結合)のみを認めていますが、例外としてifの条件式[2.7]for[2.8]に限ってはLua風の表記(..)を用いる必要があります(他の記号を機械的に置き換えてLuaに判定を投げているため)。 文法としては完全に一貫性を欠きますが許してください。

2.3.2 - 代入略記における特殊な記号

右辺に値や変数ではなく「*」を指定すると、当該変数の初期化(0または"")を意味します。
右辺不足時に実際に補われているのはこの記号です。
%0,$0=*,*

右辺の変数/値/*の直後には、特別な末尾オプションを付加できます。

%0!左辺の残った項すべてに同じ値(%0)を代入します。
%0@左辺の当該項以降に同じ型(数値変数)が続く限り、同じ値(%0)を代入します。
%0@数字指定した個数分の項に一括代入します。"あ"@3"あ","あ","あ"と等価です。

# @ ! 表記いずれかの後に追加のオプション「?(数字)」を指定できます。
「?(数字)」を指定すると、連続して代入される値が(数字)または1ずつ増減します。負の値を指定しても構いません。
0@3?10 は 0,10,20 と等価です。
文字に対してこのオプションが指定されると、末尾に半角で番号を付与します。
【"ぬ"@3?】 は 【"ぬ1","ぬ2","ぬ3"】 と等価です。
【"ぬ"@3?4】 は 【"ぬ4","ぬ8","ぬ12"】 と等価です。
# @ ! を記述せずに?(数字)のみ指定した場合、「@?(数字)」の略記と見なします。
(左辺の型が変わるまで連続代入+(数字)ずつ増加or連番付与)
同様に、!(数字)は!?(数字)の略記と見なされます。
(左辺の残り全てに連続代入+加算または連番付与)

2.3.3 - 加減乗除と剰余の略記(%0+=100)

add,sub,mul,div,modに略記が用意されています。
%0+=100add %0,100の略記です。
%0-=100sub %0,100の略記です。
%0*=100mul %0,100の略記です。
%0/=100dib %0,100の略記です。
%0%=100mod %0,100の略記です(見づらいため注意)。
このうち+=のみは文字変数に対しても適用できます。他はエラーを返します。

剰余(割ったあまりの数、mod)を%で表すのはLua風の表記です(実際のところ、計算はLuaに投げています)。ところが%は数字変数の語頭でもあるため、NSLaでは剰余と数字変数の記号が衝突しています。
この衝突は、以下のような記述(数字変数による変数番号の指定)において、意図に反した動作を招くおそれがあります。
;【問題1】 %0=3 if(10 % %0==1) -->10 % 3==1 ;条件を満たす end if(10%%0==1) -->103==1 ;条件満たさず end ;【問題2】 %3=5 if(10 % 3==1) ;条件を満たす end if(10%3==1) -->105==1 ;条件満たさず end
これはif/for条件節が内部的にLuaスクリプトとして処理される仕様に由来する問題です[2.16.5]。
「NScripter変数を生の文字や数字に変換→Luaで判定」の順に処理されるため、「剰余と数字(変数)」がくっついて記述されていると、本来の意図がどうであれ「数字変数」や「数字変数で番号指定された数字変数」として解釈されてしまいます。

動作オプションの設定[4.1]次第では「` (Windowsキーボードではshift+@)」「(数字変数ではない)%」として解釈させる回避手段も用意されていますが、剰余を扱う際は極力半角スペースやタブを間に挿入すべきです。

一方代入略記[2.3.1]では独自に項を切り分けて処理されるため、剰余の直後に数字変数を記述しても正しく解釈されます。 %1=10%%0 -->%1=1

2.3.4 - inc/decの略記(%0++/%0--)

%0++inc %0の略記です。
%0--dec %0の略記です。
後者はLua風のコメントアウトと衝突する点に注意が必要です。
%0--
%0--;あいうえお
%0----あいうえお
%01減少させる(+注釈)」を表します
%0 --
%0--あいうえお
%0 --あいうえお
%0というテキスト(+注釈)」を表します
見ての通り原則として「よきにはからう」ようにはなっていますが、記述ミスには気を付ける必要があります。

2.3.5 - NSLaにおける配列の扱い(連想配列)

実際はLuaのグローバル変数(テーブル型)を埋め込んで使用しているだけです。[2.16.2]したがって以下の記述は読み飛ばして問題ありません。

NSLaで配列を用いるには、 foo={} のように定義を行う必要があります。このとき使用する名前は原則としてエイリアスと重複しないようにしてください。
配列に値を代入する場合は foo[1]="bar"のように表記します。代入する値の型は文字でも数字でも構いません。
命令の引数として値を呼ぶ場合はlsp 1,&foo[1],0,0のように&を付けて表記します。 この例ではfooという配列変数の1番に代入された値を呼び出しています。

添え字(上記例でいう1の部分です)に文字列を使うこともできます。&foo["あいうえお"]のように記述します。一般に、これは連想配列と呼ばれます。
★多次元配列の定義方法 dimの場合★ ★値の初期値は0ではない(nilである)点 ★1オリジンにすべきである点 ★保存方法

2.4 - エイリアス

2.4.1 - 文字変数によるエイリアス指定($$0,%$0)

NSLaでは$$0 %$0のように変数を記述することができます。つまり、エイリアス名を文字変数で指定することができます。
これは素のNScripterではエラーとなる記述です。
もちろん、従来の$%0 %%0つまり変数による変数番号指定もそのまま使えます。

2.4.2 - numalias時の注意点

★オプション次第では同名のLua変数にも同時に数値が代入される
その場合定数ではないのでその後他の値が代入されているかもしれない
★if/for内での呼び出しは怖いぞよ
★配列とエイリアス

2.5 - ローカル変数の定義と使用

2.5.1 - ローカル変数とは?

参照できる範囲が違う理由 原則として同じ名前は使えないという制約 NScripterの通常変数 Luaのグローバル変数 スクリプトのどこからでも参照できる (環境に関する話は省略します。) ローカル変数 いつでも定義できる 限られた場所でのみ使える 同じ名前を使うと★ ★定義節の命令で通常変数を割り振る準備 ★定義節でいちいちnumaliasする必要がないため便利という話 ★ただしLuaと違ってラベル外部(深度外、関数の外)にローカル変数を保存しておくことはできないという話

2.5.2 - 名前ありローカル変数(ローカルエイリアス)(/@hoge,fuga → $hoge %fuga)

名前の付いたローカル変数を用いたい場合、/@に続いてエイリアス名を記述します。
if($0==1) /@hoge $hoge="あいうえお" 値は「$hoge」です。 -->値は「あいうえお」です。 end 値は「$hoge」です。 -->未定義エラー!
複数のローカル変数を同時に定義することもできます。
/@hoge,fuga --$hoge,$fuga,%hoge,%fugaが用意される
定義時に初期値を代入することもできます。
/@hoge,fuga=15,"あいうえお" --$hoge="15",$fuga="あいうえお",%hoge=15,%fuga=0が用意される

2.5.3 - var変数(深度依存ローカル変数)

通常のローカル変数と異なり、var変数は定義したgosub深度でのみ使用できます。一方でifネストの制約はありません。
より深い深度にgosubする際に現在値を「この深度のvar変数情報」として保存し、return直後にその値を用いて復帰しています。 --ここは深度1です gosub *label1 値は「$hoge」です。 -->未定義エラー! ---------------------------------------------------- *label1 --ここは深度2です if(true) var hoge="あいうえお" end 値は「$hoge」です。 -->値は「あいうえお」です。 gosub *label2 return *label2 --ここは深度3です 値は「$hoge」です。 -->未定義エラー! return

2.5.4 - 暗黙的にローカル化される変数

for[2.8]の管理変数はNScripter/Lua変数を問わずローカル化されます(forを出たとき、for開始以前の値に戻ります)。
ラベルの引数受け皿[2.10.1]は暗黙的にvar変数[2.5.3]として定義されます。オプション次第では代わりに通常の名前ありローカル変数(ローカルエイリアス)[2.5.2]として定義することもできます。

2.5.5 - 無名のローカル変数

local $0
★あまりおすすめしない

2.5.6 - var変数とローカルエイリアスの干渉エラー(名前被り時のエラー発生)について

★内部処理の関係で「現在使われている変数名」が被るとエラーを出している

2.6 - テキスト処理とクリック待ち

★色々付いていますがテキストボタンには対応していません(非常に残念)

2.6.1 - 文字化けの自動回避機能

★化けません

2.6.2 - zenkakko

★復活しています ★詳細とpretxextgosubとtext0との兼ね合い

2.6.3 - linepage

★追加の引数を持ちます

2.6.4 - clickstr

★追加の引数をたくさん持ちます

2.6.5 - 常駐ボタンの設置

★パッケージ化された関数 これは明確に乗っ取りの負担軽減が目的です。
つまり「常駐ボタンを設置したいだけなのに、“クリック時は読み進める”まで定義したくない」  ↓とのタイミング デフォルトのクリック待ち関数では自動で再定義を行っています。 NSNSpermanentbuttons("prepare")

2.6.6 - 自作関数によるクリック待ちの乗っ取り(NSNSclickwait())

NSNSclickwait(frommyselnum,voicewaiting,notfromtextwait)

この関数は俗にシステムカスタマイズと呼ばれる処理のうち、
「クリック待ち時の動作を変更する」
に相当します。
つまり、「テキスト中のクリック待ち(@¥)」または「自作selnum」から呼び出され、以下の処理を担う関数です。
@(必要であれば)常駐ボタンを定義する
A(bexec命令で)クリックやキーやボタン押下等の「入力」を検知する
B結果(何が入力されたのか)をNSLaに返す
NSLaデフォルトの関数は実装例としてのサンプルを兼ねています。

NSLaでは、単に常駐ボタンを実装するだけなら常駐ボタン設置関数[2.6.5]を使用して配置・取得する事ができます。
その場合クリック待ち関数を修正・自作する必要はありません。つまり、この関数を改変する場合は
「有効なキー入力を追加・変更したい(Zキーで読み進めたい、F12リセットは要らない等)」
「ゲームパッド主体のジャンルにおいて、テキスト表示時にゲームパッドの入力を検知したい」
どちらかの状況にある事が想定されます。

■引数について 第一引数(bclearを行わずtrapを発火させないフラグ)
自作selnum等から呼び出して使う場合はtrueを渡してNSNSclickwait(true)とします。これはtrapの発火を防ぐためです。
第二引数(オートモードのボイス待ちミリ秒)
オートモード[2.12]中であり、かつボイス待ちを行う(クリック待ち関数を再帰的に呼び出す)場合に次回確認までの待ち時間(ミリ秒)を渡します。デフォルト関数では100ミリ秒ごとにボイス再生の有無を判定しています。
外部からの呼び出し時は(何か特別な演出を用いるのでない限り)使用しません。
第三引数(常駐ボタンを起動しないフラグ)
判定に常駐ボタンを用いたくない場合はtrueを渡します。これは自作バックログからの呼び出し等を想定しています。
これらの引数は全てデフォルト関数内で利用しています。したがって、関数を自作する場合はこの限りではありません。 第四引数(テキストクリック待ちから呼ばれた場合にクリック待ち記号が渡される)
NSLaデフォルトのオプション環境では「@ \ @ ¥」の四種類いずれかが渡されます。
一部のテキスト系命令で自動挿入されるクリック待ちについてはその機能に準じます。
(つまり ("@" または "@")で一致判定を行えばとりあえず問題ありません。)
これはispage命令相当の機能ですが、標準で定義している関数では特に利用していません。

■NSLaデフォルトの関数で行っている処理
NSLaにおいて、デフォルトの「クリック待ち」が担う処理は以下の3つです。

@(必要であれば)常駐ボタンを定義する デフォルトの関数では常駐ボタン設置関数[2.6.5]を(定義されていれば)自動で呼び出しますが、 そちらで定義したくない特別な理由があればここで直接定義しても構いません。
A(bexecを用いて)クリックやボタン等の入力を取得する bexecそのものです。特別な理由があれば代わりに旧ボタンを用いても構いませんが、様々な理由(反応速度の差、常駐ボタン設置関数との兼ね合い等)から推奨はしません。NSLaはテキストボタンを使用できない[2.18.2]点にも注意してください。
BNSLaに結果を返す bexecの結果に応じて起こすべきアクションを決めます。以下で詳しく解説※します。
【詳しい解説】
bexecで入力を取得した結果、
「マウス・キー入力を検知した」
「ボタンが押されていた」
「オートモードやスキップ中だった」
等の返答があったものとします。デフォルト関数では結果をその場でbkekkaという変数に格納し、中身に応じて処理を振り分けます。 基本的には、
・何らかの入力扱いする
・systemcallを呼び出す
・即座に何らかの命令を発火させる(trapによる命令割り込み[2.11])
何れかの反応を返す事になります。デフォルト関数では以下の順で判定・処理しています。

●(常駐)ボタンを押したか?
 常駐ボタン設置関数を呼び出してチェックしています。  特別な理由がない限りは常駐ボタン関数に任せてよいはずですが、必要であれば関数内に直接記述しても構いません。
 以下に該当箇所のコードを(若干書き換えつつ)引用します。

--100番を押していた場合 if(bkekka=="S100")then --●何らかの入力を検知させたい場合 --右クリック扱いしたい場合 --bkekka="RCLICK" --ホイール上入力扱いしたい場合 --bkekka="WHEELUP" --スキップしたい場合のみsystemcallではなくこちらで行います --bkekka="SKIP" --●systemcallしたい場合(標準メニューを呼ぶ等) --NSNSrclickmove_systemcall="windowerase" --※倍角テキストモード[2.6.8]中にデフォルト回想を呼ぶとエラーを招くため、 -- lookbackのみは以下のように書く必要がある -- if(not NSNSbsmm_mul)then NSNSrclickmove_systemcall="lookback" end --●任意の命令で割り込みたい場合 (基本的には自作selnumからの呼び出しで発火させるべきではない) -- NSNSdotrap=NSNStrap --trapの発火 -- NSNSdotrap=NSNSrtrap --r_trapの発火 -- NSNSdotrap=NSNSlrtrap --lr_trapの発火 -- NSNSdotrap='caption "常駐ぼたんくりっく"' --割り込む命令を直接指定する例 -- NSNSdotrap='押 し た な ?' --テキストも通る(使い所はやや乏しい) -- NSNSdotrap='%20=57' --NSLa特有の略記やLuaコードも通る -- NSNSdotrap='*何らかのラベル' --ラベルを記述するとgotoジャンプする -- NSNSdotrap='gosub *trapによるgosubジャンプ' --[[ 【割り込む際の注意】 ※ボタンウェイトおよび標準selnumの実行中はtrapが発火しない(本来の挙動と同様)。 ※trapで割り込む命令にgosubを指定した場合のみ、やや特殊な挙動になる @「飛び先からreturnで戻るまでずっと」「trap発火中」と見なされる。 A「trap発火中は右クリックメニューが発火しない」  「独自右クリックメニュー[2.11.4](※1)の中ではtrapが発火しない」  というセーフティ機能が存在する。 詳しくはtrapによる命令割り込み[2.11]を参照。 --]] --200番を押していた場合 elseif(bkekka=="S200")then end --常駐ボタン関数[2.6.5]がセットされていたらそちらでも判定する if(not notfromtextwait and type(NSNSpermanentbuttons)=="function")then local newkekka=NSNSpermanentbuttons("check",resnum) if(newkekka)then bkekka=newkekka end end

●オートモード関連の処理
オートモード[2.12]中であるか、オートモードの切り替わりが発生するかどうかを判定します。NSLaにおけるオートモードの扱いは当該項目を参照してください。

if(bkekka=="AUTO" or (bkekka=="TIMEOUT" and NSNSautomode))then if(bkekka=="AUTO" and NSNSautomode)then NSNSautomode=false else bkekka="WHEELDOWN" NSSystemCall("automode") --「ボイス鳴ってる間は待つ」の処理(自身を再帰的に呼び出す) --NScripterDS.dllまたはNSOgg2.dllが前提、前者はろだのラッパー(nds関数)利用が前提 if((type(NSNSexistogg2)=="string" and type(nds)=="function" and nds("isplaying",NSNSexistogg2)==1) or (NSNSexistogg2 and NSOggIsPlaying(0)))then return NSNSclickwait(frommyselnum,100) end end end

●デフォルトおよびNSLa追加分の入力判定
以下の判定を行っています(コードは省略)。 クリック(相当のキー)
右クリック(相当のキー)
ホイール上(回想呼び出し)
F11(デバッグコンソール呼び出し)
F12(リセット)
単に特定のキーをクリック扱いする場合などはここに加筆すると良いでしょう。
ツクール系列に揃えたZキー読み進めなどを足しておくと便利かもしれません。

●オートモードを止める入力だった場合はskipoffする
●結果をreturnする bkekka(文字),resnum(数字)
の二つを返しています。

以上がデフォルト関数で行われている処理です。 大多数を占めるであろうノベル用途では、デフォルト関数(と常駐ボタン設置関数[2.6.5]の調整)でおよそ事足りると思います。

■関数を改変すべき場合
ここで想定するシチュエーションは
「ゲームパッド主体のジャンルにおいて、ゲームパッドの入力をテキスト送りに使いたい」
というものです。
たとえばNScripterで弾幕STGを制作するならば、当然プラグインを用いてゲームパッドに対応するべきです。
しかしデフォルトのクリック待ち(およびbexec)はパッドの入力を検知出来ません、標準テキストの利用に問題が生じます。
その場合標準テキストを諦めるか、検知可能なbexecを自作するか、この関数を改変または自作する必要があります。

繰り返しになりますが、この関数を自作する場合、最低限行うべき処理は以下の3点です。
@(必要であれば)常駐ボタンを定義する
Aクリックやキーやボタン押下等の「入力」を検知する
B結果(何が入力された事にするか)を返す

入力検知、つまりAの箇所を改変する場合、
btimeを短く設定した上でbexecとプラグイン側の入力チェックを同時に行う
bexecを使わず自力で入力を取得する
といった方法が考えられます。

2.6.7 - 自作関数によるテキスト表示の乗っ取り(deffontd.dllとの連携)

★deffontd.dllはすごいぞという話 サンプルコード参照

2.6.8 - 倍角テキストモード

★相当無茶

2.6.9 - NSLaにおけるputtextとtext/text0コールバックの扱い

★zenkakkoこちらで説明した方が良いのでは? ★tagコールバックの扱い
text0 テキストの先頭で呼ばれ、これから処理する予定の文字列が引数として渡されます。文字列を返せばそのテキストにすり替え、falseを返せばテキスト表示を中止します。 ★zenkakko、pretextgosubとの兼ね合い
text 呼ばれません ※クリック待ち時の挙動はNSNSclickwait()[2.6.6]で処理されます。
puttext 非推奨です(テキストも:で区切れるため意味がない&テキストに伴うべき機能が一部働かない)

2.7 - ifによる条件分岐

条件分岐とループは(NScripterから見て)大きく文法が追加されています。
従来のIFに加えてLua風のif〜elseif〜else〜endも利用できます。

2.7.1 - if〜end

NSLaにおけるifの最も基本的な形は以下の通りです。
if(条件式) 条件を満たした場合の処理 end
「満たした場合の処理を複数行に分けて書ける」のが素のNScripterとの大きな差です。従来は以下のように記述する必要がありました。
;パターン1 IF(条件式の否定):skip 2 ;(以下の処理をちょうど飛ばすだけの行数) 条件を満たした場合の処理 ;パターン2 IF(条件式の否定):goto *label 条件を満たした場合の処理 *label ;パターン3 IF(条件式の否定):jumpf 条件を満たした場合の処理 ~

条件式の直後には、必ず「改行」「:「then」のうちいずれかを記述する必要があります。 従来のNScripterでは:を省略可能でしたが、NSLaでは省略できません。この非互換性はコンバートツールによって補正されます[2.17.1]
したがって、従来通り単一の行に記述したい場合、以下のような表記をすることになります。
if(条件式) :(命令) :end
この表記を醜く思う場合、従来と同じ動作をする大文字のIF[2.7.4]の使用を検討できます。

条件式にはNScripterと同じ演算記号を使用できます。
(実際は条件式の記号を内部で置換し、Luaとして判定しています。)

【>】
【>=】
【<】
【<=】
「大小(または辞書順)の判定」
【==】「等しい」
【~=】
【!=】
【<>】
「等しくない」
【and】
【&&】
「かつ」
【or】
【||】
「または」
()「括弧内の判定結果(真偽)を一つの項と見なす)」
(多重に記述可能)
【not hoge】「否定(項hogeが偽である)」
★Lua変数とエイリアス直書きの注意点

endは従来のNScripterにおいて「本体の終了」を意味する命令でしたが、NSLaにおいてはifを閉じるための予約語として機能しています。 従来のendに相当する命令は「nsend」および「nsbreak」です[2.15]この非互換性はコンバートツールによって補正されます[2.17.1]

2.7.2 - elseとelseif

else」は「条件を満たさなかった場合に以下を処理する」を意味する予約語です。ifと組み合わせて使用します。
if(条件式) 満たした場合の処理 else 満たさなかった場合の処理 end

elseif」は「直前までの条件式を満たさなかった場合に判定」を意味する予約語です。ifやelseと組み合わせて使用します。
if(条件式A) Aを満たした場合の処理 elseif(条件式B) Aを満たさず、Bを満たした場合の処理 elseif(条件式C) A・Bを満たさず、Cを満たした場合の処理 else どれも満たさなかった場合の処理 end

2.7.3 - ifのネスト(入れ子)とネストの離脱(outif/killif)

ifネストの中に別のifを記述しても構いません(入れ子にすることができます)。
if(条件式A) Aを満たした場合の処理 if(条件式B) A・Bを満たした場合の処理 end end

NSLaのifネストには、
「内部にラベルを記述してはいけない」
「skipの飛び先は同一ネストでなければならない」
という二重の制約が課されています。詳しくはラベルの記述位置に関する注意[2.9.4]を参照してください。 そうした制限下で小規模なネスト内ジャンプに対応するために、以下の予約語が作られています。

何らかの理由からifネストの外まですぐさま離脱したい場合、「outif」命令を利用できます。
これはforにおけるbreakのように働く予約語です。
;ネスト0 if(条件式A) ;ネスト1 Aを満たした場合の処理 if(条件式B) ;ネスト2 outif end end --outifを呼ぶとここまで離脱する

そうではなくネストを部分的に離脱したい場合、「killif」命令を利用できます。
killifが呼ばれると、直後の引数に指定した数(省略時は2個)だけネストを離脱します。
;ネスト0 if(条件式A) ;ネスト1 Aを満たした場合の処理 if(条件式B) ;ネスト2 if(条件式C) ;ネスト3 killif 2 end ここは飛ばされる end --ここまで離脱する Aを満たした場合の処理の続き end

2.7.4 - IF(互換用)

原則として小文字で命令を記述するNSLaにおいて、唯一の例外となっているのがIFです。
IF(条件式) :満たせば以下を実行、満たさなければ次行へ移動
見ての通り互換用の命令です(「満たさなければ次行へ」という命令ですが、必要に応じて利用しても構いません。

また、IF以下はネストと見なされません(ネストが加算されません)。
この仕様は前項のネスト部分離脱処理[2.7.3]と組み合わせる際に便利かもしれません。
;ネスト0 if(条件式A) ;ネスト1 Aを満たした場合の処理 if(条件式B) ;ネスト2 Bを満たした場合の処理 IF(条件式C):killif 1 Bを満たした場合の処理の続き end ;Cを満たした場合ここに離脱する end

2.7.5 - do

Luaのdo(ブロック要素)と似ています。 ローカル変数[2.5.1]名前ありローカル変数(ローカルエイリアス)[2.5.2]のために存在する制御文で、 ネストを1増加させる他は何も行いません。 役割上は「if(true)」と同義です。 ;ネスト0 do ;ネスト1 end

2.7.6 - switchとcaseによる分岐

switch文はNScripterにもLuaに備わっていない構文ですが、少なからぬ言語で採用されています。 「最初に[switchの値]==[caseの値]を満たしたcase文」の直下のみを実行します。 条件分岐のための構文であり、if〜elseif〜else〜endのif節きわめて似た機能を持ちます。

以下にswitchによる条件分岐とifによる条件分岐の比較を示します。

switch(%0) case 0 %0==0であった場合に読まれます。 case 1 case 2 複数のcaseを一つの実行分に紐付けることもできます(条件式のorに相当)。 この場合は%0==1または%0==2であった場合に読まれます。 case %1 %0==%1であった場合に読まれます。 case "あいうえお" %0=="あいうえお"であった場合に読まれます。 case あいうえお 生の全角文字に限り、""を省略しても構いません。 case abc %0==abc(半角文字はLua変数と見なされます)であった場合に読まれます。 default 条件を満たすcaseが一つもなかった場合に読まれます(elseに相当)。 default節は省略可能です。 caseとdefaultの記述順は自由です。 つまり、何れかのcaseとセットで書いても構いません。 end

if(%0==0) 0なら読まれます。 elseif(%0==1 or %0==2) 1または2なら読まれます。 elseif(%0==%1) %1なら読まれます。 elseif(%0<=10) 10以下なら読まれます。 elseif(%0=="あいうえお") "あいうえお"なら読まれます。 --elseif(%0==あいうえお) -- ※これはエラーです elseif(%0==abc) %0==abc(半角文字はLua変数と見なされます)であった場合に読まれます。 else 他に条件を満たすif節が一つもなかった場合に読まれます。 defaultと異なり、記述位置や組み合わせの自由度はありません。 end

case内部の処理を途中で終えたい場合、breakでswitch末尾のendまで離脱できます(forなどのループ中にswitchを書く場合は注意してください)。 ★case節末尾の自動breakとfallthrough命令 ★case直下はネスト0と見なされるためラベルやローカルラベルを記述できますが、

2.8 - ループ

管理変数およびforの挙動は、従来のNScripterと互換していません(Luaに合わせています)[2.17.3]。「管理変数をループ内部で書き換える」ことで「ループ回数を動的に変化させる」スクリプトをコンバートする場合、手作業で修正を加える必要があります。

forの管理変数は暗黙的に(疑似)ローカル化され、for離脱時に元の値へ戻ります[2.5.4]

NScripterや多くの言語同様に、breakによってループを離脱できます。

★gosub・gotoの注意(ローカル変数、var変数)

2.8.1 - forによる回数指定ループ

基本形は以下の通りです。
;NScripter変数で管理 for %0=1,5 ループ内部の処理 next --Lua変数で管理(離脱時には元の値に戻る一方、内部的にはグローバル変数を利用する点に注意してください!) for i=1,5 do ループ内部の処理 end

「to」「step」ではなくカンマで区切ります。ステップは省略できます。
★もっといろいろ省略できる

ループ末尾はnext(NScripter風の表記)でもend(Lua風の表記)でも構いません。nextを用いれば対応関係が厳密になり相対的に記述ミスを検出しやすくなります(endはifネスト[2.7.1]の末尾にも用いられるため)が、Luaに慣れたユーザーにとってはend表記の方が自然に使えるかもしれません。

条件式の直後には、必ず「改行」「:「do」のうちいずれかを記述する必要があります。 管理変数にはNScripter変数、Lua変数どちらを使っても構いません。

2.8.2 - ジェネリックforによるループ

★pairsとかも使えるという話
for i in tab do alert(tab[i]) -->変数tabの中身を次々表示する(順番は保証されない) end
for k,v in tab do --何らかの処理 end for k,v in pairs(tab) do --何らかの処理 end

--pairs以外のイテレータも使用できます。 str="1=Tanaka,2=Saitou,3=Gotou,44=松尾芭蕉" for num,value in string.gmatch(str,"(%d+)=([^,]*)") do alert(num) -->"1"→"2"→"3"→"44" alert(value) -->"Tanaka"→"Saitou"→"Gotou"→"松尾芭蕉" end ★ただし管理変数は2つまでしか記述できず、  出てくる値は事前に全て評価される(ループ途中での変更は無視される) ★困るようなら複数行埋め込みLua使ってね


2.8.3 - forの管理変数にNScripter変数を指定する場合の注意

★非互換の項に回す?

2.8.4 - whileによる継続条件指定ループ

Luaのwhileとほぼ同じ動きで、NScripterのforはこちらに似ています。 whileを読むたびに判定を行い、「条件式が真である間」継続するループです。

--10回繰り返される %0=0 while(%0<=10)do %0++ %0回目のループです end --中身は読まれない %0=0 while(-1>999)--doはあってもなくてもいい -- end --無限ループ %0=0 while(true)do %0++ %0回目のループです end


break命令で離脱できる点はforと一緒です。

2.8.5 - repeat〜untilによる離脱条件指定ループ

Luaのrepeat/untilとほぼ同じ動きです。 untilを読むたびに判定を行い、「条件式が真となるまで」repeatに戻り続けるループです。 末尾で離脱判定を行う関係上、他のループと異なり最初の一周は必ず実行されます。

--10回繰り返される %0=0 repeat %0++ %0回目のループです until(%0>=10) --一度だけ実行される repeat 一度だけ実行されます until(true) --無限ループ repeat %0++ %0回目のループです until(false)


break命令で離脱できる点はforと一緒です。

2.9 - ラベルとラベルジャンプ

2.9.1 - *日本語ラベル

NSLaではラベル名に日本語(全角文字)を使用できます。

2.9.2 - goto

★skip共々言うことなくね?

2.9.3 - ローカルラベル(jumpf/jumpb/~ラベル名)

jumpf/jumpbの飛び先に名前を付けることができます。
jumpf テスト ~ ここには飛ばない ~テスト ここに飛ぶ
通常のラベルと異なり、付ける「名前」はスクリプト内で重複しても構いません(最も「近い」場所にジャンプします)。
まるでgotoと拘束の弱いラベルであるかのように動作するため、NSLaでは~(チルダ)をローカルラベルと呼ぶことにします。

例外的な挙動として、jumpf/jumpb側で名前を指定しなかった場合、名前を問わず、最も近い場所に見つけたローカルラベルにジャンプします。
「無名のローカルラベルに絞り込んで飛ぶ」という動作ではないため注意が必要です。
jumpf ~あいうえお ここに飛ぶ ~ ここではない

2.9.4 - ラベルの記述位置に関する注意

ラベルとローカルラベルは「ifネストの外部、行の最初」に記述する必要があります。
これを言い換えると、「ラベルジャンプの飛び先はネストの内側であってはならない」
という制約になります。ラベルジャンプ命令(goto/gosub/jumpf/jumpb)は飛び先がネスト外(ifの外部)であることを期待するため、 続けてendを見つけるとデフォルトではエラーを吐きます。

この制約は、ネスト内部でスクリプト位置を移動したい場合において影響してきます。 部分的にネストを飛び出すにはkillif命令[2.7.3]を使ってください。
同一ネスト内でジャンプを行う必要がある場合、skipを用いてください。skipは同ネストへの移動を期待します。

動作オプションをNSNSjumptozeronest=nilと設定すると、
jumpf/jumpbの飛び先は同じネストであることを期待する」と挙動を変更できます。
そうした場合は「ネスト内ジャンプにskip/jumpf、ifネストからの離脱にkillif/outif」と役割分担できますが、 一方でjumpf時にネストがずれてしまってもその場でエラーが出ず、skip同様にバグの特定が難しくなります。
以上の問題から、デフォルトではtrue(jumpfにはネスト外ジャンプを期待する)が設定されています。

2.10 - サブルーチン(gosub)と引数と戻り値

NSLaにとって、ラベルは同時に関数でもあります。つまりgosubから引数を受け渡し、returnから値を返すことが出来ます。
引数・受け皿・戻り値ともに、記述ルールは代入略記の[2.3.1]左辺・右辺に準じます。

2.10.1 - gosubと引数

あたかもdefsub済み命令であるかのように、飛び先ラベルに引数を渡すことが出来ます。
gosub *テスト("あいうえお",15) gosub *テスト "あいうえお",15 ------------------- *テスト(hoge,fuga) $hoge,%fugaが渡されました。@ return
受け皿は暗黙的に深度依存ローカル変数[2.5.3]と見なされます。上記の例ではラベル先頭で
var hoge,fuga="あいうえお",15
が実行されていることになります。

2.10.2 - returnと戻り値(getret($0-1))

戻り値を受け取る事もできます。
gosub *テスト("あいうえお",15) getret($0-1) 「$0」「$1」が戻ってきました。 ------------------- *テスト(hoge,fuga) /@foo=$hoge+"かきくけこ" return $foo,%fuga*3

2.10.3 - defsub

全角文字もdefsub可能です。 ★予約語とluasub済み命令はdefsub出来ません。 引数の受け取りはgosubのそれに準じます。

2.11 - trapによる割り込み

NSLaでは、(ラベルジャンプだけでなく)任意の命令を割り込ませることができます。 ★発火タイミングと有効範囲と発火中の制約について

2.11.1 - ラベルジャンプの割り込み

trap *ラベル
従来と同じ動作です。ラベル記述位置に関する制限[2.9.4]には注意する必要があります。

2.11.2 - 命令の割り込み

NScripter命令・Luaコード・テキスト等、「NSLaにおいて単一の命令と解釈される文字列」も仕込む事が出来ます。
trap[bg "foo.png",0]
trap[$0="あいうえお"]
trap[alert("あいうえお") local a=12 alert(a)]
trap[$0="あいうえお"]
これらが発火した場合、原則として「(本来実行されるはずだった)次の命令の直前」に割り込まれます。
例外として、テキスト表示中(クリック待ち)に発火した場合は、割り込んだ命令を実行後に残りのテキストを表示します。

仕込んだ文字列の変数は(trapを定義した瞬間ではなく)発火した瞬間に評価されます。
$0="あいうえお" trap[gosub *テスト($0)] $0="かきくけこ" trapさせます→@しました¥ ---------------------- *テスト(str) $strが渡されました。@/ -->かきくけこが渡されました。 return

2.11.3 - 用意された文法と非互換性(rtrap/lrtrap)

trapの準備は以下の命令で行えます。
trap "〜" r_trap "〜" lr_trap "〜"
従来の記述では「"」を含む命令に問題が出るため、対策として以下の3つが用意されています。
trap[〜] rtrap[〜] lrtrap[〜]
従来通りoff,stop,resumeも使用できます。
trap off trap stop trap resume

現時点でtrap2とlr_trap2には対応していません。これはNSLaにおける非互換性の一つです。

2.11.4 - 右クリック動作の乗っ取り(rgosub相当の設定)

(ラベルが独自管理であるため)NScripter標準のrgosubには対応しておらず、(selnumを乗っ取る前提の)代替機能となっている ★ 【注】 ※ボタンウェイトおよび標準selnumの実行中はtrapが発火しない(本来の挙動と同様)。 ※trapで割り込む命令にgosubを指定した場合のみ、やや特殊な挙動になる @「飛び先からreturnで戻るまでずっと」「trap発火中」と見なされる。 A「trap発火中は右クリックメニューが発火しない」  「独自右クリックメニュー(※1)の中ではtrapが発火しない」  というセーフティ機能が存在する。 ※1…独自右クリックメニュー rgosubに近い機能。 設定例は以下。 NSNSrclickmove="*hoge" --*hogeにgosub NSNSrclickmove="rmenu" --systemcall rmenuに相当 NSNSrclickmove="" --何もしない NSNSrclickmove=hoge() --関数hoge()を呼ぶ。【 (関数を定義してから設定する必要があります) 】 ただし、ラベルへのgosubを設定する場合はselnum命令自作が推奨される。 標準selnumでは複数の問題を起こす(※2)。 ※2…独自メニューにラベルgosubを設定し、標準のselnumを使用した場合に起きる問題 selnum内で独自右クリックメニューを発火させた上で、 ・飛び先ラベルでsystemcallを呼んでも反応しない ・飛び先ラベルでloadgameするとバグる(実行中だったselnumが消せずに残ってしまう) ・飛び先ラベルで多重にselnumすると元の選択肢が化ける ・飛び先ラベルでテキストを表示すると選択肢に重なって表示される 2番目の問題が比較的致命的であるため、selnumの自作を推奨することになる。

2.12 - ログとテキスト自動送り(スキップ、オートモード)

2.12.1 - 既読ログと既読スキップ

★NSLaはテキストの既読情報を記録する

2.12.2 - ファイルログ

★bg以外の命令に関してもログを追加出来る
 if節での判定はfchk("ファイル名")が基本

2.12.3 - ラベルログ

★  if節での判定はlchk("*ラベル名")が基本
 多重実行した関数内で通過したラベルの記録は、実行方法とオプションに左右される

2.12.4 - オートモードとボイス待ち(nscripterDS.dllとの連携)

★nscripterDS.dllまたはnsogg2.dllの使用が前提  オプションで指定する

2.12.5 - バックログの自作

2.13 - セーブとロード

2.13.1 - NSLaにおけるセーブとロードの扱い

★Lua主体かつセーブ併用でない限りはNScripterと同感覚で使って問題ありません  セーブポイントが更新されない(savepointを記述できない)タイミングが存在します

2.13.2 - セーブポイントを更新できないタイミング

★ ・saveoff中 ・ジェネリックfor ・多重実行されたns関数内部

2.13.3 - Lua変数のセーブとロード(luadata.save()/luadata.tload())

★外部ファイルに出力する。簡単な暗号化もオプションで用意されている(やや重い)

2.13.4 - バックログ記録地点へ巻き戻す(ヒストリー)機能(NSNShistory変数)

2.14 - デバッグコンソール(F11)とリセットボタン(F12)

2.14.1 - F11デバッグコンソールの使い方

デバッグ支援用の機能です。 F11キーを押すとタイトルバーに実行状態が表示され、同時に画面上方にtextareaが出現します。 入力内容に応じて以下の処理が実行されます。
入力欄が空 デバッグモードを終わります。
NScripter変数 変数の中身をウインドウ(タイトル欄)に表示します。
$hoge -->$hogeの中身を表示
カンマ(,)で区切ることで複数の変数を表示できます。
$foo,$bar -->$foo,$barの中身を表示
変数=値 その場でNScripter変数に値を代入します。文法は代入の略記[2.3.1]に準じます。
ラベル名 ラベルが存在すれば位置を、存在しなければその旨を教えてくれます。
Luaとして認識される文字列 入力内容をその場で実行します。 デフォルトではNスク変数らしき文字を変換します。 不要な場合は埋め込みLua同様「//」に続けてください。
「@」で始まる文字列 @以降の文字で命令割り込みを予約します。
入力内容はデバッグモードを抜けた瞬間に発火します。
また、特殊な制御コマンドとして
「@」現在の発火予定を表示
「@@」発火予定の消去
「@@@」実行予定の復元(デバッグモードに入る前の内容に戻す)
「@@@@」前回の入力内容を繰り返す
が用意されています。
上記以外 @を省略した記述(命令の割り込み予約)と見なします。
デフォルトではanimationコールバック内でF11の入力を検知し、NSNSdebugmode()を呼び出しています。NSLaを改造して他の場所から呼び出す場合、
・一時的にNSLuaAnimationMode(false)としてアニメーションコールバックを止める
・アニメーションコールバック内の呼び出しを削る
等の措置が推奨されます。textfieldの入力待ち時は裏でアニメーションコールバックが実行されており、放っておくと多重に実行される恐れがあるためです。

2.14.2 - F12リセットに関する注意

「F12キーでリセット」はRPGツクール2000などに見られるショートカットキーです。クイックセーブ・ロード主体であろうサウンドノベル用途での必要性はさておき、NSLa標準の処理ではF12キーをリセットに割り振っています。

具体的には
「アニメーションコールバックまたはクリック待ち処理(NSNSclickwait[2.6.6])でF12を検知する」
「連続実行防止用にNSNSF12osippa=trueとした上でresetの実行予約で割り込む」
「拡張スクリプトがresetを実行していたら自動で必要な処理(拡張スクリプトの位置調節等)を行う」
と処理されています。 したがって埋め込んだLua関数内部でリセットを検知する場合、検知した瞬間速やかに抜け出すべきです。

※NSLaに限らず、NSLuaを利用する際は「リセット」に気を使う必要があります。
 (Lua変数はreset命令で変動しない=自動では初期化されないため)
 NSLaにおいてリセット時にLua変数を初期化したい場合、
 @拡張スクリプト内部で使う変数を単一のテーブルに格納する
 A実行節先頭で定義する(ことで疑似的にLua変数を初期化する)
 このような手順が考えられます。

*start h={} --resetする度に再定義≒初期化される h.hoge="hoge"

2.15 - 拡張スクリプトの終了(nsbreak/nsend)

従来のend命令に相当します(NSLaにおいて、"end"はifネスト[2.7.1]for[2.8]を閉じる予約語です)。 nsbreakは現在のns関数のみ終了(離脱)し、nsendは多重実行中の全ns関数を終了させようとします[3.2.5] NScripter目線においては両者の違いはありません。

2.16 - スクリプトにLuaを埋め込む

★ NScripter命令の内部に埋め込む(基本的には引数として)方法と、コードを直接埋め込んで命令のように実行する方法が用意されています。

2.16.1 - 命令であるかのようにLuaコードを記述する

★ 通常のスクリプトにおける命令であるかのように、Luaコードを記述することができます。 NSLa側で「Luaコードか、NScripter命令か」を自動的に解釈し、前者ならloadstring()越しに実行します。

*start bg black,1 alert() このように :alert("「次のコロンまで」がコードの範囲と見なされます。") :local a,b a=1 b=2

エスケープ「::」

/. ./複数行埋め込むこともできる 埋め込んだLua内部に拡張スクリプトを記述することもできる

加工するためloadstringを乗っ取っている点に注意

2.16.3 - 命令にLua変数/関数を埋め込む(&hoge)

★&foo テーブル・関数も可能だがキーに注意

2.16.2 - 命令にLuaコードを埋め込む(^^〜^^)

(単一の変数ではなく)複雑な値をNScriptr命令の引数に用いたい場合、そのようにLuaコードを記述できます。
bg ^^hoge^^,1 bg ^^foo..bar^^,1 bg ^^hoge="foo" return hoge^^,1
^^〜^^内部には
@「(そのままreturn可能な)変数」
A「(そのままreturn可能な)式」
B「最終的に値をreturnする関数の中身」
何れかを記述してください。

テキストに埋め込む事もできます。
あいうえお^^kakikukeko^^さしすせそ@

2.16.4 - 「:」「%」に関する注意

★「:」は命令区切りが優先されてしまう ★「`」を%と見なすオプションが有効

2.16.5 - if/forの真の姿

★条件式内部はLuaとして処理している話

2.17 - 既存スクリプトのコンバート

★@ツールでコンバートできる A手で直す必要がある(が代替手段は用意されている) B完全に対応していない(移植できない) で分けた方が良いのではないか

2.17.1 - コンバートツールで自動変換される内容

2.17.2 - 非互換性(手で書き換える必要が生じるスクリプト)

2.17.3 - 内部で管理変数を書き換えているfor

2.17.4 - 引数を持つdefsub命令

2.17.5 - 既にシステムカスタマイズしている場合

2.17.6. - NSLaが用いるluasub済み命令と衝突する場合

2.17.7 - コールバックを利用している場合

2.18 - 非対応の命令・機能

2.18.1 - definereset

2.18.2 - テキストボタン

2.18.3 - テキスト直埋めの変数操作(そういうものがあります)

2.18.4 - システムカスタマイズ(クリック待ち)専用の命令群