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を読み込みます」といった具合です。
この例は同梱サンプルにおけるデフォルト挙動であり、実際には好きな名前のファイルを好きなタイミングで読み込む事ができます。

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

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

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

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

「生の文字」と書いた場合、原則として""で括られた文字列を意味します。
「生の数字」と書いた場合も、同様に、変数記述ではない数字そのものを意味します。
「生の全角文字」と書いた場合、""で括られてすらいない全角文字列を意味します。$0=あいうえおの右辺がその例です。

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

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

「評価する」と書いた場合、「(該当する文字列を)処理・実行する」と読み替えて構いません。
たとえば「“$0,$1=$1,$0”の右辺を評価し、それから代入する」という文章は、
以下の二段階の操作を意味します。

@右辺の「$1,$0」が具体的な値(変数の中身)に置き換わる A$0に$1の中身が、$1に$0の中身が代入される(→$0,$1の値が入れ替わる)

「真である」「偽である」と書いた場合、前者を「条件を満たす」ないし「変数に何らかの値が代入されている」と読み替えて構いません。 Luaが分かる人は当然そのまま読んでください。

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

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

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

1.2 NSLaが使用するリソース

NSLaは動作のためにNScripter変数を一つ使用し、多くのLuaの変数/luasub命令/コールバックを予約します。
★既存のスクリプトをNSLa用にコンバートする場合の注意★も参照してください。 また、ノベル用コードを利用する場合、多くのスプライト番号をテキストや独自バックログの表示用に予約します。

1.2.1 Lua変数

「語頭が『NSNS』であるLuaグローバル変数全て」をNSLa用に予約します。
たとえば拡張スクリプトはNSNSgyoに格納されており、NSNSsaveonがsaveon状態か否かを管理しています。

NSNSで始まらない例として、たとえば以下のような関数を定義しています。
luadata.save() luadata.load() luadata.tload()
これらはLua変数の保存と読み出しを行う関数で、内部動作(ログ系の機能における出力)でも使用しています。
利便性のために追加した関数もあります。
string.split() table.copy() alert() ensafe()
こうした関数は内部動作に使用しておらず、必要に応じて上書きしても構いません。

デフォルトのLua関数のうち、error()とloadstring()とNSSleep()はグローバルに上書きしています。

上記以外に、NSLaの実行そのものを司る関数として以下を使用しています。 nsload() nsloadfile() ns() nsfile() nsboot()
このうちns関数が本体で、他はns関数を実行するためのラッパーです。詳細については拡張スクリプトの動的な読み込みと実行[3.2]を参照してください。

1.2.2 NScripter変数

Lua変数NSNSSaveHensuで指定した番号の文字変数(通常変数が望ましい)を1つ使用します。
デフォルトでは以下の通り定義しています。

;$V4095G2000S640,480L10000 NSNSSaveHensu=1999

この変数は内部情報(ロード時の戻り行など)を記録するための領域として予約されます。 スクリプトの可能な限り早い位置(NSLa読み込み直後、または定義節の先頭付近)で、「極力通常変数末尾に近い(使わない)番号」を割り当ててください。

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

localalias 1000,1255 setvar 1256,1511

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

以下の命令はNSLa内部で個別に処理されており、defsubluasubは出来なくなっています。
これらは、スクリプト位置やNSLa自体の動作を操作するキーワード(制御構文)です。
コンバーターは変換中にこれらの命令を見つけると警告を出します。

--分岐・繰り返し if elseif elif else end outif killif for next do while repeat until switch case default fallthrough continue break nsbreak nsend --ジャンプ goto gosub return tablegoto skip jumpf jumpb --コルーチン setcoroutine resume yield --その他宣言・代入・内部処理 trap rtrap lrtrap --この辺は厳密に言うと微妙だけど予約としておく local var defsub select selgosub --内部でselnumを呼び出す。selnumは乗っ取り前提 mov reset

1.2.4 予約語以外のluasub済み命令

以下の命令がluasubされています。ロード後復帰用にログを取っているだけのものから内部動作に深く関わるものまで様々ですが、既存のスクリプトと衝突する可能性が最も高いのはこれらの命令群です。
コンバーターは変換中にこれらの命令を見つけると警告を出します。

main domain english savedir savegame savepoint saveon saveoff loadgame systemcall setwindow setwindow2 setwindow3 clickstr linepage puttext kinsoku setkinsoku addkinsoku trap r_trap lr_trap rmode loadgosub textcolor textclear numalias stralias automode_time skipoff zenkakko --新旧ボタン関連全て セーブデータに用いるログ取り用途・環境の記録 btnwait bclear btndef spbtn cellcheckspbtn btn exbtn cellcheckexbtn 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 lsp lsph csp msp amsp textspeed textspeeddefault indent texton textoff texthide textshow --音回り bgm bgmonce dwave dwaveloop bgmstop dwavestop stop bgmvol defbgmvol getbgmvol bgmfadein bgmfadeout sevol defsevol getsevol voicevol defvoicevol getvoicevol --以下はデフォルト命令ではない uselocalalias usevar loopsevol defloopsevol getloopsevol

1.2.5 コールバック

以下のコールバックを定義しています。自分で定義する場合は案内に従ってください。

NSCALL_animation() NSCALL_save() NSCALL_load() NSCALL_end() NSCALL_savepoint() NSCALL_reset()

内部からそれぞれ

NSNSCALL_animation() NSNSCALL_save() NSNSCALL_load() NSNSCALL_end() NSNSCALL_savepoint() NSNSCALL_reset()

を呼び出してください(呼び出し先で内部処理が実行される)。
たとえばNSLaデフォルトのloadコールバックは

function NSCALL_load() NSNSCALL_load() end

と定義されています。
NScall_close() 終了前にNSNSsafeend=trueと代入しておくか、NSEnd(true)と終了してください。

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

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

1.3 NSLaの導入方法

1.3.1 NSLaの最小構成例

■「NScripter風に動く」スクリプトを新規に作成する場合
同梱ファイルをそのまま利用できます。

dllフォルダ NSLaを含むライブラリが入っています。
UIフォルダ NSLa_novelがセーブ/ロード画面やオプション画面、バックログやテキストウインドウに使用する素材が入っています。
lua51.dll/lua5.1.dll dllフォルダ内の一部プラグインが利用しています。
system.lua 「NScripterであるかのように」[3.1.2]NSLaを呼び出し、実行しています。
000.txt〜255.txt ここに拡張スクリプトの定義節・実行節を記述します。
表に出しておきたくない場合、テキストアーカイブではなくns2ファイルアーカイブに格納してください。
00.txt 上部メニューの設定(insertmenu/resetmenu等)とレイヤープラグインの定義はこちらに記述します(処理順の都合)。最小構成例では1行目の初期定義と上部メニューの非表示、NSLaの初期実行(NSCOM_main()の呼び出し)のみ行っています。
NSLaはほとんど使用していませんが、NScripter本体の動作安定に不可欠です。

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

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

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

1.3.2 最小構成例の起動

●00.txt…NSLa読み込み前に読み込まれる領域です。
前項[2.1.1]で説明した通り、00.txtでは
@初期定義(;$V4095G2000S640,480L10000)
A上部メニューの操作
Bレイヤープラグイン定義
CNSCOM_main関数の呼び出し
のみを行っています。
●000.txt…「定義節で行うべき処理」のほとんどが記述されています。
*defineからreturn(game相当の離脱処理)までの処理に相当します。
●100.txt…「実行節」の例です。全画面ウインドウと下部ウインドウ両方の構成例を示しています。
*start以降の処理に相当します。

1.3.3 スクリプトの実行(大文字・小文字に関する注意)

2.1 条件分岐

複雑な条件分岐を行う際、従来は苦しい記述が必要でした。

;パターン1 IF (条件式の否定) :skip (以下の処理をちょうど飛ばすだけの行数) 〜条件を満たした場合の処理〜 IF (条件式の否定) :skip (以下の処理をちょうど飛ばすだけの行数) 〜条件を満たした場合の処理〜 ;パターン2 IF (条件式) :〜条件を満たした場合の処理〜 :goto *label IF (条件式) :〜条件を満たした場合の処理〜 :goto *label *label ;パターン3 IF (条件式の否定) :jumpf 〜条件を満たした場合の処理〜 ~

NSLaの条件分岐には大きく文法が追加され、複雑な分岐を容易に記述できます。

2.1.1 if〜end

NSLaにおけるifの最も基本的な形は以下の通りです。
「if節の処理を複数行に分けて書ける」点が素のNScripterとの大きな差です。

if(条件式) 〜 条件を満たした場合の処理 〜 end

条件式にはNScripterおよびLuaとほぼ同じ演算子を使用できます。
(実際には条件式の記号を内部で置換し、Luaコードとして真偽を判定します。)

【>】
【>=】
【<】
【<=】
「大小(または辞書順)の判定」
【==】「等しい」
【~=】
【!=】
【<>】
「等しくない」
【and】
【&&】
「かつ」
【or】
【||】
「または」
(〜)「括弧内の判定結果(真偽)を一つの項と見なす)」
(多重に記述可能)
【not hoge】「否定(項hogeが偽である)」
【+】
【-】
【*】
【/】
数値の加減乗除を行います。
【%】剰余(割った余り、mod)を計算します。
数値変数と区別するために%の直後には空白を入れてください。
【%変数名】
【$変数名】
NScripter変数へのアクセスを意味します。
【変数名】Lua変数へのアクセスを意味します。
エイリアス参照ではない点に注意してください。

2.1.2 elseとelseif

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

if(条件式) 満たした場合の処理 else 満たさなかった場合の処理 end

elseif」または「elif」は「直前までの条件式を満たさなかった場合にのみ判定」を意味する予約語です。ifやelseと組み合わせて使用します。
言語によって表記が様々であるため方言として二語を予約していますが、基本的にはどちらか一方のみ用いてください。

if(条件式A) Aを満たした場合の処理 elseif(条件式B) Aを満たさず、Bを満たした場合の処理 elseif(条件式C) A・Bを満たさず、Cを満たした場合の処理 else どれも満たさなかった場合の処理 end

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

2.1.4 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,2 ; カンマ区切りにすることで、複数の条件を一つのcaseにまとめても構いません。 case 3 to 10 3<=%0<=10であった場合に読まれます。 case >=100 %0>=100であった場合に読まれます。 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.1.5 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.2 ループ

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

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

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

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

2.2.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.2.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.2.3 forの管理変数にNScripter変数を指定する場合の注意

★非互換の項に回す? 周ごとに管理変数をリセットする仕様、Luaに合わせている

2.2.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と一緒です。 毎ループごとに判定を行う分forよりも動作が重い制御文ですが、そもそもforがそれほど軽くないNSLaにおいては誤差です。

2.2.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.3 ラベルとローカルラベル

2.3.1 ラベル(*)とgoto

2.3.2 ローカルラベル(~)とjumpf/jumpb

jumpf/jumpbの飛び先に名前を付けることができます。

jumpf テスト ~ ここには飛ばない ~テスト ここに飛ぶ


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

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

jumpf ~あいうえお ここに飛ぶ ~ ここではない


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

ラベルとローカルラベルは「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.4 サブルーチン(gosub)と引数と戻り値

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

2.4.1 gosubと引数

あたかもdefsub済み命令であるかのように、飛び先ラベルに引数を渡すことが出来ます。

gosub *テスト("あいうえお",15) gosub *テスト "あいうえお",15 ------------------- *テスト(hoge,fuga) $hoge,%fugaが渡されました。@ return

受け皿は暗黙的に深度依存ローカル変数[2.5.3]と見なされます。上記の例ではラベル先頭で

var hoge,fuga="あいうえお",15


が実行されていることになります。

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

戻り値を受け取る事もできます。

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


2.4.3 defsub

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

2.4.4 関数の中断(コルーチン)

2.5 trapによる割り込み処理

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

2.5.1 gotoの割り込み

2.5.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.5.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.5.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の自作を推奨することになる。

3.1 代入と四則演算

3.1.1 代入($0,%0="あいう",100)

●代入
以下はmov %0,10の略記です。

%0=10

●まとめて代入
以下は%0=10 :$0="あいうえお"の略記です。

%0,$0=10,"あいうえお"

●右辺が余った(項が左辺より多い)場合
余分な項は無視されます。

%0,%1=0,1,2,3 -->%0=0,%1=1

●右辺が不足している(項が左辺より少ない)場合
自動的に0または""が補われます。

%0,%1,%2,$3=0,1 -->%0=0,%1=1,%2=0,$3=""

●左右の辺で型が合わない場合
自動変換を試みます。

%0,%1,$2="123","あいうえお",456 -->%0=123,%1=0(変換失敗),$2="456"

●左辺の範囲指定
以下の左辺は%0,%1,%2の略記です。

%0-2=0,1,2

●左右の範囲指定
「-」の代わりに「#」を使います(右辺には式が来るかもしれないため)。以下の右辺は%10,%11,%12の略記です。

%0-2=%10#12

●同じ型の変数を連続で指定する場合
変数記号($%)を省略しても構いません。

%0,2,$10=0,2,"あいうえお"

●文字変数に全角文字を代入する場合
この場合のみ、文字を括る""を省略できます。

$0=あいうえお

●右辺に四則演算を記述する場合
右辺に四則演算を記述できますが、文字列に計算式を結合する場合のみは必ず()で括る必要があります(処理順の都合)。
演算記号そのものについては★次項★を参照してください。

%0=(15-1)*3/4 -->10 $0="あいう"+(15-1) -->"あいう14" $0="あいう"+15-1 -->エラー!

●代入略記における結合
文字列に対しては"+"(NScripter式)".."(Lua式)のどちらを用いても構いません。

$0="あ"+"い".."う" -->"あいう"

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

3.1.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連番付与)
同様に、!(数字)は!?(数字)の略記と見なされます。
(左辺の残り全てに連続代入+加算または連番付与)

3.1.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

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

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

3.1.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オリジンにすべきである点 ★保存方法

3.2 ローカル変数とブロック

3.2.1 ローカル変数とは?

Luaを含む多くのプログラミング言語でサポートされている機能です。
NScripter風に捉えるなら「どこでも宣言可能で、宣言した箇所以下でのみ有効になる(不要になれば破棄される)変数名」と理解してください。

*label let hoge --現在のifネスト/gosub深度以下で$hoge,%hogeを使用できる --何か処理をする return

一時的に値を格納したいだけの場合など、コード全体から見えなくてもよい変数を定義節でいちいちnumaliasせずともよくなります。

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

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

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

for[2.8]の管理変数はNScripter/Lua変数を問わずローカル化され、(ループ終了後は開始以前の値に戻ります)。
関数ラベルの引数[2.10.1]は暗黙的にvar変数[2.5.3]として定義されます。

3.2.5 無名のローカル変数

内部処理のための旧い構文であり、スクリプト中では可能な限りlet/varを用いて(名前を付けて)ください。 letと同様に定義箇所以下のネスト・深度が有効範囲です。

local $0 --$0が一時的にローカル変数化

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

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

3.2.7 do〜end

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

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

4.1.1 文字化けの自動回避機能

★化けません

4.1.2 zenkakko

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

4.1.3 linepage

★  ・素のNスクと異なり、数字の引数を1つ取ります。   linepage 1と書いた場合、従来と同じ挙動(文末に常に改ページ待ち付与)です。   linepage 5と書くことで「発火に必要な最低行数」を指定できます。   linepage 0と書くことで機能をオフに出来ます。  ・末尾が _ / の場合は発火しません。  ・実行ブロック中でも付け消し可能です。

4.1.4 clickstr

 ※変更した挙動   ・実行ブロック中でも付け消し可能です。   ・文字の指定↑は"/"で区切ります。 文字によっては誤爆するかも?(未検証)   ・指定した文字がテキスト中で連続すると、クリック待ちはその末尾で一回発生します(一括処理されます)。 -------------------------- clickstr "!/?" あああああ!!!!??!!! -->あああああ!!!!??!!!@ --------------------------   ・clickstr ""で解除します。  ※追加の引数(任意)             ↓こいつと             ↓こいつ   clickstr "強/制/ク/リ/ッ/ク/待/ち/文/字" (,en) (,改ページに変わる境界行 (,クリック待ち発火に必要な字数) )   ・第2引数の前に追加の引数enを(生で)渡すと、    半角の!?.,辺りでもクリック待ちが発生します。   ・第2引数の後に追加の引数(数字)を渡すと、    「クリック待ちされていないテキストがn文字溜まるまではclickstrが発火しない」    という挙動になります。ただし、改ページライン以降であれば常に通常通り発火します。

4.1.5 常駐ボタンの設置

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

4.1.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を使わず自力で入力を取得する
といった方法が考えられます。

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

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

4.1.8 倍角テキストモード

★相当無茶

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

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

4.1.10 bexec2

★標準のNSNSclickwait()から呼ばれています。 bexecと比べて以下の性質を持ちます。 ・関数として呼べるNSCOM_exec2(true) で結果を戻り値として返す ・btransが無い ・btnarea相当のbareaがある ・複合ボタン指定の略記がある("P100-110"のように書ける) 内部でからNSNSbexec2_sub()関数を呼んでおり、戻った値を入力結果と見なすことができます。 他のプラグインと組み合わせれば、マウスとキーボード以外のデバイス(ゲームパッド等)の入力結果も反映可能です。 subresult=NSNSbexec2_sub() --戻り値がある場合、それは以下の構造を持ったテーブルであることを期待する subresult={ --クリックした扱いの結果を返すならこのように click={ l=true, r=false, ld=false, rd=false, w=false, }, --キー入力した扱いならこのように key="A", }

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

ログ共通の仕様として、用いるには終了時にNSNSCALL_logfiles()を呼び出す必要があります。
ただし、NSLaデフォルトでNSNSCALL_end内で呼び出しているため普通は意識する必要がありません。

;■全て有効にする場合 ;fchk()用のファイルログ filelog "flogl.dat" ;lchk()用の既読ラベルログ NSNSkidokulabelpath="labell" ;fchk,lchkはLua関数として条件式内で呼び出します。 ;既読スキップ用のテキストログ NSNSkidokudatapath="kidokul" ;■全て無効にする場合 NSNSkidokulabelpath=nil NSNSkidokudatapath=nil

4.2.1 既読ログと既読スキップ

行・列で記録する点は本体同様ですが、NSLaではテキストのみ既読スキップ停止の判定を行います。
既読スキップ「モード」の宣言(systemcall skipが既読スキップになる)は従来通りkidokumode 1です。

既読ログにはデフォルトで以下のパスが指定されています。既読ログを出力しない場合は=nilと代入してください。
また、savedir命令でフォルダを指定していた場合、その直下からパスが始まることに注意してください。

NSNSkidokudatapath="kidokul"

既読スキップを実行中、true実行のns関数[3.2.6]に遭遇した場合の挙動をオプションで指定できます。

NSNSkidokutrue=true -- trueなら 「未読テキストとして読み込み、関数を抜けたタイミングでスクリプトやラベル共々破棄」 -- falseなら「全テキストを既読扱い(停止判定を省略)し、関数を抜けるまでスキップ続行」

なお、「false実行[3.2.7]で一時的に追加された仮想スクリプト」内部のテキスト既読情報は、当該関数を抜けたタイミングで一緒に破棄されます。 ★「スクリプト先頭からの行/列」で既読フラグを保存しています。

4.2.2 ファイルログ

NSLaではbg命令に加えてbgmおよびld命令の読み込みも保存しています。
savedir時の挙動は既読ログと同じですが、ファイルログのみデフォルトでオフである点に注意してください。

filelog "flogl.dat"

より多くの命令や自作関数でログを追加したい場合、NSNSaddfilelog("ファイル名")の形でログに追加できます。

if節で判定を行う際は、fchk("ファイル名")の形を用います。

if(fchk("*ラベル名")) 既知のファイルです。 end

特殊文字構文として命令中に埋め込む場合、&(fchk("ファイル名") && "true.png" || "false.png")のように用います。

lsp 1,&(fchk("ファイル名") and "true" or "false")+".png",0,0

両者の実体はLua関数です。特に後者は引数のように埋め込むLua[2.16.2]と三項演算の組み合わせです。
NSLaは起動時にfchk=NSNSfchkと代入しようとします。

--複数の引数を指定すると、複雑な判定を行うことができます。 NSNSlchk({"ファイル1","ファイル2","ファイル3"},true,true) --第1引数には文字列、またはラベル名文字列が並んだテーブルを渡します。 -- この文字列がNSNSlabellogテーブルに保存されているかをチェックします。 --第1引数がテーブル(=複数の値)だった場合、第2引数で判定方法を決めます。 -- 第2引数が真なら「ファイルのうちどれかが既知なら真(or)」で判定、偽なら「全て既知なら真(and)」で判定します。

4.2.3 ラベルログ

savedir時の注意は既読ログ・ファイルログのそれと同じです。

--デフォルトで以下のファイル名が宣言されています。ラベルログが不要な場合は=nilとします。 NSNSkidokulabelpath="labell" --true(既定値)ならラベル名を暗号化して管理します(メモ帳などでログファイルを開いてもラベル名は読めません) NSNSfilelabellogangou=true

if節で既読判定を行う場合、lchk("*ラベル名")の形で用います。

if(lchk("*ラベル名")) 既知のラベルです。 end

特殊文字構文として命令中に埋め込む場合、&(lchk("*ラベル名") && "true.png" || "false.png")のように用います。

lsp 1,&(lchk("*ラベル名") and "true" or "false")+".png",0,0

fchk()と同じく実体はLua関数です。

--複数の引数を指定すると、複雑な判定を行うことができます。 NSNSlchk({"*ラベル1","*ラベル2","*ラベル3"},true,true) --第1引数には文字列、またはラベル名文字列が並んだテーブルを渡します。 -- この文字列がNSNSlabellogテーブルに保存されているかをチェックします。 --第2引数がtrueならfalseログ(仮想スクリプト内でのみ読んだ事のあるラベル名)も既知と認めます(※)。 --第1引数がテーブル(=複数の値)だった場合、第3引数で判定方法を決めます。 -- 第3引数が真なら「ラベルのうちどれかが既知なら真(or)」で判定、偽なら「全て既知なら真(and)」で判定します。

falseで多重実行したns関数内の仮想スクリプト[3.2.7]でのみ通過したラベルを記録するか否か、オプションで設定できます。

NSNSkidokulabelstrict=false(既定値) --trueの場合、仮想モード中のラベルは完全に破棄される。 --falseの場合、仮想モード中のラベルはfalseとして保存され、lchk()の第二引数が真である場合のみ既知と見なす。

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

★nscripterDS.dll(をnds関数で運用している環境)またはnsogg2.dllの使用が前提  オプションで指定する

4.2.5 バックログと巻き戻し機能(ヒストリー)(NSNShistory変数)

4.3 セーブ、リセット、終了処理

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

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

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

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

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

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

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

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

4.3.5 リセットボタン(F12)

5.1 デバッグコンソール(F11)

5.1.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の入力待ち時は裏でアニメーションコールバックが実行されており、放っておくと多重に実行される恐れがあるためです。

5.1.2 変数ウォッチ

5.1.3 ステップ実行

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

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

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

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

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

エスケープ「::」

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

長いコードを実行しても構いませんが、処理の末尾まで単一命令として扱われる(=NSLaが介在しない)点に注意してください。 F12キー(リセットボタン、命令の合間に判定が行われる)のレスポンスを考えるならば、「描画やアニメーションを挟む命令」の直後にコードを区切った方が賢明です。 加工するためloadstringを乗っ取っている点に注意

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

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

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

(単一の変数ではなく)複雑な値をNScriptr命令の引数に用いたい場合、そのようにLuaコードを記述できます。

bg ^^hoge^^,1 bg ^^foo..bar^^,1 bg ^^hoge="foo" return hoge^^,1


^^〜^^内部には
@「(そのままreturn可能な)変数」
A「(そのままreturn可能な)式」
B「最終的に値をreturnする関数の中身」
何れかを記述してください。

テキストに埋め込む事もできます。

あいうえお^^kakikukeko^^さしすせそ@

6.1.4 「:」「%」に関する注意

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

6.1.5 if/forの真の姿

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

7.1 NSLaの真の姿 - Lua関数としてのNSLa

7.1.1 NSLaの「実際の」組み込み方

7.1.2 NSLa付属のsystem.luaが行っている処理

7.2 拡張スクリプトの動的な読み込みと実行

7.2.1 NSNSInitializing()

7.2.2 nsload()、nsloadfile()

7.2.3 nsboot()、nsfile()

7.2.4 ns()

7.2.5 NSLaの多重実行

7.2.6 純粋(true)実行

7.2.7 仮想(false)実行

7.3 埋め込みLuaに追加している仕様(loadstringに施した仕掛け)

7.3.1 全般的な注意

7.3.2 テーブル定義時の全角キー

7.3.3 全角キーと糖衣構文

7.3.4 アロー関数もどき

7.3.5 デフォルト値を持つ関数の引数

7.3.6 あいまい連結(Optional Chaining)

7.3.7 論理演算子の互換

7.3.8 "1.."の有効化

7.3.9 全角のグローバル変数

8.1 コンバートツールで修正される処理

8.1.1 if後のコロン(:)

8.1.2 演算子「mod」→「%」

8.1.3 演算子「=」「&」「|」→「==」「&&」「||」

8.1.4 「end」→「nsend」

8.1.5 「game」→「return」

8.1.6 「trap "off"」→「trap off」

8.1.7 「return "*label"」→「return *"label"」

8.1.8 「for %0=1 to 3 step 2」→「for %0=1,3,2」

8.1.9 getparamの関数引数化

8.1.10 movの略記化

8.1.11 配列変数のLua化

8.2 コンバータが警告する処理(手動での修正が必要)

8.2.1 旧(nsa)アーカイブの使用

8.2.2 defsub/luasub不可命令

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

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

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

8.3 NSLaが対応していない処理(非互換性)

8.3.1 definereset

8.3.2 テキストボタン

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

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

9.1 Lua標準ライブラリに追加された関数

9.1.1 math.limit()

9.1.2 string.split()

9.1.3 new() (table.new)

9.1.4 table.size()

9.1.5 table.map()

9.1.6 table.filter()

9.1.7 table.pile()

9.1.8 table.pack()

9.1.9 table.flat()

9.1.10 table.compact()

9.1.11 table.copy()

9.1.12 table.overwrite()

9.1.13 table.set()

9.1.14 table.delset()

9.1.15 table.andset()

9.1.16 table.orset()

9.1.17 table.xorset()

9.1.18 table.decset()

9.1.19 os.copy()

9.1.20 os.filelist()

9.1.21 os.mkdir()

9.1.22 os.lunation()

9.1.23 luadata.save()

9.1.24 luadata.load()

9.1.25 luadata.tload()

9.1.26 NSNSinitializing()

9.1.27 NSNScaption()

9.1.28 NSNSsetwindow()

9.1.29 NSNSpermanentbuttons()

9.1.30 NSNSmov()

9.1.31 NSNScheckcoroutine()

9.1.32 NSNStoplain()

9.1.33 NSNSreadfile()

9.1.34 nsboot()

9.1.35 nsfile()

9.1.36 nsload()

9.1.37 nsloadfile()

9.1.38 ns()

9.1.39 alert()

9.1.40 ensafe()

9.2 Lua標準ライブラリから仕様変更した関数

9.2.1 math.min()

9.2.2 math.max()

9.2.3 table.sort()

9.2.4 loadstring()

9.2.5 error()

9.3 組み込み済みNScripterプラグイン

9.4 組み込み済みLuaライブラリ