OSDN Git Service

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