※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

1番単純な戦闘、ピップと敵との1対1の素手での殴りあいをしましょう。必要な戦闘を処理する関数はこのようになります。

combat.concounter() 敵の生命点や攻撃基準点、追加被害点などのステータスを読み込む
click_combat_start() ユーザーが「戦闘開始」をクリックしたときに、敵味方の攻撃順が指定してあるか調べる
combat.roll_Pip_quick() ピップの素早さを決めるサイコロを振る
combat.get_Pip_quick() サイコロの目をピップの素早さに代入する
combat.roll_enemy_quick() 敵の素早さを決めるサイコロを振る
combat.get_enemy_quick() サイコロの目を敵の素早さに代入する
combat.compare_quick() ピップと敵のどちらが先攻するか決める
combat.Pip_select() ピップが行動可能か調べ、ユーザーにピップの行動を選ぶよう促す
click_punch() 「殴る」ボタンをクリックしたときに、ピップの打撃手段を素手にする
combat.Pip_strike() ピップが素手や剣などの打撃攻撃時の被害点計算
combat.Pip2enemy_turn() 戦闘を続行して敵にターンを渡すかどうか判断
combat.enemy_select() 敵が行動可能か、どの行動をするかを決める
combat.enemy_do() 敵の行動
combat.enemy2Pip_turn() 戦闘を続行してピップにターンを渡すかどうか判断
combat.result() 戦闘を終了して経験値を獲得
combat.reset() 戦闘後に敵を初期化、戦闘中のみの効果を消す

下のような戦闘全体を管理する combat.main() 関数は作ることができません。なぜなら、途中にサイコロを振る動作があり、setTimeout() 関数を使うからです。setTimeout 関数があると、JavaScriptは setTimeout 関数をいったん素通りして、setTimeout 関数以降の処理が全部終わってから、setTimeout 関数で指定されたミリ秒後に動作します。サイコロの目が決まるまで待ってくれません。サイコロを振る命令を書いて、次の行にサイコロの目に応じた処理をさせようとしてもダメだということです。

// 実装できない例
function combat.main () {
    combat.function1(); // 敵のデータ読み込み
    combat.function2(); // 戦闘前のサイコロを振る
    combat.function3(); // 戦闘前のサイコロの目を使う
    while (combat.condition() === true) {
        combat.function4(); // 味方のサイコロを振る
        combat.function5(); // 味方のサイコロの目を使う
        combat.function6(); // 敵のサイコロを振る
        combat.function7(); // 敵のサイコロの目を使う
   }
    combat.function8(); // 経験値獲得
    combat.function9(); // 敵のリセット
}

仕方なしに、、それぞれの細分化された戦闘を処理する関数の最後に、次の戦闘処理関数を呼び出すような芋づる式ににしました。

余計な混乱を避けるため、魔法の特殊効果、毒などの特殊効果の文はすべて省いています。完全な関数は後で見せます。

// 敵の生命点や攻撃基準点、追加被害点などのステータスを読み込む
combat.encounter = function (){
    var i;

    enemy_party.exist = true; // 敵パーティが現れた。
    Pip.quick = 0;            // ピップの素早さ初期化
    enemy_party.quick = 0;    // 敵パーティの素早さ初期化

    if (Section.num === "46") { //まぬけな百姓
        enemy_party.id_num = 1; // 敵パーティのID番号
        enemy_party.num = 1;    // 敵パーティの敵数
        enemy_party.quick = -1; // ピップが先攻
    }

    enemy_party.name = enemy_data[enemy_party.id_num].name; // 敵パーティ名の読み込み

    i = 0; // 敵ステータスの読み込み
    enemy[i].id_num =  enemy_party.id_num; // 敵のID番号
    enemy[i].name = enemy_data[enemy_party.id_num].name; // 敵の名前
    enemy[i].max_LIFE_POINT = enemy_data[enemy_party.id_num].max_LIFE_POINT; // 敵の最大生命点
    enemy[i].LIFE_POINT = enemy_data[enemy_party.id_num].LIFE_POINT; //  敵の生命点
    enemy[i].attack_base = enemy_data[enemy_party.id_num].attack_base; // 敵の攻撃基準点
    enemy[i].extra_damage = enemy_data[enemy_party.id_num].extra_damage; // 敵の追加被害点
    enemy[i].defence = enemy_data[enemy_party.id_num].defence; // 敵の防御力
    enemy[i].attack_way = enemy_data[enemy_party.id_num].attack_way; // 敵の攻撃手段
    enemy[i].Bribery_amount = enemy_data[enemy_party.id_num].Bribery_amount; // 敵のワイロ買収に必要な金貨

    update_status(); // 表示の更新

    add_msg("戦闘を開始するには「戦闘開始」をクリックせよ。「友好反応」「ワイロ」「逃亡」などはそのボタンをクリックせよ。");
}
// ユーザーが「戦闘開始」をクリックしたときに、敵味方の攻撃順が指定してあるか調べる
function click_combat_start() {
    add_msg("戦闘開始をクリックした。");
    if (enemy_party.exist === true) {
        combat.onCombat = true; // 戦闘中フラグをtrueに
        if (Pip.quick !== enemy_party.quick) { // どちらが先攻か既に決まっていれば
            combat.compare_quick();
        } else { // どちらが先攻か決める必要があるなら
            combat.roll_Pip_quick();
        }
    } else {
        add_msg("敵がいないので何も起こらない。");
    }
}
// ピップの素早さを決めるサイコロを振る
combat.roll_Pip_quick = function (){
    add_msg("ピップの素早さのサイコロを1個振れ。");
    dice.start(1, "combat.get_Pip_quick()");
}
//サイコロの目をピップの素早さに代入する
combat.get_Pip_quick = function () {
    Pip.quick = dice.die1pip;
    add_msg("ピップの素早さは" + Pip.quick);
    combat.roll_enemy_quick();
}
// 敵の素早さを決めるサイコロを振る
combat.roll_enemy_quick = function (){
    add_msg(enemy_party.name + "の素早さのサイコロを1個振れ。");
    window.setTimeout('dice.start(1, "combat.get_enemy_quick()");', combat.wait_time);
}
// サイコロの目を敵の素早さに代入する
combat.get_enemy_quick = function () {
    enemy_party.quick = dice.die1pip;
    add_msg(enemy_party.name + "の素早さは" + enemy_party.quick);
    combat.compare_quick();
}
// ピップと敵のどちらが先攻するか決める
combat.compare_quick = function () {
    if (Pip.quick === enemy_party.quick) {
        Pip.quick = 0; // ピップの素早さを初期化
        enemy_party.quick = 0; // 敵パーティの素早さを初期化
        add_msg("ピップと" + enemy_party.name + "は同じ目を出した。サイコロを振り直しだ。");
        dice.start(1, "combat.get_Pip_quick()");
    } else if (Pip.quick > enemy_party.quick) { // ピップの方が素早い
        add_msg("ピップが先手を取った。");
        combat.Pip_select();
    } else { // 敵パーティの方が素早い
        add_msg(enemy_party.name + "が先手を取った。");
        combat.enemy_select(0);
    }
}
// ピップが行動可能か調べ、ユーザーにピップの行動ボタンをクリックするよう促す
combat.Pip_select = function (){
    //add_msg("combat.Pip_select()に入った。"); //デバッグ表示用
    if (Pip.LIFE_POINT <= 0) { // 生命点0以下で死
        add_msg("ピップは死んでいる。。。");
        combat.Pip2enemy_turn();
    } else if (Pip.LIFE_POINT <= 5) { // 生命点5以下で気絶
        add_msg("ピップは気絶している。。。");
        combat.Pip2enemy_turn();
    } else { // ピップが行動可能
        add_msg("ピップはどうする? 「殴る」などの行動ボタンをクリックせよ。");
    }
}
// 「殴る」ボタンをクリックしたときに、ピップの打撃手段を素手にする
function click_punch() {
    Pip.attack_base = 6; // ピップの攻撃基準点
    Pip.extra_damage = 0; // ピップの追加被害点
    Pip.attack_way = "素手"; // ピップの攻撃方法
    dice.start(2,"combat.Pip_strike()");
}
// ピップが素手や剣などの打撃攻撃時の被害点計算
combat.Pip_strike = function () {
    //add_msg("pip_strikeに入った。"); デバッグ表示用
    var attack_point = Math.max(dice.dice12pip - Pip.attack_base, 0) + Pip.extra_damage; // 攻撃力
    var damage_point = attack_point - enemy[i].defence; // 敵へ与える被害点

    add_msg("ピップは" + Pip.attack_way + "で" + enemy[i].name + "を攻撃。");

    if (dice.dice12pip - Pip.attack_base <= 0) { // サイコロの目が攻撃基準点以下
        add_msg("空振り!");
    } else if (damage_point <= 0) { // 攻撃が当たったが防御されて被害点無し
        add_msg("ミス! " + enemy[i].name + "に攻撃が通らない。");
    } else { // 敵に被害を与えた
        enemy[i].LIFE_POINT -= damage_point;
        add_msg("ピップは" + enemy[i].name + "に" + damage_point + "点の被害点を与えた。");

        update_status();
    }
    combat.Pip2enemy_turn();
}
// 戦闘を続行して敵にターンを渡すかどうか判断
combat.Pip2enemy_turn = function () {
    var i;
    var max_enemy_LIFE_POINT = 0;
    for (i = 0; i < enemy.length; i++) { // 敵の最大生命点を求める
        max_enemy_LIFE_POINT = Math.max(max_enemy_LIFE_POINT, enemy[i].LIFE_POINT);
    }

    if (Pip.LIFE_POINT <= 0) { //ピップが死んだ
        add_msg("ピップは生命点が0になった。14に行け。");
    } else if (max_enemy_LIFE_POINT <= 0) { //敵が死んだ
        add_msg("敵をやっつけた!");
        combat.result();    //戦後処理へ
    } else {
        combat.enemy_select(0);
        }
    }
}
// 敵が行動可能か、どの行動をするかを決める
combat.enemy_select = function (i){ // 引数iは敵の番号
    //add_msg("combat.enemy_select(" + i + ")に入った。"); // デバッグ用
    
    if (enemy[i].max_LIFE_POINT <= 0 ) { // 生死を問わず敵がいれば最大生命点は0より大きいはず
	//add_msg("敵" + i + "は初めからいない。");
    } else if (enemy[i].LIFE_POINT <= 0 && enemy[i].max_LIFE_POINT > 0) {
        add_msg(enemy[i].name + "は死んでいる。");
        combat.enemy_do(i);
    } else if (enemy[i].LIFE_POINT <= 5 && enemy[i].max_LIFE_POINT > 5) {
        add_msg(enemy[i].name + "は気絶している。");
        combat.enemy_do(i);
    } else {
        add_msg(enemy[i].name + "は" + enemy[i].attack_way + "でピップを攻撃。");
        dice.start(2, "combat.enemy_do('" + i + "')");
    }
}
// 敵の行動
combat.enemy_do = function (i) {
    //add_msg("combat.enemy_do(" + i + ")に入った。"); // デバッグ用

    var attack_point = Math.max(dice.dice12pip - enemy[i].attack_base, 0) + enemy[i].extra_damage;
    var damage_point = attack_point - Pip.defence;

    if (enemy[i].LIFE_POINT <= 0 && enemy[i].max_LIFE_POINT > 0) {
        //死んでいる 何もしない
    } else if (enemy[i].LIFE_POINT <= 5 && enemy[i].max_LIFE_POINT > 5) {
        //気絶している 何もしない
    } else {  //攻撃してくる
        if (dice.dice12pip <= enemy[i].attack_base) {
            add_msg("空振り!");
        } else if (damage_point <= 0) {
            add_msg("ミス! ピップは被害を受けない。");
        } else { // 被害点が1以上
            Pip.LIFE_POINT -= damage_point;
            add_msg("ピップは" + enemy[i].name + "から" + damage_point + "点の被害を受けた。");
        }
    }

    update_status();
    combat.enemy2Pip_turn(i);
}
// 戦闘を続行してピップにターンを渡すかどうか判断
combat.enemy2Pip_turn = function (i) {
    var j, k;
    var max_enemy_LIFE_POINT = 0;
    for (j = 0; j < enemy.length; j++) { // 敵の最大生命点を求める
        max_enemy_LIFE_POINT = Math.max(max_enemy_LIFE_POINT, enemy[j].LIFE_POINT);
    }

    if (Pip.LIFE_POINT <= 0) { //ピップが死んだ
        add_msg("ピップは生命点が0になった。14に行け。");
    } else if (max_enemy_LIFE_POINT <= 0) { //敵が死んだ
        add_msg("敵をやっつけた!");
        combat.result();    //戦後処理へ
    } else if (i !== enemy.length - 1) { // 敵が最終でなければ
        i++;
        combat.enemy_select(i); // 次の敵の行動
    } else { // 敵が最終なら
        combat.Pip_select(); // ピップに行動を渡す
    }
}
// 戦闘を終了して経験値を獲得
combat.result = function () {
    Pip.EXPERIENCE_POINT++; //通常の敵を倒して経験値ゲット
    combat.reset();
}
// 戦闘後に敵を初期化
combat.reset = function () {
    //add_msg("combat.reset()に入った。");
    var i;

    combat.onCombat = false; // 戦闘中フラグをfalseに

    enemy_party = {
        name : "ダミー",
        exist: false,
        id_num : 0,
        num: 0,
        quick : 0,
        first_strike : false,
        Friendly_Reaction_tried : false,
        Bribery_tried : false
    };

    for (i = 0; i < enemy.length; i++) { // 敵全員の初期化
        enemy[i] = {
            id_num: 0,
            name: "ダミー",
            max_LIFE_POINT:  0,
            LIFE_POINT:  0,
            attack_base: 6,
            extra_damage: 0,
            defence: 0,
            attack_way: "素手",
            Section : "",
            Bribery_amount : 0,
            Friendly_Reaction_tried : false,
            Friendly_Reaction_die1pip : 0,
            Friendly_Reaction : false,
            Bribery_tried : false,
            Bribery : false,
            sleep_globe: 0,
            gelatin : false,
            Eye_of_Horus : 0,
            Laughing_Globe : 0,
            Psionic_Helm_Stop : 0,
            Psionic_Helm_Half : false
        };
    }

    update_status();
}