maple & chicken

適当に垂れ流す。メイプルのエミュ鯖に関する話がメインになるとおもいます。

js 基本編2

早速ブログのモチベが下がってきたけど頑張る。
あ、あとコメント欄で質問受け付けてます。エミュに関することなら何でもどうぞ。
(望む答えが返ってくるとは限りませんが…)

statusの使い方。その1

前回の内容だけではメッセージが一つだけのNPCしか作ることはできません。
statusを使いますがstatusって言ってもただの変数に過ぎません。
基本的にはactionが何回呼び出されたか数え、その回数に応じて動作を変えていきます。

var status = -1;

function action(mode, type, selection) {
    status++;

    if(status == 0) {
        cm.sendNext("メッセージ1");
    } else if(status == 1) {
        cm.sendOk("メッセージ2");
        cm.dispose();
    }
}

スペースの都合上start()には消えてもらいました。
1回目にaction()が呼び出されたとき、4:status++;によってstatusが0になります。
よって条件分岐でメッセージ1が表示されます。
そこでNEXTが押されると再度action()が呼び出され同じようにstatusが1になります。
statusはグローバル関数として宣言されているので値は引き継がれます。
statusが1になっているので分岐してメッセージ2になります。

今回はif文を使いましたがswitchを使っても構いません。
使うとこのようになります

var status = -1;

function action(mode, type, selection) {
    status++;

    switch (status) {
        case 0:
            cm.sendNext("メッセージ1");
            break;
        case 1:
            cm.sendOk("メッセージ2");
            cm.dispose();
            break;
    }
}

どちら使うかは完全に好みです。分岐が増えてくるとswitchのほうが速いですが微々たるもんです。
おそらく何万分の1秒の世界でしょうか

ちなみに僕はswitch派です(だって追加削除が楽で読みやすいんだもの)

status その2

上のサンプルではインクリメントがそのまま置かれてますが条件つけて置く場合があります。
ざっくり言うとボタンが3つ以上あるNPCウィンドウを使うとき、です。

例えば……sendYesNo()←YesとNoとEND CHATの3つ。
このままだとYes押してもNo押しても次のメッセージに進んでしまいます。(そういう意図のプログラムもあるっちゃあるけど)

Yesだとそのまま次のメッセージへ、Noなら別の処理を…ってしたいですよね。
判別するにはmodeの引数を使います。

var status = -1;

function action(mode, type, selection) {
    
    if(mode == 1) {
        status++;
    } else {
        status = 99;
    }
    
    switch (status) {
        case 0:
            cm.sendYesNo("メッセージ1");
            break;
        case 1:
            cm.sendOk("メッセージ2");
            cm.dispose();
            break;
        case 99:
            cm.sendOk("NOが押されました");
            cm.dispose();
            break;
    }
}

このようにしてみました。
基本的にYESNOのYESやNextPrevのNEXTのように肯定的なボタンが押された場合1が、NOやPREVなどの否定的なボタンの場合は0がmodeの引数として渡されます。
(詳しくは前の記事にまとめてあります。)

なのでmodeが1のときは加算、0のときの処理を書いてやれば良いわけです。
こちらのサンプルではstatusに99を代入してswitchに99のときの処理を追加しています。
else{}内に直接書いてもいいですがその時は必ずreturn;を書くようにしましょう。

    if(mode == 1) {
        status++;
    } else {
        cm.sendOk("NOが押されました");
        cm.dispose();
        return;
    }

そうでないと処理がそこで終わらずswitch文にまで突入します。
同じようなバグで、構築の砦にやらかしたJSが公開されています(わたしがやらかしました)。

あとstatus--;にすると前のメッセージに戻るというような動作になります(PREVを使うときは基本これかな。)

YesNoもNextPrevも両方使いたい!って方はtypeで分岐処理してください。
サンプルおいておくので各自理解してください(丸投げ)

var status = -1;

function action(mode, type, selection) {
    
    if(mode == 1) {
        status++;
    } else {
        status = type ? 99 : 98; //直前のウィンドウがsendYesNoならtype=4、sendNextPrevならtype=0
    }
    
    switch (status) {
        case 0:
            cm.sendNext("メッセージ1");
            break;
        case 1:
            cm.sendNextPrev("メッセージ2");
            break;
        case 2:
            cm.sendYesNo("メッセージ3");
            break;
        case 3:
            cm.sendOk("メッセージ4");
            cm.dispose();
            break;
        case 98:
            cm.sendOk("PREVが押されました");
            cm.dispose();
            break;
        case 99:
            cm.sendOk("NOが押されました");
            cm.dispose();
            break;
    }
}

typeの値についても前の記事に書いてます。
ちなみにtype ? 99 : 98;とかあるのは3項演算子です。
typeの部分が論理式になっていて真の場合は":"の前、偽なら後の式が使われます。
式が1行とかの短いものならifより可読性が高くなるかもしれません。(どうでもいい)


長くなりすぎたので今回はここまでです。
次回はsendSimpleによる分岐について書く予定です

追記 10/05:
一部修正しました