OSDN Git Service

f1b29a5f6e34c7f8937cbdc06a10bf901d763c61
[hengband/hengband.git] / src / core / hp-mp-regenerator.c
1 #include "system/angband.h"
2 #include "core/hp-mp-regenerator.h"
3 #include "cmd-item/cmd-magiceat.h"
4 #include "floor/floor.h"
5 #include "monster-race/race-flags2.h"
6 #include "monster/monster-status.h"
7
8 /*!<広域マップ移動時の自然回復処理カウンタ(広域マップ1マス毎に20回処理を基本とする)*/
9 int wild_regen = 20;
10
11 /*!
12  * @brief プレイヤーのHP自然回復処理 / Regenerate hit points -RAK-
13  * @param percent 回復比率
14  * @return なし
15  */
16 void regenhp(player_type* creature_ptr, int percent)
17 {
18     if (creature_ptr->special_defense & KATA_KOUKIJIN)
19         return;
20     if (creature_ptr->action == ACTION_HAYAGAKE)
21         return;
22
23     HIT_POINT old_chp = creature_ptr->chp;
24
25     /*
26          * Extract the new hitpoints
27          *
28          * 'percent' is the Regen factor in unit (1/2^16)
29          */
30     HIT_POINT new_chp = 0;
31     u32b new_chp_frac = (creature_ptr->mhp * percent + PY_REGEN_HPBASE);
32     s64b_LSHIFT(new_chp, new_chp_frac, 16);
33     s64b_add(&(creature_ptr->chp), &(creature_ptr->chp_frac), new_chp, new_chp_frac);
34     if (0 < s64b_cmp(creature_ptr->chp, creature_ptr->chp_frac, creature_ptr->mhp, 0)) {
35         creature_ptr->chp = creature_ptr->mhp;
36         creature_ptr->chp_frac = 0;
37     }
38
39     if (old_chp != creature_ptr->chp) {
40         creature_ptr->redraw |= (PR_HP);
41         creature_ptr->window |= (PW_PLAYER);
42         wild_regen = 20;
43     }
44 }
45
46 /*!
47  * @brief プレイヤーのMP自然回復処理(regen_magic()のサブセット) / Regenerate mana points
48  * @param upkeep_factor ペット維持によるMPコスト量
49  * @param regen_amount 回復量
50  * @return なし
51  */
52 void regenmana(player_type* creature_ptr, MANA_POINT upkeep_factor, MANA_POINT regen_amount)
53 {
54     MANA_POINT old_csp = creature_ptr->csp;
55     s32b regen_rate = regen_amount * 100 - upkeep_factor * PY_REGEN_NORMAL;
56
57     /*
58          * Excess mana will decay 32 times faster than normal
59          * regeneration rate.
60          */
61     if (creature_ptr->csp > creature_ptr->msp) {
62         s32b decay = 0;
63         u32b decay_frac = (creature_ptr->msp * 32 * PY_REGEN_NORMAL + PY_REGEN_MNBASE);
64         s64b_LSHIFT(decay, decay_frac, 16);
65         s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), decay, decay_frac);
66         if (creature_ptr->csp < creature_ptr->msp) {
67             creature_ptr->csp = creature_ptr->msp;
68             creature_ptr->csp_frac = 0;
69         }
70     }
71
72     /* Regenerating mana (unless the player has excess mana) */
73     else if (regen_rate > 0) {
74         MANA_POINT new_mana = 0;
75         u32b new_mana_frac = (creature_ptr->msp * regen_rate / 100 + PY_REGEN_MNBASE);
76         s64b_LSHIFT(new_mana, new_mana_frac, 16);
77         s64b_add(&(creature_ptr->csp), &(creature_ptr->csp_frac), new_mana, new_mana_frac);
78         if (creature_ptr->csp >= creature_ptr->msp) {
79             creature_ptr->csp = creature_ptr->msp;
80             creature_ptr->csp_frac = 0;
81         }
82     }
83
84     /* Reduce mana (even when the player has excess mana) */
85     if (regen_rate < 0) {
86         s32b reduce_mana = 0;
87         u32b reduce_mana_frac = (creature_ptr->msp * (-1) * regen_rate / 100 + PY_REGEN_MNBASE);
88         s64b_LSHIFT(reduce_mana, reduce_mana_frac, 16);
89         s64b_sub(&(creature_ptr->csp), &(creature_ptr->csp_frac), reduce_mana, reduce_mana_frac);
90         if (creature_ptr->csp < 0) {
91             creature_ptr->csp = 0;
92             creature_ptr->csp_frac = 0;
93         }
94     }
95
96     if (old_csp != creature_ptr->csp) {
97         creature_ptr->redraw |= (PR_MANA);
98         creature_ptr->window |= (PW_PLAYER);
99         creature_ptr->window |= (PW_SPELL);
100         wild_regen = 20;
101     }
102 }
103
104 /*!
105  * @brief プレイヤーのMP自然回復処理 / Regenerate magic regen_amount: PY_REGEN_NORMAL * 2 (if resting) * 2 (if having regenarate)
106  * @param regen_amount 回復量
107  * @return なし
108  */
109 void regenmagic(player_type* creature_ptr, int regen_amount)
110 {
111     MANA_POINT new_mana;
112     int dev = 30;
113     int mult = (dev + adj_mag_mana[creature_ptr->stat_ind[A_INT]]); /* x1 to x2 speed bonus for recharging */
114
115     for (int i = 0; i < EATER_EXT * 2; i++) {
116         if (!creature_ptr->magic_num2[i])
117             continue;
118         if (creature_ptr->magic_num1[i] == ((long)creature_ptr->magic_num2[i] << 16))
119             continue;
120
121         /* Increase remaining charge number like float value */
122         new_mana = (regen_amount * mult * ((long)creature_ptr->magic_num2[i] + 13)) / (dev * 8);
123         creature_ptr->magic_num1[i] += new_mana;
124
125         /* Check maximum charge */
126         if (creature_ptr->magic_num1[i] > (creature_ptr->magic_num2[i] << 16)) {
127             creature_ptr->magic_num1[i] = ((long)creature_ptr->magic_num2[i] << 16);
128         }
129
130         wild_regen = 20;
131     }
132
133     for (int i = EATER_EXT * 2; i < EATER_EXT * 3; i++) {
134         if (!creature_ptr->magic_num1[i])
135             continue;
136         if (!creature_ptr->magic_num2[i])
137             continue;
138
139         /* Decrease remaining period for charging */
140         new_mana = (regen_amount * mult * ((long)creature_ptr->magic_num2[i] + 10) * EATER_ROD_CHARGE)
141             / (dev * 16 * PY_REGEN_NORMAL);
142         creature_ptr->magic_num1[i] -= new_mana;
143
144         /* Check minimum remaining period for charging */
145         if (creature_ptr->magic_num1[i] < 0)
146             creature_ptr->magic_num1[i] = 0;
147         wild_regen = 20;
148     }
149 }
150
151 /*!
152  * @brief 100ゲームターン毎のモンスターのHP自然回復処理 / Regenerate the monsters (once per 100 game turns)
153  * @param player_ptr プレーヤーへの参照ポインタ
154  * @return なし
155  * @note Should probably be done during monster turns.
156  */
157 void regenerate_monsters(player_type* player_ptr)
158 {
159     for (int i = 1; i < player_ptr->current_floor_ptr->m_max; i++) {
160         monster_type* m_ptr = &player_ptr->current_floor_ptr->m_list[i];
161         monster_race* r_ptr = &r_info[m_ptr->r_idx];
162
163         if (!monster_is_valid(m_ptr))
164             continue;
165
166         if (m_ptr->hp < m_ptr->maxhp) {
167             int frac = m_ptr->maxhp / 100;
168             if (!frac)
169                 if (one_in_(2))
170                     frac = 1;
171
172             if (r_ptr->flags2 & RF2_REGENERATE)
173                 frac *= 2;
174
175             m_ptr->hp += frac;
176             if (m_ptr->hp > m_ptr->maxhp)
177                 m_ptr->hp = m_ptr->maxhp;
178
179             if (player_ptr->health_who == i)
180                 player_ptr->redraw |= (PR_HEALTH);
181             if (player_ptr->riding == i)
182                 player_ptr->redraw |= (PR_UHEALTH);
183         }
184     }
185 }
186
187 /*!
188  * @brief 30ゲームターン毎のボール中モンスターのHP自然回復処理 / Regenerate the captured monsters (once per 30 game turns)
189  * @param creature_ptr プレーヤーへの参照ポインタ
190  * @return なし
191  * @note Should probably be done during monster turns.
192  */
193 void regenerate_captured_monsters(player_type* creature_ptr)
194 {
195     bool heal = FALSE;
196     for (int i = 0; i < INVEN_TOTAL; i++) {
197         monster_race* r_ptr;
198         object_type* o_ptr = &creature_ptr->inventory_list[i];
199         if (!o_ptr->k_idx)
200             continue;
201         if (o_ptr->tval != TV_CAPTURE)
202             continue;
203         if (!o_ptr->pval)
204             continue;
205
206         heal = TRUE;
207         r_ptr = &r_info[o_ptr->pval];
208         if (o_ptr->xtra4 < o_ptr->xtra5) {
209             int frac = o_ptr->xtra5 / 100;
210             if (!frac)
211                 if (one_in_(2))
212                     frac = 1;
213
214             if (r_ptr->flags2 & RF2_REGENERATE)
215                 frac *= 2;
216
217             o_ptr->xtra4 += (XTRA16)frac;
218             if (o_ptr->xtra4 > o_ptr->xtra5)
219                 o_ptr->xtra4 = o_ptr->xtra5;
220         }
221     }
222
223     if (heal) {
224         creature_ptr->update |= (PU_COMBINE);
225         creature_ptr->window |= (PW_INVEN);
226         creature_ptr->window |= (PW_EQUIP);
227         wild_regen = 20;
228     }
229 }