OSDN Git Service

[Fix] 投げたオブジェクトの軌跡が残る
[hengband/hengband.git] / src / status / base-status.c
1 #include "status/base-status.h"
2 #include "core/player-redraw-types.h"
3 #include "core/player-update-types.h"
4 #include "core/window-redrawer.h"
5 #include "game-option/birth-options.h"
6 #include "inventory/inventory-slot-types.h"
7 #include "object-enchant/item-feeling.h"
8 #include "object-enchant/special-object-flags.h"
9 #include "perception/object-perception.h"
10 #include "player/player-status-flags.h"
11 #include "player-info/avatar.h"
12 #include "spell-kind/spells-floor.h"
13 #include "system/object-type-definition.h"
14 #include "view/display-messages.h"
15
16 /* Array of stat "descriptions" */
17 static concptr desc_stat_pos[]
18     = { _("強く", "stronger"), _("知的に", "smarter"), _("賢く", "wiser"), _("器用に", "more dextrous"), _("健康に", "healthier"), _("美しく", "cuter") };
19
20 /* Array of stat "descriptions" */
21 static concptr desc_stat_neg[]
22     = { _("弱く", "weaker"), _("無知に", "stupider"), _("愚かに", "more naive"), _("不器用に", "clumsier"), _("不健康に", "more sickly"), _("醜く", "uglier") };
23
24 /*!
25  * @brief プレイヤーの基本能力値を増加させる / Increases a stat by one randomized level -RAK-
26  * @param stat 上昇させるステータスID
27  * @return 実際に上昇した場合TRUEを返す。
28  * @details
29  * Note that this function (used by stat potions) now restores\n
30  * the stat BEFORE increasing it.\n
31  */
32 bool inc_stat(player_type *creature_ptr, int stat)
33 {
34     BASE_STATUS gain;
35     BASE_STATUS value = creature_ptr->stat_cur[stat];
36     if (value >= creature_ptr->stat_max_max[stat])
37         return FALSE;
38
39     if (value < 18) {
40         gain = ((randint0(100) < 75) ? 1 : 2);
41         value += gain;
42     } else if (value < (creature_ptr->stat_max_max[stat] - 2)) {
43         gain = (((creature_ptr->stat_max_max[stat]) - value) / 2 + 3) / 2;
44         if (gain < 1)
45             gain = 1;
46
47         value += randint1(gain) + gain / 2;
48         if (value > (creature_ptr->stat_max_max[stat] - 1))
49             value = creature_ptr->stat_max_max[stat] - 1;
50     } else {
51         value++;
52     }
53
54     creature_ptr->stat_cur[stat] = value;
55     if (value > creature_ptr->stat_max[stat]) {
56         creature_ptr->stat_max[stat] = value;
57     }
58
59     creature_ptr->update |= PU_BONUS;
60     return TRUE;
61 }
62
63 /*!
64  * @brief プレイヤーの基本能力値を減少させる / Decreases a stat by an amount indended to vary from 0 to 100 percent.
65  * @param stat 減少させるステータスID
66  * @param amount 減少させる基本量
67  * @param permanent TRUEならば現在の最大値を減少させる
68  * @return 実際に減少した場合TRUEを返す。
69  * @details
70  *\n
71  * Amount could be a little higher in extreme cases to mangle very high\n
72  * stats from massive assaults.  -CWS\n
73  *\n
74  * Note that "permanent" means that the *given* amount is permanent,\n
75  * not that the new value becomes permanent.  This may not work exactly\n
76  * as expected, due to "weirdness" in the algorithm, but in general,\n
77  * if your stat is already drained, the "max" value will not drop all\n
78  * the way down to the "cur" value.\n
79  */
80 bool dec_stat(player_type *creature_ptr, int stat, int amount, int permanent)
81 {
82     bool res = FALSE;
83     BASE_STATUS cur = creature_ptr->stat_cur[stat];
84     BASE_STATUS max = creature_ptr->stat_max[stat];
85     int same = (cur == max);
86     if (cur > 3) {
87         if (cur <= 18) {
88             if (amount > 90)
89                 cur--;
90             if (amount > 50)
91                 cur--;
92             if (amount > 20)
93                 cur--;
94             cur--;
95         } else {
96             int loss = (((cur - 18) / 2 + 1) / 2 + 1);
97             if (loss < 1)
98                 loss = 1;
99
100             loss = ((randint1(loss) + loss) * amount) / 100;
101             if (loss < amount / 2)
102                 loss = amount / 2;
103
104             cur = cur - loss;
105             if (cur < 18)
106                 cur = (amount <= 20) ? 18 : 17;
107         }
108
109         if (cur < 3)
110             cur = 3;
111
112         if (cur != creature_ptr->stat_cur[stat])
113             res = TRUE;
114     }
115
116     if (permanent && (max > 3)) {
117         chg_virtue(creature_ptr, V_SACRIFICE, 1);
118         if (stat == A_WIS || stat == A_INT)
119             chg_virtue(creature_ptr, V_ENLIGHTEN, -2);
120
121         if (max <= 18) {
122             if (amount > 90)
123                 max--;
124             if (amount > 50)
125                 max--;
126             if (amount > 20)
127                 max--;
128             max--;
129         } else {
130             int loss = (((max - 18) / 2 + 1) / 2 + 1);
131             loss = ((randint1(loss) + loss) * amount) / 100;
132             if (loss < amount / 2)
133                 loss = amount / 2;
134
135             max = max - loss;
136             if (max < 18)
137                 max = (amount <= 20) ? 18 : 17;
138         }
139
140         if (same || (max < cur))
141             max = cur;
142
143         if (max != creature_ptr->stat_max[stat])
144             res = TRUE;
145     }
146
147     if (res) {
148         creature_ptr->stat_cur[stat] = cur;
149         creature_ptr->stat_max[stat] = max;
150         creature_ptr->redraw |= (PR_STATS);
151         creature_ptr->update |= (PU_BONUS);
152     }
153
154     return (res);
155 }
156
157 /*!
158  * @brief プレイヤーの基本能力値を回復させる / Restore a stat.  Return TRUE only if this actually makes a difference.
159  * @param stat 回復ステータスID
160  * @return 実際に回復した場合TRUEを返す。
161  */
162 bool res_stat(player_type *creature_ptr, int stat)
163 {
164     if (creature_ptr->stat_cur[stat] != creature_ptr->stat_max[stat]) {
165         creature_ptr->stat_cur[stat] = creature_ptr->stat_max[stat];
166         creature_ptr->update |= (PU_BONUS);
167         creature_ptr->redraw |= (PR_STATS);
168         return TRUE;
169     }
170
171     return FALSE;
172 }
173
174 /*
175  * Lose a "point"
176  */
177 bool do_dec_stat(player_type *creature_ptr, int stat)
178 {
179     bool sust = FALSE;
180     switch (stat) {
181     case A_STR:
182         if (has_sustain_str(creature_ptr))
183             sust = TRUE;
184         break;
185     case A_INT:
186         if (has_sustain_int(creature_ptr))
187             sust = TRUE;
188         break;
189     case A_WIS:
190         if (has_sustain_wis(creature_ptr))
191             sust = TRUE;
192         break;
193     case A_DEX:
194         if (has_sustain_dex(creature_ptr))
195             sust = TRUE;
196         break;
197     case A_CON:
198         if (has_sustain_con(creature_ptr))
199             sust = TRUE;
200         break;
201     case A_CHR:
202         if (has_sustain_chr(creature_ptr))
203             sust = TRUE;
204         break;
205     }
206
207     if (sust && (!ironman_nightmare || randint0(13))) {
208         msg_format(_("%sなった気がしたが、すぐに元に戻った。", "You feel %s for a moment, but the feeling passes."), desc_stat_neg[stat]);
209         return TRUE;
210     }
211
212     if (dec_stat(creature_ptr, stat, 10, (ironman_nightmare && !randint0(13)))) {
213         msg_format(_("ひどく%sなった気がする。", "You feel %s."), desc_stat_neg[stat]);
214         return TRUE;
215     }
216
217     return FALSE;
218 }
219
220 /*
221  * Restore lost "points" in a stat
222  */
223 bool do_res_stat(player_type *creature_ptr, int stat)
224 {
225     if (res_stat(creature_ptr, stat)) {
226         msg_format(_("元通りに%sなった気がする。", "You feel %s."), desc_stat_pos[stat]);
227         return TRUE;
228     }
229
230     return FALSE;
231 }
232
233 /*
234  * Gain a "point" in a stat
235  */
236 bool do_inc_stat(player_type *creature_ptr, int stat)
237 {
238     bool res = res_stat(creature_ptr, stat);
239     if (inc_stat(creature_ptr, stat)) {
240         if (stat == A_WIS) {
241             chg_virtue(creature_ptr, V_ENLIGHTEN, 1);
242             chg_virtue(creature_ptr, V_FAITH, 1);
243         } else if (stat == A_INT) {
244             chg_virtue(creature_ptr, V_KNOWLEDGE, 1);
245             chg_virtue(creature_ptr, V_ENLIGHTEN, 1);
246         } else if (stat == A_CON)
247             chg_virtue(creature_ptr, V_VITALITY, 1);
248
249         msg_format(_("ワーオ!とても%sなった!", "Wow! You feel %s!"), desc_stat_pos[stat]);
250         return TRUE;
251     }
252
253     if (res) {
254         msg_format(_("元通りに%sなった気がする。", "You feel %s."), desc_stat_pos[stat]);
255         return TRUE;
256     }
257
258     return FALSE;
259 }
260
261 /*
262  * Forget everything
263  */
264 bool lose_all_info(player_type *creature_ptr)
265 {
266     chg_virtue(creature_ptr, V_KNOWLEDGE, -5);
267     chg_virtue(creature_ptr, V_ENLIGHTEN, -5);
268     for (int i = 0; i < INVEN_TOTAL; i++) {
269         object_type *o_ptr = &creature_ptr->inventory_list[i];
270         if ((o_ptr->k_idx == 0) || object_is_fully_known(o_ptr))
271             continue;
272
273         o_ptr->feeling = FEEL_NONE;
274         o_ptr->ident &= ~(IDENT_EMPTY);
275         o_ptr->ident &= ~(IDENT_KNOWN);
276         o_ptr->ident &= ~(IDENT_SENSE);
277     }
278
279     creature_ptr->update |= (PU_BONUS);
280     creature_ptr->update |= (PU_COMBINE | PU_REORDER);
281     creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
282     wiz_dark(creature_ptr);
283     return TRUE;
284 }