/*! * @brief 一定時間毎に呪術で消費するMPを処理する / * Upkeeping hex spells Called from dungeon.c * @return なし */ void check_hex(void) { int spell; s32b need_mana; u32b need_mana_frac; bool res = FALSE; /* Spells spelled by player */ if (p_ptr->realm1 != REALM_HEX) return; if (!p_ptr->magic_num1[0] && !p_ptr->magic_num1[1]) return; if (p_ptr->magic_num1[1]) { p_ptr->magic_num1[0] = p_ptr->magic_num1[1]; p_ptr->magic_num1[1] = 0; res = TRUE; } /* Stop all spells when anti-magic ability is given */ if (p_ptr->anti_magic) { stop_hex_spell_all(); return; } need_mana = 0; for (spell = 0; spell < 32; spell++) { if (hex_spelling(spell)) { const magic_type *s_ptr; s_ptr = &technic_info[REALM_HEX - MIN_TECHNIC][spell]; need_mana += mod_need_mana(s_ptr->smana, spell, REALM_HEX); } } /* Culcurates final mana cost */ need_mana_frac = 0; s64b_div(&need_mana, &need_mana_frac, 0, 3); /* Divide by 3 */ need_mana += (p_ptr->magic_num2[0] - 1); /* Not enough mana */ if (s64b_cmp(p_ptr->csp, p_ptr->csp_frac, need_mana, need_mana_frac) < 0) { stop_hex_spell_all(); return; } /* Enough mana */ else { s64b_sub(&(p_ptr->csp), &(p_ptr->csp_frac), need_mana, need_mana_frac); p_ptr->redraw |= PR_MANA; if (res) { #ifdef JP msg_print("詠唱を再開した。"); #else msg_print("You restart spelling."); #endif p_ptr->action = ACTION_SPELL; /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS | PU_HP); /* Redraw map and status bar */ p_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE); /* Update monsters */ p_ptr->update |= (PU_MONSTERS); /* Window stuff */ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); } } /* Gain experiences of spelling spells */ for (spell = 0; spell < 32; spell++) { const magic_type *s_ptr; if (!hex_spelling(spell)) continue; s_ptr = &technic_info[REALM_HEX - MIN_TECHNIC][spell]; if (p_ptr->spell_exp[spell] < SPELL_EXP_BEGINNER) p_ptr->spell_exp[spell] += 5; else if(p_ptr->spell_exp[spell] < SPELL_EXP_SKILLED) { if (one_in_(2) && (dun_level > 4) && ((dun_level + 10) > p_ptr->lev)) p_ptr->spell_exp[spell] += 1; } else if(p_ptr->spell_exp[spell] < SPELL_EXP_EXPERT) { if (one_in_(5) && ((dun_level + 5) > p_ptr->lev) && ((dun_level + 5) > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; } else if(p_ptr->spell_exp[spell] < SPELL_EXP_MASTER) { if (one_in_(5) && ((dun_level + 5) > p_ptr->lev) && (dun_level > s_ptr->slevel)) p_ptr->spell_exp[spell] += 1; } } /* Do any effects of continual spells */ for (spell = 0; spell < 32; spell++) { if (hex_spelling(spell)) { do_spell(REALM_HEX, spell, SPELL_CONT); } } }
/*! * @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); }
static void _dump_book(doc_ptr doc, int realm, int book) { int k_idx = lookup_kind(realm2tval(realm), book); int i, increment = 64; caster_info *caster_ptr = get_caster_info(); if ((p_ptr->pclass == CLASS_SORCERER) || (p_ptr->pclass == CLASS_RED_MAGE)) increment = 0; else if (realm == p_ptr->realm1) increment = 0; else if (realm == p_ptr->realm2) increment = 32; if (realm == REALM_HISSATSU) { doc_printf(doc, "<color:G> %-25.25s Lvl SP %-15.15s Cast</color>\n", k_name + k_info[k_idx].name, "Desc"); } else { if (caster_ptr && (caster_ptr->options & CASTER_USE_HP)) doc_printf(doc, "<color:G> %-23.23s Profic Lvl HP Fail %-15.15s Cast Fail</color>\n", k_name + k_info[k_idx].name, "Desc"); else doc_printf(doc, "<color:G> %-23.23s Profic Lvl SP Fail %-15.15s Cast Fail</color>\n", k_name + k_info[k_idx].name, "Desc"); } for (i = 0; i < 8; i++) { int s_idx = book * 8 + i; magic_type *s_ptr; int cost; bool max = FALSE; char proficiency[10]; char info[80]; cptr comment; char line[160]; char color = 'w'; if (is_magic(realm)) s_ptr = &mp_ptr->info[realm - 1][s_idx]; else s_ptr = &technic_info[realm - MIN_TECHNIC][s_idx]; if (s_ptr->slevel >= 99) continue; if (realm == REALM_HISSATSU) cost = s_ptr->smana; else { s16b exp = experience_of_spell(s_idx, realm); int exp_level = spell_exp_level(exp); cost = mod_need_mana(s_ptr->smana, s_idx, realm); max = FALSE; if (!increment && (exp_level == EXP_LEVEL_MASTER)) max = TRUE; else if ((increment == 32) && (exp_level >= EXP_LEVEL_EXPERT)) max = TRUE; else if ((p_ptr->pclass == CLASS_RED_MAGE) && (exp_level >= EXP_LEVEL_SKILLED)) max = TRUE; strncpy(proficiency, exp_level_str[exp_level], 4); proficiency[3] = ']'; proficiency[4] = '\0'; } strcpy(info, do_spell(realm, s_idx, SPELL_INFO)); comment = info; if (p_ptr->pclass == CLASS_SORCERER || p_ptr->pclass == CLASS_RED_MAGE) { if (s_ptr->slevel > p_ptr->max_plv) { comment = "unknown"; color = 'D'; } else if (s_ptr->slevel > p_ptr->lev) { comment = "forgotten"; color = 'y'; } } else if ((realm == p_ptr->realm1) ? ((p_ptr->spell_forgotten1 & (1L << s_idx))) : ((p_ptr->spell_forgotten2 & (1L << s_idx)))) { comment = "forgotten"; color = 'y'; } else if (!((realm == p_ptr->realm1) ? (p_ptr->spell_learned1 & (1L << s_idx)) : (p_ptr->spell_learned2 & (1L << s_idx)))) { comment = "unknown"; if (s_ptr->slevel > p_ptr->lev) color = 'D'; else color = 'B'; } else if (!((realm == p_ptr->realm1) ? (p_ptr->spell_worked1 & (1L << s_idx)) : (p_ptr->spell_worked2 & (1L << s_idx)))) { comment = "untried"; } sprintf(line, " %c) ", I2A(i)); if (realm == REALM_HISSATSU) { spell_stats_ptr stats = spell_stats_old(realm, s_idx); strcat( line, format( "<color:%c>%-25s %3d %3d %-15.15s %5d</color>", color, do_spell(realm, s_idx, SPELL_NAME), s_ptr->slevel, cost, comment, stats->ct_cast ) ); } else { spell_stats_ptr stats = spell_stats_old(realm, s_idx); strcat( line, format( "<color:%c>%-25s%c%-4s %3d %3d %3d%% %-15.15s %5d %4d %3d%%</color>", color, do_spell(realm, s_idx, SPELL_NAME), (max ? '!' : ' '), proficiency, s_ptr->slevel, cost, spell_chance(s_idx, realm), comment, stats->ct_cast, stats->ct_fail, spell_stats_fail(stats) ) ); } doc_printf(doc, "%s\n", line); } doc_newline(doc); }
/*! * @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; }