static int _calc_fail_rate(_spell_ptr spell) { int result = 0; int k_idx = _lookup_kind(&spell->kind); int lvl = k_info[k_idx].level; if (spell->kind.tval == TV_ROD) lvl = lvl * 5/6 - 5; result = lvl * 4 / 5 + 20; result -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); lvl /= 2; if (p_ptr->lev > lvl) result -= 3 * (p_ptr->lev - lvl); result = mod_spell_chance_1(result, REALM_NONE); result = MAX(result, adj_mag_fail[p_ptr->stat_ind[A_INT]]); if (p_ptr->stun > 50) result += 25; else if (p_ptr->stun) result += 15; if (result> 95) result = 95; result = mod_spell_chance_2(result, REALM_NONE); return result; }
/*! * @brief 使用可能な青魔法を選択する / * Allow user to choose a imitation. * @param sn 選択したモンスター攻撃ID、キャンセルの場合-1、不正な選択の場合-2を返す * @return 発動可能な魔法を選択した場合TRUE、キャンセル処理か不正な選択が行われた場合FALSEを返す。 * @details * If a valid spell is chosen, saves it in '*sn' and returns TRUE\n * If the user hits escape, returns FALSE, and set '*sn' to -1\n * If there are no legal choices, returns FALSE, and sets '*sn' to -2\n *\n * The "prompt" should be "cast", "recite", or "study"\n * The "known" should be TRUE for cast/pray, FALSE for study\n *\n * nb: This function has a (trivial) display bug which will be obvious\n * when you run it. It's probably easy to fix but I haven't tried,\n * sorry.\n */ static int get_learned_power(int *sn) { int i = 0; int num = 0; int y = 1; int x = 18; int minfail = 0; int plev = p_ptr->lev; int chance = 0; int ask = TRUE, mode = 0; int spellnum[MAX_MONSPELLS]; char ch; char choice; char out_val[160]; char comment[80]; s32b f4 = 0, f5 = 0, f6 = 0; cptr p = _("魔法", "magic"); monster_power spell; bool flag, redraw; int menu_line = (use_menu ? 1 : 0); /* Assume cancelled */ *sn = (-1); /* Nothing chosen yet */ flag = FALSE; /* No redraw yet */ redraw = FALSE; #ifdef ALLOW_REPEAT /* TNB */ /* Get the spell, if available */ if (repeat_pull(sn)) { /* Success */ return (TRUE); } #endif /* ALLOW_REPEAT -- TNB */ if (use_menu) { screen_save(); while(!mode) { #ifdef JP prt(format(" %s ボルト", (menu_line == 1) ? "》" : " "), 2, 14); prt(format(" %s ボール", (menu_line == 2) ? "》" : " "), 3, 14); prt(format(" %s ブレス", (menu_line == 3) ? "》" : " "), 4, 14); prt(format(" %s 召喚", (menu_line == 4) ? "》" : " "), 5, 14); prt(format(" %s その他", (menu_line == 5) ? "》" : " "), 6, 14); prt("どの種類の魔法を使いますか?", 0, 0); #else prt(format(" %s bolt", (menu_line == 1) ? "> " : " "), 2, 14); prt(format(" %s ball", (menu_line == 2) ? "> " : " "), 3, 14); prt(format(" %s breath", (menu_line == 3) ? "> " : " "), 4, 14); prt(format(" %s sommoning", (menu_line == 4) ? "> " : " "), 5, 14); prt(format(" %s others", (menu_line == 5) ? "> " : " "), 6, 14); prt("use which type of magic? ", 0, 0); #endif choice = inkey(); switch(choice) { case ESCAPE: case 'z': case 'Z': screen_load(); return FALSE; case '2': case 'j': case 'J': menu_line++; break; case '8': case 'k': case 'K': menu_line+= 4; break; case '\r': case 'x': case 'X': mode = menu_line; break; } if (menu_line > 5) menu_line -= 5; } screen_load(); } else { sprintf(comment, _("[A]ボルト, [B]ボール, [C]ブレス, [D]召喚, [E]その他:", "[A] bolt, [B] ball, [C] breath, [D] summoning, [E] others:")); while (TRUE) { if (!get_com(comment, &ch, TRUE)) { return FALSE; } if (ch == 'A' || ch == 'a') { mode = 1; break; } if (ch == 'B' || ch == 'b') { mode = 2; break; } if (ch == 'C' || ch == 'c') { mode = 3; break; } if (ch == 'D' || ch == 'd') { mode = 4; break; } if (ch == 'E' || ch == 'e') { mode = 5; break; } } } set_rf_masks(&f4, &f5, &f6, mode); for (i = 0, num = 0; i < 32; i++) { if ((0x00000001 << i) & f4) spellnum[num++] = i; } for (; i < 64; i++) { if ((0x00000001 << (i - 32)) & f5) spellnum[num++] = i; } for (; i < 96; i++) { if ((0x00000001 << (i - 64)) & f6) spellnum[num++] = i; } for (i = 0; i < num; i++) { if (p_ptr->magic_num2[spellnum[i]]) { if (use_menu) menu_line = i+1; break; } } if (i == num) { msg_print(_("その種類の魔法は覚えていない!", "You don't know any spell of this type.")); return (FALSE); } /* Build a prompt (accept all spells) */ (void)strnfmt(out_val, 78, _("(%c-%c, '*'で一覧, ESC) どの%sを唱えますか?", "(%c-%c, *=List, ESC=exit) Use which %s? "), I2A(0), I2A(num - 1), p); if (use_menu) screen_save(); /* Get a spell from the user */ choice= (always_show_list || use_menu) ? ESCAPE:1 ; while (!flag) { if(choice==ESCAPE) choice = ' '; else if( !get_com(out_val, &choice, TRUE) )break; if (use_menu && choice != ' ') { switch(choice) { case '0': { screen_load(); return (FALSE); } case '8': case 'k': case 'K': { do { menu_line += (num-1); if (menu_line > num) menu_line -= num; } while(!p_ptr->magic_num2[spellnum[menu_line-1]]); break; } case '2': case 'j': case 'J': { do { menu_line++; if (menu_line > num) menu_line -= num; } while(!p_ptr->magic_num2[spellnum[menu_line-1]]); break; } case '6': case 'l': case 'L': { menu_line=num; while(!p_ptr->magic_num2[spellnum[menu_line-1]]) menu_line--; break; } case '4': case 'h': case 'H': { menu_line=1; while(!p_ptr->magic_num2[spellnum[menu_line-1]]) menu_line++; break; } case 'x': case 'X': case '\r': { i = menu_line - 1; ask = FALSE; break; } } } /* Request redraw */ if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) { /* Show the list */ if (!redraw || use_menu) { char psi_desc[80]; /* Show list */ redraw = TRUE; /* Save the screen */ if (!use_menu) screen_save(); /* Display a list of spells */ prt("", y, x); put_str(_("名前", "Name"), y, x + 5); put_str(_("MP 失率 効果", "SP Fail Info"), y, x + 33); /* Dump the spells */ for (i = 0; i < num; i++) { int need_mana; prt("", y + i + 1, x); if (!p_ptr->magic_num2[spellnum[i]]) continue; /* Access the spell */ spell = monster_powers[spellnum[i]]; chance = spell.fail; /* Reduce failure rate by "effective" level adjustment */ if (plev > spell.level) chance -= 3 * (plev - spell.level); else chance += (spell.level - plev); /* Reduce failure rate by INT/WIS adjustment */ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); chance = mod_spell_chance_1(chance); need_mana = mod_need_mana(monster_powers[spellnum[i]].smana, 0, REALM_NONE); /* Not enough mana to cast */ if (need_mana > p_ptr->csp) { chance += 5 * (need_mana - p_ptr->csp); } /* Extract the minimum failure rate */ minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; /* Minimum failure rate */ if (chance < minfail) chance = minfail; /* Stunning makes spells harder */ if (p_ptr->stun > 50) chance += 25; else if (p_ptr->stun) chance += 15; /* Always a 5 percent chance of working */ if (chance > 95) chance = 95; chance = mod_spell_chance_2(chance); /* Get info */ learned_info(comment, spellnum[i]); if (use_menu) { if (i == (menu_line-1)) strcpy(psi_desc, _(" 》", " > ")); else strcpy(psi_desc, " "); } else sprintf(psi_desc, " %c)", I2A(i)); /* Dump the spell --(-- */ strcat(psi_desc, format(" %-26s %3d %3d%%%s", spell.name, need_mana, chance, comment)); prt(psi_desc, y + i + 1, x); } /* Clear the bottom line */ if (y < 22) prt("", y + i + 1, x); } /* Hide the list */ else { /* Hide list */ redraw = FALSE; /* Restore the screen */ screen_load(); } /* Redo asking */ continue; } if (!use_menu) { /* Note verify */ ask = isupper(choice); /* Lowercase */ if (ask) choice = tolower(choice); /* Extract request */ i = (islower(choice) ? A2I(choice) : -1); } /* Totally Illegal */ if ((i < 0) || (i >= num) || !p_ptr->magic_num2[spellnum[i]]) { bell(); continue; } /* Save the spell index */ spell = monster_powers[spellnum[i]]; /* Verify it */ if (ask) { char tmp_val[160]; /* Prompt */ (void) strnfmt(tmp_val, 78, _("%sの魔法を唱えますか?", "Use %s? "), monster_powers[spellnum[i]].name); /* Belay that order */ if (!get_check(tmp_val)) continue; } /* Stop the loop */ flag = TRUE; } /* Restore the screen */ if (redraw) screen_load(); /* Show choices */ p_ptr->window |= (PW_SPELL); /* Window stuff */ window_stuff(); /* Abort if needed */ if (!flag) return (FALSE); /* Save the choice */ (*sn) = spellnum[i]; #ifdef ALLOW_REPEAT /* TNB */ repeat_push(*sn); #endif /* ALLOW_REPEAT -- TNB */ /* Success */ return (TRUE); }
/*! * @brief 青魔法コマンドのメインルーチン / * do_cmd_cast calls this function if the player's class is 'Blue-Mage'. * @return 処理を実行したらTRUE、キャンセルした場合FALSEを返す。 */ bool do_cmd_cast_learned(void) { int n = 0; int chance; int minfail = 0; int plev = p_ptr->lev; monster_power spell; bool cast; int need_mana; /* not if confused */ if (p_ptr->confused) { msg_print(_("混乱していて唱えられない!", "You are too confused!")); return TRUE; } /* get power */ if (!get_learned_power(&n)) return FALSE; spell = monster_powers[n]; need_mana = mod_need_mana(spell.smana, 0, REALM_NONE); /* Verify "dangerous" spells */ if (need_mana > p_ptr->csp) { /* Warning */ msg_print(_("MPが足りません。", "You do not have enough mana to use this power.")); if (!over_exert) return FALSE; /* Verify */ if (!get_check(_("それでも挑戦しますか? ", "Attempt it anyway? "))) return FALSE; } /* Spell failure chance */ chance = spell.fail; /* Reduce failure rate by "effective" level adjustment */ if (plev > spell.level) chance -= 3 * (plev - spell.level); else chance += (spell.level - plev); /* Reduce failure rate by INT/WIS adjustment */ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); chance = mod_spell_chance_1(chance); /* Not enough mana to cast */ if (need_mana > p_ptr->csp) { chance += 5 * (need_mana - p_ptr->csp); } /* Extract the minimum failure rate */ minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; /* Minimum failure rate */ if (chance < minfail) chance = minfail; /* Stunning makes spells harder */ if (p_ptr->stun > 50) chance += 25; else if (p_ptr->stun) chance += 15; /* Always a 5 percent chance of working */ if (chance > 95) chance = 95; chance = mod_spell_chance_2(chance); /* Failed spell */ if (randint0(100) < chance) { if (flush_failure) flush(); msg_print(_("魔法をうまく唱えられなかった。", "You failed to concentrate hard enough!")); sound(SOUND_FAIL); if (n >= MS_S_KIN) /* Cast the spell */ cast = cast_learned_spell(n, FALSE); } else { sound(SOUND_ZAP); /* Cast the spell */ cast = cast_learned_spell(n, TRUE); if (!cast) return FALSE; } /* Sufficient mana */ if (need_mana <= p_ptr->csp) { /* Use some mana */ p_ptr->csp -= need_mana; } else { int oops = need_mana; /* No mana left */ p_ptr->csp = 0; p_ptr->csp_frac = 0; /* Message */ msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!")); /* Hack -- Bypass free action */ (void)set_paralyzed(p_ptr->paralyzed + randint1(5 * oops + 1)); chg_virtue(V_KNOWLEDGE, -10); /* Damage CON (possibly permanently) */ if (randint0(100) < 50) { bool perm = (randint0(100) < 25); /* Message */ msg_print(_("体を悪くしてしまった!", "You have damaged your health!")); /* Reduce constitution */ (void)dec_stat(A_CON, 15 + randint1(10), perm); } } /* Take a turn */ p_ptr->energy_use = 100; /* Window stuff */ p_ptr->redraw |= (PR_MANA); p_ptr->window |= (PW_PLAYER); p_ptr->window |= (PW_SPELL); return TRUE; }