OSDN Git Service

Merge pull request #2122 from sikabane-works/release/3.0.0Alpha52
[hengbandforosx/hengbandosx.git] / src / mspell / mspell-damage-calculator.cpp
1 #include "mspell/mspell-damage-calculator.h"
2 #include "game-option/birth-options.h"
3 #include "inventory/inventory-slot-types.h"
4 #include "monster-race/monster-race.h"
5 #include "monster-race/race-ability-flags.h"
6 #include "monster-race/race-flags2.h"
7 #include "monster/monster-status.h"
8 #include "player-info/equipment-info.h"
9 #include "system/floor-type-definition.h"
10 #include "system/monster-race-definition.h"
11 #include "system/monster-type-definition.h"
12 #include "system/object-type-definition.h"
13 #include "system/player-type-definition.h"
14 #include "util/bit-flags-calculator.h"
15
16 /*!
17  * @brief モンスターの使う呪文の威力を決定する /
18  * @param dam 定数値
19  * @param dice_num ダイス数
20  * @param dice_side ダイス面
21  * @param mult ダイス倍率
22  * @param div ダイス倍率
23  * @param TYPE  DAM_MAXで最大値を返し、DAM_MINで最小値を返す。DAM_ROLLはダイスを振って値を決定する。
24  * @return 攻撃呪文のダメージを返す。攻撃呪文以外は-1を返す。
25  */
26 static HIT_POINT monspell_damage_roll(HIT_POINT dam, int dice_num, int dice_side, int mult, int div, int TYPE)
27 {
28     switch (TYPE) {
29     case DAM_MAX:
30         dam += maxroll(dice_num, dice_side) * mult / div;
31         break;
32     case DAM_MIN:
33         dam += dice_num * 1 * mult / div;
34         break;
35     case DAM_ROLL:
36         dam += damroll(dice_num, dice_side) * mult / div;
37         break;
38     case DICE_NUM:
39         return dice_num;
40     case DICE_SIDE:
41         return dice_side;
42     case DICE_MULT:
43         return mult;
44     case DICE_DIV:
45         return div;
46     case BASE_DAM:
47         return dam;
48     }
49
50     if (dam < 1)
51         dam = 1;
52     return dam;
53 }
54
55 /*!
56  * @brief モンスターの使う呪文の威力を返す /
57  * @param player_ptr プレイヤーへの参照ポインタ (破滅の手用)
58  * @param SPELL_NUM 呪文番号
59  * @param hp 呪文を唱えるモンスターの体力
60  * @param rlev 呪文を唱えるモンスターのレベル
61  * @param powerful 呪文を唱えるモンスターのpowerfulフラグ
62  * @param shoot_dd 射撃のダイス数
63  * @param shoot_ds 射撃のダイス面
64  * @param shoot_base 射撃の固定威力値
65  * @param TYPE  DAM_MAXで最大値を返し、DAM_MINで最小値を返す。DAM_ROLLはダイスを振って値を決定する。
66  * @return 攻撃呪文のダメージを返す。攻撃呪文以外は-1を返す。
67  */
68 static HIT_POINT monspell_damage_base(
69     PlayerType *player_ptr, MonsterAbilityType ms_type, int hp, int rlev, bool powerful, int shoot_dd, int shoot_ds, int shoot_base, int TYPE)
70 {
71     HIT_POINT dam = 0, dice_num = 0, dice_side = 0, mult = 1, div = 1;
72
73     switch (ms_type) {
74     case MonsterAbilityType::SHRIEK:
75         return -1;
76     case MonsterAbilityType::XXX1:
77         return -1;
78     case MonsterAbilityType::DISPEL:
79         return -1;
80     case MonsterAbilityType::ROCKET:
81         dam = (hp / 4) > 800 ? 800 : (hp / 4);
82         break;
83     case MonsterAbilityType::SHOOT:
84         dice_num = shoot_dd;
85         dice_side = shoot_ds;
86         dam = shoot_base;
87         break;
88     case MonsterAbilityType::XXX2:
89         return -1;
90     case MonsterAbilityType::XXX3:
91         return -1;
92     case MonsterAbilityType::XXX4:
93         return -1;
94
95     case MonsterAbilityType::BR_ACID:
96     case MonsterAbilityType::BR_ELEC:
97     case MonsterAbilityType::BR_FIRE:
98     case MonsterAbilityType::BR_COLD:
99         dam = ((hp / 3) > 1600 ? 1600 : (hp / 3));
100         break;
101     case MonsterAbilityType::BR_POIS:
102         dam = ((hp / 3) > 800 ? 800 : (hp / 3));
103         break;
104     case MonsterAbilityType::BR_NETH:
105         dam = ((hp / 6) > 550 ? 550 : (hp / 6));
106         break;
107     case MonsterAbilityType::BR_LITE:
108     case MonsterAbilityType::BR_DARK:
109         dam = ((hp / 6) > 400 ? 400 : (hp / 6));
110         break;
111     case MonsterAbilityType::BR_CONF:
112     case MonsterAbilityType::BR_SOUN:
113         dam = ((hp / 6) > 450 ? 450 : (hp / 6));
114         break;
115     case MonsterAbilityType::BR_CHAO:
116         dam = ((hp / 6) > 600 ? 600 : (hp / 6));
117         break;
118     case MonsterAbilityType::BR_DISE:
119         dam = ((hp / 6) > 500 ? 500 : (hp / 6));
120         break;
121     case MonsterAbilityType::BR_NEXU:
122         dam = ((hp / 3) > 250 ? 250 : (hp / 3));
123         break;
124     case MonsterAbilityType::BR_TIME:
125         dam = ((hp / 3) > 150 ? 150 : (hp / 3));
126         break;
127     case MonsterAbilityType::BR_INER:
128     case MonsterAbilityType::BR_GRAV:
129         dam = ((hp / 6) > 200 ? 200 : (hp / 6));
130         break;
131     case MonsterAbilityType::BR_SHAR:
132         dam = ((hp / 6) > 500 ? 500 : (hp / 6));
133         break;
134     case MonsterAbilityType::BR_PLAS:
135         dam = ((hp / 6) > 150 ? 150 : (hp / 6));
136         break;
137     case MonsterAbilityType::BR_FORC:
138         dam = ((hp / 6) > 200 ? 200 : (hp / 6));
139         break;
140     case MonsterAbilityType::BR_MANA:
141         dam = ((hp / 3) > 250 ? 250 : (hp / 3));
142         break;
143     case MonsterAbilityType::BA_NUKE:
144         mult = powerful ? 2 : 1;
145         dam = rlev * (mult / div);
146         dice_num = 10;
147         dice_side = 6;
148         break;
149     case MonsterAbilityType::BR_NUKE:
150         dam = ((hp / 3) > 800 ? 800 : (hp / 3));
151         break;
152     case MonsterAbilityType::BA_CHAO:
153         dam = (powerful ? (rlev * 3) : (rlev * 2));
154         dice_num = 10;
155         dice_side = 10;
156         break;
157     case MonsterAbilityType::BR_DISI:
158         dam = ((hp / 6) > 150 ? 150 : (hp / 6));
159         break;
160     case MonsterAbilityType::BR_VOID:
161         dam = ((hp / 3) > 250 ? 250 : (hp / 6));
162         break;
163     case MonsterAbilityType::BR_ABYSS:
164         dam = ((hp / 3) > 250 ? 250 : (hp / 6));
165         break;
166     case MonsterAbilityType::BA_ACID:
167         if (powerful) {
168             dam = (rlev * 4) + 50;
169             dice_num = 10;
170             dice_side = 10;
171         } else {
172             dam = 15;
173             dice_num = 1;
174             dice_side = rlev * 3;
175         }
176
177         break;
178     case MonsterAbilityType::BA_ELEC:
179         if (powerful) {
180             dam = (rlev * 4) + 50;
181             dice_num = 10;
182             dice_side = 10;
183         } else {
184             dam = 8;
185             dice_num = 1;
186             dice_side = rlev * 3 / 2;
187         }
188
189         break;
190     case MonsterAbilityType::BA_FIRE:
191         if (powerful) {
192             dam = (rlev * 4) + 50;
193             dice_num = 10;
194             dice_side = 10;
195         } else {
196             dam = 10;
197             dice_num = 1;
198             dice_side = rlev * 7 / 2;
199         }
200
201         break;
202     case MonsterAbilityType::BA_COLD:
203         if (powerful) {
204             dam = (rlev * 4) + 50;
205             dice_num = 10;
206             dice_side = 10;
207         } else {
208             dam = 10;
209             dice_num = 1;
210             dice_side = rlev * 3 / 2;
211         }
212
213         break;
214     case MonsterAbilityType::BA_POIS:
215         mult = powerful ? 2 : 1;
216         dice_num = 12;
217         dice_side = 2;
218         break;
219     case MonsterAbilityType::BA_NETH:
220         dam = 50 + rlev * (powerful ? 2 : 1);
221         dice_num = 10;
222         dice_side = 10;
223         break;
224     case MonsterAbilityType::BA_WATE:
225         dam = 50;
226         dice_num = 1;
227         dice_side = powerful ? (rlev * 3) : (rlev * 2);
228         break;
229     case MonsterAbilityType::BA_MANA:
230     case MonsterAbilityType::BA_DARK:
231         dam = (rlev * 4) + 50;
232         dice_num = 10;
233         dice_side = 10;
234         break;
235     case MonsterAbilityType::BA_VOID:
236         dam = (powerful ? (rlev * 3) : (rlev * 2));
237         dice_num = 10;
238         dice_side = 10;
239         break;
240     case MonsterAbilityType::BA_ABYSS:
241         dam = (powerful ? (rlev * 3) : (rlev * 2));
242         dice_num = 10;
243         dice_side = 10;
244         break;
245     case MonsterAbilityType::DRAIN_MANA:
246         dam = rlev;
247         div = 1;
248         dice_num = 1;
249         dice_side = rlev;
250         break;
251     case MonsterAbilityType::MIND_BLAST:
252         dice_num = 7;
253         dice_side = 7;
254         break;
255     case MonsterAbilityType::BRAIN_SMASH:
256         dice_num = 12;
257         dice_side = 12;
258         break;
259     case MonsterAbilityType::CAUSE_1:
260         dice_num = 3;
261         dice_side = 8;
262         break;
263     case MonsterAbilityType::CAUSE_2:
264         dice_num = 8;
265         dice_side = 8;
266         break;
267     case MonsterAbilityType::CAUSE_3:
268         dice_num = 10;
269         dice_side = 15;
270         break;
271     case MonsterAbilityType::CAUSE_4:
272         dice_num = 15;
273         dice_side = 15;
274         break;
275     case MonsterAbilityType::BO_ACID:
276         mult = powerful ? 2 : 1;
277         dam = rlev / 3 * (mult / div);
278         dice_num = 7;
279         dice_side = 8;
280         break;
281     case MonsterAbilityType::BO_ELEC:
282         mult = powerful ? 2 : 1;
283         dam = rlev / 3 * (mult / div);
284         dice_num = 4;
285         dice_side = 8;
286         break;
287     case MonsterAbilityType::BO_FIRE:
288         mult = powerful ? 2 : 1;
289         dam = rlev / 3 * (mult / div);
290         dice_num = 9;
291         dice_side = 8;
292         break;
293     case MonsterAbilityType::BO_COLD:
294         mult = powerful ? 2 : 1;
295         dam = rlev / 3 * (mult / div);
296         dice_num = 6;
297         dice_side = 8;
298         break;
299     case MonsterAbilityType::BA_LITE:
300         dam = (rlev * 4) + 50;
301         dice_num = 10;
302         dice_side = 10;
303         break;
304     case MonsterAbilityType::BO_NETH:
305         dam = 30 + (rlev * 4) / (powerful ? 2 : 3);
306         dice_num = 5;
307         dice_side = 5;
308         break;
309     case MonsterAbilityType::BO_WATE:
310         dam = (rlev * 3 / (powerful ? 2 : 3));
311         dice_num = 10;
312         dice_side = 10;
313         break;
314     case MonsterAbilityType::BO_MANA:
315         dam = 50;
316         dice_num = 1;
317         dice_side = rlev * 7 / 2;
318         break;
319     case MonsterAbilityType::BO_PLAS:
320         dam = 10 + (rlev * 3 / (powerful ? 2 : 3));
321         dice_num = 8;
322         dice_side = 7;
323         break;
324     case MonsterAbilityType::BO_ICEE:
325         dam = (rlev * 3 / (powerful ? 2 : 3));
326         dice_num = 6;
327         dice_side = 6;
328         break;
329     case MonsterAbilityType::BO_VOID:
330         dam = 10 + (rlev * 3 / (powerful ? 2 : 3));
331         dice_num = 13;
332         dice_side = 14;
333         break;
334     case MonsterAbilityType::BO_ABYSS:
335         dam = 10 + (rlev * 3 / (powerful ? 2 : 3));
336         dice_num = 13;
337         dice_side = 14;
338         break;
339     case MonsterAbilityType::MISSILE:
340         dam = (rlev / 3);
341         dice_num = 2;
342         dice_side = 6;
343         break;
344     case MonsterAbilityType::SCARE:
345         return -1;
346     case MonsterAbilityType::BLIND:
347         return -1;
348     case MonsterAbilityType::CONF:
349         return -1;
350     case MonsterAbilityType::SLOW:
351         return -1;
352     case MonsterAbilityType::HOLD:
353         return -1;
354     case MonsterAbilityType::HASTE:
355         return -1;
356
357     case MonsterAbilityType::HAND_DOOM:
358         mult = player_ptr->chp;
359         div = 100;
360         dam = 40 * (mult / div);
361         dice_num = 1;
362         dice_side = 20;
363         break;
364
365     case MonsterAbilityType::HEAL:
366         return -1;
367     case MonsterAbilityType::INVULNER:
368         return -1;
369     case MonsterAbilityType::BLINK:
370         return -1;
371     case MonsterAbilityType::TPORT:
372         return -1;
373     case MonsterAbilityType::WORLD:
374         return -1;
375     case MonsterAbilityType::SPECIAL:
376         return -1;
377     case MonsterAbilityType::TELE_TO:
378         return -1;
379     case MonsterAbilityType::TELE_AWAY:
380         return -1;
381     case MonsterAbilityType::TELE_LEVEL:
382         return -1;
383
384     case MonsterAbilityType::PSY_SPEAR:
385         dam = powerful ? 150 : 100;
386         dice_num = 1;
387         dice_side = powerful ? (rlev * 2) : (rlev * 3 / 2);
388         break;
389
390     case MonsterAbilityType::DARKNESS:
391         return -1;
392     case MonsterAbilityType::TRAPS:
393         return -1;
394     case MonsterAbilityType::FORGET:
395         return -1;
396     case MonsterAbilityType::RAISE_DEAD:
397         return -1;
398     case MonsterAbilityType::S_KIN:
399         return -1;
400     case MonsterAbilityType::S_CYBER:
401         return -1;
402     case MonsterAbilityType::S_MONSTER:
403         return -1;
404     case MonsterAbilityType::S_MONSTERS:
405         return -1;
406     case MonsterAbilityType::S_ANT:
407         return -1;
408     case MonsterAbilityType::S_SPIDER:
409         return -1;
410     case MonsterAbilityType::S_HOUND:
411         return -1;
412     case MonsterAbilityType::S_HYDRA:
413         return -1;
414     case MonsterAbilityType::S_ANGEL:
415         return -1;
416     case MonsterAbilityType::S_DEMON:
417         return -1;
418     case MonsterAbilityType::S_UNDEAD:
419         return -1;
420     case MonsterAbilityType::S_DRAGON:
421         return -1;
422     case MonsterAbilityType::S_HI_UNDEAD:
423         return -1;
424     case MonsterAbilityType::S_HI_DRAGON:
425         return -1;
426     case MonsterAbilityType::S_AMBERITES:
427         return -1;
428     case MonsterAbilityType::S_UNIQUE:
429         return -1;
430     case MonsterAbilityType::MAX:
431         return -1;
432     }
433
434     return monspell_damage_roll(dam, dice_num, dice_side, mult, div, TYPE);
435 }
436
437 /*!
438  * @brief モンスターの使う射撃のダイス情報を返す /
439  * @param r_ptr モンスター種族への参照ポインタ
440  * @param dd ダイス数への参照ポインタ
441  * @param ds ダイス面への参照ポインタ
442  */
443 void monspell_shoot_dice(monster_race *r_ptr, int *dd, int *ds)
444 {
445     int p = -1; /* Position of SHOOT */
446     int n = 0; /* Number of blows */
447     const int max_blows = 4;
448     for (int m = 0; m < max_blows; m++) {
449         if (r_ptr->blow[m].method != RaceBlowMethodType::NONE)
450             n++; /* Count blows */
451
452         if (r_ptr->blow[m].method == RaceBlowMethodType::SHOOT) {
453             p = m; /* Remember position */
454             break;
455         }
456     }
457
458     /* When full blows, use a first damage */
459     if (n == max_blows)
460         p = 0;
461
462     if (p < 0) {
463         (*dd) = 0;
464         (*ds) = 0;
465     } else {
466         (*dd) = r_ptr->blow[p].d_dice;
467         (*ds) = r_ptr->blow[p].d_side;
468     }
469 }
470
471 /*!
472  * @brief モンスターの使う呪文の威力を返す /
473  * @param player_ptr プレイヤーへの参照ポインタ
474  * @param ms_type 呪文番号
475  * @param m_idx 呪文を唱えるモンスターID
476  * @param TYPE  DAM_MAXで最大値を返し、DAM_MINで最小値を返す。DAM_ROLLはダイスを振って値を決定する。
477  * @return 攻撃呪文のダメージを返す。攻撃呪文以外は-1を返す。
478  */
479 HIT_POINT monspell_damage(PlayerType *player_ptr, MonsterAbilityType ms_type, MONSTER_IDX m_idx, int TYPE)
480 {
481     floor_type *floor_ptr = player_ptr->current_floor_ptr;
482     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
483     monster_race *r_ptr = &r_info[m_ptr->r_idx];
484     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
485     HIT_POINT hp = (TYPE == DAM_ROLL) ? m_ptr->hp : m_ptr->max_maxhp;
486     int shoot_dd, shoot_ds;
487
488     monspell_shoot_dice(r_ptr, &shoot_dd, &shoot_ds);
489     return monspell_damage_base(player_ptr, ms_type, hp, rlev, monster_is_powerful(floor_ptr, m_idx), shoot_dd, shoot_ds, 0, TYPE);
490 }
491
492 /*!
493  * @brief モンスターの使う所属としての呪文の威力を返す /
494  * @param player_ptr プレイヤーへの参照ポインタ
495  * @param ms_type 呪文番号
496  * @param r_idx 呪文を唱えるモンスターの種族ID
497  * @param TYPE  DAM_MAXで最大値を返し、DAM_MINで最小値を返す。DAM_ROLLはダイスを振って値を決定する。
498  * @return 攻撃呪文のダメージを返す。攻撃呪文以外は-1を返す。
499  */
500 HIT_POINT monspell_race_damage(PlayerType *player_ptr, MonsterAbilityType ms_type, MONRACE_IDX r_idx, int TYPE)
501 {
502     monster_race *r_ptr = &r_info[r_idx];
503     DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
504     bool powerful = any_bits(r_ptr->flags2, RF2_POWERFUL);
505     HIT_POINT hp = r_ptr->hdice * (ironman_nightmare ? 2 : 1) * r_ptr->hside;
506     int shoot_dd, shoot_ds;
507
508     monspell_shoot_dice(r_ptr, &shoot_dd, &shoot_ds);
509     return monspell_damage_base(player_ptr, ms_type, std::min(MONSTER_MAXHP, hp), rlev, powerful, shoot_dd, shoot_ds, 0, TYPE);
510 }
511
512 /*!
513  * @brief 青魔導師の使う呪文の威力を返す /
514  * @param player_ptr プレイヤーへの参照ポインタ
515  * @param SPELL_NUM 呪文番号
516  * @param plev 使用するレベル。2倍して扱う。
517  * @param TYPE  DAM_MAXで最大値を返し、DAM_MINで最小値を返す。DAM_ROLLはダイスを振って値を決定する。
518  * @return 攻撃呪文のダメージを返す。攻撃呪文以外は-1を返す。
519  */
520 HIT_POINT monspell_bluemage_damage(PlayerType *player_ptr, MonsterAbilityType ms_type, PLAYER_LEVEL plev, int TYPE)
521 {
522     int hp = player_ptr->chp;
523     int shoot_dd = 1, shoot_ds = 1, shoot_base = 0;
524     object_type *o_ptr = nullptr;
525
526     if (has_melee_weapon(player_ptr, INVEN_MAIN_HAND))
527         o_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND];
528     else if (has_melee_weapon(player_ptr, INVEN_SUB_HAND))
529         o_ptr = &player_ptr->inventory_list[INVEN_SUB_HAND];
530
531     if (o_ptr) {
532         shoot_dd = o_ptr->dd;
533         shoot_ds = o_ptr->ds;
534         shoot_base = o_ptr->to_d;
535     }
536
537     return monspell_damage_base(player_ptr, ms_type, hp, plev * 2, false, shoot_dd, shoot_ds, shoot_base, TYPE);
538 }