OSDN Git Service

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