1 #include "spell/spell-info.h"
2 #include "io/input-key-requester.h"
3 #include "monster-race/monster-race.h"
4 #include "player/player-class.h"
5 #include "player/player-skill.h"
6 #include "player/player-status-table.h"
7 #include "realm/realm-names-table.h"
8 #include "realm/realm-types.h"
9 #include "spell/spells-execution.h"
10 #include "system/floor-type-definition.h"
11 #include "system/monster-type-definition.h"
12 #include "term/screen-processor.h"
13 #include "term/term-color-types.h"
14 #include "util/int-char-converter.h"
15 #include "view/display-messages.h"
16 #include "world/world.h"
20 * Returns experience of a spell
21 * @param caster_ptr プレーヤーへの参照ポインタ
23 * @param use_realm 魔法領域
26 EXP experience_of_spell(player_type *caster_ptr, SPELL_IDX spell, REALM_IDX use_realm)
28 if (caster_ptr->pclass == CLASS_SORCERER)
29 return SPELL_EXP_MASTER;
30 else if (caster_ptr->pclass == CLASS_RED_MAGE)
31 return SPELL_EXP_SKILLED;
32 else if (use_realm == caster_ptr->realm1)
33 return caster_ptr->spell_exp[spell];
34 else if (use_realm == caster_ptr->realm2)
35 return caster_ptr->spell_exp[spell + 32];
42 * Modify mana consumption rate using spell exp and dec_mana
43 * @param caster_ptr プレーヤーへの参照ポインタ
44 * @param need_mana 基本消費MP
49 MANA_POINT mod_need_mana(player_type *caster_ptr, MANA_POINT need_mana, SPELL_IDX spell, REALM_IDX realm)
51 #define MANA_CONST 2400
53 #define DEC_MANA_DIV 3
54 if ((realm > REALM_NONE) && (realm <= MAX_REALM)) {
55 need_mana = need_mana * (MANA_CONST + SPELL_EXP_EXPERT - experience_of_spell(caster_ptr, spell, realm)) + (MANA_CONST - 1);
56 need_mana *= caster_ptr->dec_mana ? DEC_MANA_DIV : MANA_DIV;
57 need_mana /= MANA_CONST * MANA_DIV;
61 if (caster_ptr->dec_mana)
62 need_mana = (need_mana + 1) * DEC_MANA_DIV / MANA_DIV;
73 * @brief 呪文の失敗率修正処理1(呪い、消費魔力減少、呪文簡易化) /
74 * Modify spell fail rate
75 * Using to_m_chance, dec_mana, easy_spell and heavy_spell
76 * @param caster_ptr プレーヤーへの参照ポインタ
77 * @param chance 修正前失敗率
81 PERCENTAGE mod_spell_chance_1(player_type *caster_ptr, PERCENTAGE chance)
83 chance += caster_ptr->to_m_chance;
85 if (caster_ptr->heavy_spell)
88 if (caster_ptr->dec_mana && caster_ptr->easy_spell)
90 else if (caster_ptr->easy_spell)
92 else if (caster_ptr->dec_mana)
99 * @brief 呪文の失敗率修正処理2(消費魔力減少、呪い、負値修正) /
100 * Modify spell fail rate
101 * Using to_m_chance, dec_mana, easy_spell and heavy_spell
102 * @param caster_ptr プレーヤーへの参照ポインタ
103 * @param chance 修正前失敗率
105 * Modify spell fail rate (as "suffix" process)
106 * Using dec_mana, easy_spell and heavy_spell
107 * Note: variable "chance" cannot be negative.
110 PERCENTAGE mod_spell_chance_2(player_type *caster_ptr, PERCENTAGE chance)
112 if (caster_ptr->dec_mana)
114 if (caster_ptr->heavy_spell)
116 return MAX(chance, 0);
120 * @brief 呪文の失敗率計算メインルーチン /
121 * Returns spell chance of failure for spell -RAK-
122 * @param caster_ptr プレーヤーへの参照ポインタ
124 * @param use_realm 魔法領域ID
127 PERCENTAGE spell_chance(player_type *caster_ptr, SPELL_IDX spell, REALM_IDX use_realm)
129 if (!mp_ptr->spell_book)
131 if (use_realm == REALM_HISSATSU)
134 const magic_type *s_ptr;
135 if (!is_magic(use_realm)) {
136 s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
138 s_ptr = &mp_ptr->info[use_realm - 1][spell];
141 PERCENTAGE chance = s_ptr->sfail;
142 chance -= 3 * (caster_ptr->lev - s_ptr->slevel);
143 chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
144 if (caster_ptr->riding)
145 chance += (MAX(r_info[caster_ptr->current_floor_ptr->m_list[caster_ptr->riding].r_idx].level - caster_ptr->skill_exp[GINOU_RIDING] / 100 - 10, 0));
147 MANA_POINT need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, use_realm);
148 if (need_mana > caster_ptr->csp) {
149 chance += 5 * (need_mana - caster_ptr->csp);
152 if ((use_realm != caster_ptr->realm1) && ((caster_ptr->pclass == CLASS_MAGE) || (caster_ptr->pclass == CLASS_PRIEST)))
155 PERCENTAGE minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
156 if (mp_ptr->spell_xtra & MAGIC_FAIL_5PERCENT) {
161 if (((caster_ptr->pclass == CLASS_PRIEST) || (caster_ptr->pclass == CLASS_SORCERER)) && caster_ptr->icky_wield[0])
163 if (((caster_ptr->pclass == CLASS_PRIEST) || (caster_ptr->pclass == CLASS_SORCERER)) && caster_ptr->icky_wield[1])
166 chance = mod_spell_chance_1(caster_ptr, chance);
167 PERCENTAGE penalty = (mp_ptr->spell_stat == A_WIS) ? 10 : 4;
170 if ((caster_ptr->align > 50) || (caster_ptr->align < -50))
175 if (caster_ptr->align < -20)
181 if (caster_ptr->align > 20)
186 if (chance < minfail)
189 if (caster_ptr->stun > 50)
191 else if (caster_ptr->stun)
197 if ((use_realm == caster_ptr->realm1) || (use_realm == caster_ptr->realm2) || (caster_ptr->pclass == CLASS_SORCERER)
198 || (caster_ptr->pclass == CLASS_RED_MAGE)) {
199 EXP exp = experience_of_spell(caster_ptr, spell, use_realm);
200 if (exp >= SPELL_EXP_EXPERT)
202 if (exp >= SPELL_EXP_MASTER)
206 return mod_spell_chance_2(caster_ptr, chance);
211 * Print a list of spells (for browsing or casting or viewing)
212 * @param caster_ptr 術者の参照ポインタ
213 * @param target_spell 呪文ID
214 * @param spells 表示するスペルID配列の参照ポインタ
215 * @param num 表示するスペルの数(spellsの要素数)
216 * @param y 表示メッセージ左上Y座標
217 * @param x 表示メッセージ左上X座標
218 * @param use_realm 魔法領域ID
221 void print_spells(player_type *caster_ptr, SPELL_IDX target_spell, SPELL_IDX *spells, int num, TERM_LEN y, TERM_LEN x, REALM_IDX use_realm)
223 if (((use_realm <= REALM_NONE) || (use_realm > MAX_REALM)) && current_world_ptr->wizard)
224 msg_print(_("警告! print_spell が領域なしに呼ばれた", "Warning! print_spells called with null realm"));
228 if (use_realm == REALM_HISSATSU)
229 strcpy(buf, _(" Lv MP", " Lv SP"));
231 strcpy(buf, _("熟練度 Lv MP 失率 効果", "Profic Lv SP Fail Effect"));
233 put_str(_("名前", "Name"), y, x + 5);
234 put_str(buf, y, x + 29);
237 if ((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE))
239 else if (use_realm == caster_ptr->realm1)
241 else if (use_realm == caster_ptr->realm2)
246 const magic_type *s_ptr;
251 for (i = 0; i < num; i++) {
252 SPELL_IDX spell = spells[i];
254 if (!is_magic(use_realm)) {
255 s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
257 s_ptr = &mp_ptr->info[use_realm - 1][spell];
260 MANA_POINT need_mana;
261 if (use_realm == REALM_HISSATSU)
262 need_mana = s_ptr->smana;
264 EXP exp = experience_of_spell(caster_ptr, spell, use_realm);
265 need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, use_realm);
266 if ((increment == 64) || (s_ptr->slevel >= 99))
267 exp_level = EXP_LEVEL_UNSKILLED;
269 exp_level = spell_exp_level(exp);
272 if (!increment && (exp_level == EXP_LEVEL_MASTER))
274 else if ((increment == 32) && (exp_level >= EXP_LEVEL_EXPERT))
276 else if (s_ptr->slevel >= 99)
278 else if ((caster_ptr->pclass == CLASS_RED_MAGE) && (exp_level >= EXP_LEVEL_SKILLED))
281 strncpy(ryakuji, exp_level_str[exp_level], 4);
286 if (use_menu && target_spell) {
287 if (i == (target_spell - 1))
288 strcpy(out_val, _(" 》 ", " > "));
290 strcpy(out_val, " ");
292 sprintf(out_val, " %c) ", I2A(i));
294 if (s_ptr->slevel >= 99) {
295 strcat(out_val, format("%-30s", _("(判読不能)", "(illegible)")));
296 c_prt(TERM_L_DARK, out_val, y + i + 1, x);
300 strcpy(info, exe_spell(caster_ptr, use_realm, spell, SPELL_INFO));
301 concptr comment = info;
302 byte line_attr = TERM_WHITE;
303 if ((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE)) {
304 if (s_ptr->slevel > caster_ptr->max_plv) {
305 comment = _("未知", "unknown");
306 line_attr = TERM_L_BLUE;
307 } else if (s_ptr->slevel > caster_ptr->lev) {
308 comment = _("忘却", "forgotten");
309 line_attr = TERM_YELLOW;
311 } else if ((use_realm != caster_ptr->realm1) && (use_realm != caster_ptr->realm2)) {
312 comment = _("未知", "unknown");
313 line_attr = TERM_L_BLUE;
314 } else if ((use_realm == caster_ptr->realm1) ? ((caster_ptr->spell_forgotten1 & (1L << spell))) : ((caster_ptr->spell_forgotten2 & (1L << spell)))) {
315 comment = _("忘却", "forgotten");
316 line_attr = TERM_YELLOW;
317 } else if (!((use_realm == caster_ptr->realm1) ? (caster_ptr->spell_learned1 & (1L << spell)) : (caster_ptr->spell_learned2 & (1L << spell)))) {
318 comment = _("未知", "unknown");
319 line_attr = TERM_L_BLUE;
320 } else if (!((use_realm == caster_ptr->realm1) ? (caster_ptr->spell_worked1 & (1L << spell)) : (caster_ptr->spell_worked2 & (1L << spell)))) {
321 comment = _("未経験", "untried");
322 line_attr = TERM_L_GREEN;
325 if (use_realm == REALM_HISSATSU) {
326 strcat(out_val, format("%-25s %2d %4d", exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), s_ptr->slevel, need_mana));
329 format("%-25s%c%-4s %2d %4d %3d%% %s", exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), (max ? '!' : ' '), ryakuji, s_ptr->slevel,
330 need_mana, spell_chance(caster_ptr, spell, use_realm), comment));
333 c_prt(line_attr, out_val, y + i + 1, x);
336 prt("", y + i + 1, x);