OSDN Git Service

0bab1a7a54a079b3f0d764ea27df213dcd20a732
[hengbandforosx/hengbandosx.git] / src / window / main-window-left-frame.cpp
1 #include "window/main-window-left-frame.h"
2 #include "game-option/special-options.h"
3 #include "game-option/text-display-options.h"
4 #include "market/arena-info-table.h"
5 #include "monster-race/monster-race.h"
6 #include "monster/monster-status.h"
7 #include "player-base/player-race.h"
8 #include "player-info/class-info.h"
9 #include "player-info/mimic-info-table.h"
10 #include "player/player-status-table.h"
11 #include "system/floor-type-definition.h"
12 #include "system/monster-race-definition.h"
13 #include "system/monster-type-definition.h"
14 #include "system/player-type-definition.h"
15 #include "term/screen-processor.h"
16 #include "term/term-color-types.h"
17 #include "timed-effect/player-hallucination.h"
18 #include "timed-effect/timed-effects.h"
19 #include "util/string-processor.h"
20 #include "window/main-window-row-column.h"
21 #include "window/main-window-stat-poster.h"
22 #include "window/main-window-util.h"
23 #include "world/world.h"
24
25 /*!
26  * @brief プレイヤーの称号を表示する / Prints "title", including "wizard" or "winner" as needed.
27  */
28 void print_title(PlayerType *player_ptr)
29 {
30     GAME_TEXT str[14];
31     concptr p = "";
32     if (w_ptr->wizard) {
33         p = _("[ウィザード]", "[=-WIZARD-=]");
34     } else if (w_ptr->total_winner) {
35         if (player_ptr->is_true_winner()) {
36             p = _("*真・勝利者*", "*TRUEWINNER*");
37         } else {
38             p = _("***勝利者***", "***WINNER***");
39         }
40     } else {
41         angband_strcpy(str, player_titles[enum2i(player_ptr->pclass)][(player_ptr->lev - 1) / 5].data(), sizeof(str));
42         p = str;
43     }
44
45     print_field(p, ROW_TITLE, COL_TITLE);
46 }
47
48 /*!
49  * @brief プレイヤーのレベルを表示する / Prints level
50  */
51 void print_level(PlayerType *player_ptr)
52 {
53     char tmp[32];
54     sprintf(tmp, "%5d", player_ptr->lev);
55     if (player_ptr->lev >= player_ptr->max_plv) {
56         put_str(_("レベル ", "LEVEL "), ROW_LEVEL, 0);
57         c_put_str(TERM_L_GREEN, tmp, ROW_LEVEL, COL_LEVEL + 7);
58     } else {
59         put_str(_("xレベル", "Level "), ROW_LEVEL, 0);
60         c_put_str(TERM_YELLOW, tmp, ROW_LEVEL, COL_LEVEL + 7);
61     }
62 }
63
64 /*!
65  * @brief プレイヤーの経験値を表示する / Display the experience
66  */
67 void print_exp(PlayerType *player_ptr)
68 {
69     char out_val[32];
70
71     PlayerRace pr(player_ptr);
72     if ((!exp_need) || pr.equals(PlayerRaceType::ANDROID)) {
73         (void)sprintf(out_val, "%8ld", (long)player_ptr->exp);
74     } else {
75         if (player_ptr->lev >= PY_MAX_LEVEL) {
76             (void)sprintf(out_val, "********");
77         } else {
78             (void)sprintf(out_val, "%8ld", (long)(player_exp[player_ptr->lev - 1] * player_ptr->expfact / 100L) - player_ptr->exp);
79         }
80     }
81
82     if (player_ptr->exp >= player_ptr->max_exp) {
83         if (pr.equals(PlayerRaceType::ANDROID)) {
84             put_str(_("強化 ", "Cst "), ROW_EXP, 0);
85         } else {
86             put_str(_("経験 ", "EXP "), ROW_EXP, 0);
87         }
88         c_put_str(TERM_L_GREEN, out_val, ROW_EXP, COL_EXP + 4);
89     } else {
90         put_str(_("x経験", "Exp "), ROW_EXP, 0);
91         c_put_str(TERM_YELLOW, out_val, ROW_EXP, COL_EXP + 4);
92     }
93 }
94
95 /*!
96  * @brief プレイヤーのACを表示する / Prints current AC
97  */
98 void print_ac(PlayerType *player_ptr)
99 {
100     char tmp[32];
101
102 #ifdef JP
103     /* AC の表示方式を変更している */
104     put_str(" AC(     )", ROW_AC, COL_AC);
105     sprintf(tmp, "%5d", player_ptr->dis_ac + player_ptr->dis_to_a);
106     c_put_str(TERM_L_GREEN, tmp, ROW_AC, COL_AC + 6);
107 #else
108     put_str("Cur AC ", ROW_AC, COL_AC);
109     sprintf(tmp, "%5d", player_ptr->dis_ac + player_ptr->dis_to_a);
110     c_put_str(TERM_L_GREEN, tmp, ROW_AC, COL_AC + 7);
111 #endif
112 }
113
114 /*!
115  * @brief プレイヤーのHPを表示する / Prints Cur/Max hit points
116  */
117 void print_hp(PlayerType *player_ptr)
118 {
119     char tmp[32];
120     put_str("HP", ROW_CURHP, COL_CURHP);
121     sprintf(tmp, "%4ld", (long int)player_ptr->chp);
122     TERM_COLOR color;
123     if (player_ptr->chp >= player_ptr->mhp) {
124         color = TERM_L_GREEN;
125     } else if (player_ptr->chp > (player_ptr->mhp * hitpoint_warn) / 10) {
126         color = TERM_YELLOW;
127     } else {
128         color = TERM_RED;
129     }
130
131     c_put_str(color, tmp, ROW_CURHP, COL_CURHP + 3);
132     put_str("/", ROW_CURHP, COL_CURHP + 7);
133     sprintf(tmp, "%4ld", (long int)player_ptr->mhp);
134     color = TERM_L_GREEN;
135     c_put_str(color, tmp, ROW_CURHP, COL_CURHP + 8);
136 }
137
138 /*!
139  * @brief プレイヤーのMPを表示する / Prints players max/cur spell points
140  */
141 void print_sp(PlayerType *player_ptr)
142 {
143     char tmp[32];
144     byte color;
145     if ((mp_ptr->spell_book == ItemKindType::NONE) && mp_ptr->spell_first == SPELL_FIRST_NO_SPELL) {
146         return;
147     }
148
149     put_str(_("MP", "SP"), ROW_CURSP, COL_CURSP);
150     sprintf(tmp, "%4ld", (long int)player_ptr->csp);
151     if (player_ptr->csp >= player_ptr->msp) {
152         color = TERM_L_GREEN;
153     } else if (player_ptr->csp > (player_ptr->msp * mana_warn) / 10) {
154         color = TERM_YELLOW;
155     } else {
156         color = TERM_RED;
157     }
158
159     c_put_str(color, tmp, ROW_CURSP, COL_CURSP + 3);
160     put_str("/", ROW_CURSP, COL_CURSP + 7);
161     sprintf(tmp, "%4ld", (long int)player_ptr->msp);
162     color = TERM_L_GREEN;
163     c_put_str(color, tmp, ROW_CURSP, COL_CURSP + 8);
164 }
165
166 /*!
167  * @brief プレイヤーの所持金を表示する / Prints current gold
168  * @param player_ptr プレイヤーへの参照ポインタ
169  */
170 void print_gold(PlayerType *player_ptr)
171 {
172     char tmp[32];
173     put_str(_("$ ", "AU "), ROW_GOLD, COL_GOLD);
174     sprintf(tmp, "%9ld", (long)player_ptr->au);
175     c_put_str(TERM_L_GREEN, tmp, ROW_GOLD, COL_GOLD + 3);
176 }
177
178 /*!
179  * @brief 現在のフロアの深さを表示する / Prints depth in stat area
180  * @param player_ptr プレイヤーへの参照ポインタ
181  */
182 void print_depth(PlayerType *player_ptr)
183 {
184     char depths[32];
185     TERM_COLOR attr = TERM_WHITE;
186
187     TERM_LEN wid, hgt;
188     term_get_size(&wid, &hgt);
189     TERM_LEN col_depth = wid + COL_DEPTH;
190     TERM_LEN row_depth = hgt + ROW_DEPTH;
191
192     auto *floor_ptr = player_ptr->current_floor_ptr;
193     if (!floor_ptr->dun_level) {
194         strcpy(depths, _("地上", "Surf."));
195         c_prt(attr, format("%7s", depths), row_depth, col_depth);
196         return;
197     }
198
199     if (inside_quest(floor_ptr->quest_number) && !player_ptr->dungeon_idx) {
200         strcpy(depths, _("地上", "Quest"));
201         c_prt(attr, format("%7s", depths), row_depth, col_depth);
202         return;
203     }
204
205     if (depth_in_feet) {
206         (void)sprintf(depths, _("%d ft", "%d ft"), (int)floor_ptr->dun_level * 50);
207     } else {
208         (void)sprintf(depths, _("%d 階", "Lev %d"), (int)floor_ptr->dun_level);
209     }
210
211     switch (player_ptr->feeling) {
212     case 0:
213         attr = TERM_SLATE;
214         break; /* Unknown */
215     case 1:
216         attr = TERM_L_BLUE;
217         break; /* Special */
218     case 2:
219         attr = TERM_VIOLET;
220         break; /* Horrible visions */
221     case 3:
222         attr = TERM_RED;
223         break; /* Very dangerous */
224     case 4:
225         attr = TERM_L_RED;
226         break; /* Very bad feeling */
227     case 5:
228         attr = TERM_ORANGE;
229         break; /* Bad feeling */
230     case 6:
231         attr = TERM_YELLOW;
232         break; /* Nervous */
233     case 7:
234         attr = TERM_L_UMBER;
235         break; /* Luck is turning */
236     case 8:
237         attr = TERM_L_WHITE;
238         break; /* Don't like */
239     case 9:
240         attr = TERM_WHITE;
241         break; /* Reasonably safe */
242     case 10:
243         attr = TERM_WHITE;
244         break; /* Boring place */
245     }
246
247     c_prt(attr, format("%7s", depths), row_depth, col_depth);
248 }
249
250 /*!
251  * @brief プレイヤーのステータスを一括表示する(左側部分) / Display basic info (mostly left of map)
252  * @param player_ptr プレイヤーへの参照ポインタ
253  */
254 void print_frame_basic(PlayerType *player_ptr)
255 {
256     if (player_ptr->mimic_form != MimicKindType::NONE) {
257         print_field(mimic_info.at(player_ptr->mimic_form).title, ROW_RACE, COL_RACE);
258     } else {
259         char str[14];
260         angband_strcpy(str, rp_ptr->title, sizeof(str));
261         print_field(str, ROW_RACE, COL_RACE);
262     }
263
264     print_title(player_ptr);
265     print_level(player_ptr);
266     print_exp(player_ptr);
267     for (int i = 0; i < A_MAX; i++) {
268         print_stat(player_ptr, i);
269     }
270
271     print_ac(player_ptr);
272     print_hp(player_ptr);
273     print_sp(player_ptr);
274     print_gold(player_ptr);
275     print_depth(player_ptr);
276     health_redraw(player_ptr, false);
277     health_redraw(player_ptr, true);
278 }
279
280 /*!
281  * @brief モンスターの体力ゲージを表示する
282  * @param riding TRUEならば騎乗中のモンスターの体力、FALSEならターゲットモンスターの体力を表示する。表示位置は固定。
283  * @details
284  * <pre>
285  * Redraw the "monster health bar"      -DRS-
286  * Rather extensive modifications by    -BEN-
287  *
288  * The "monster health bar" provides visual feedback on the "health"
289  * of the monster currently being "tracked".  There are several ways
290  * to "track" a monster, including targetting it, attacking it, and
291  * affecting it (and nobody else) with a ranged attack.
292  *
293  * Display the monster health bar (affectionately known as the
294  * "health-o-meter").  Clear health bar if nothing is being tracked.
295  * Auto-track current target monster when bored.  Note that the
296  * health-bar stops tracking any monster that "disappears".
297  * </pre>
298  */
299 void health_redraw(PlayerType *player_ptr, bool riding)
300 {
301     int16_t health_who;
302     int row, col;
303
304     if (riding) {
305         health_who = player_ptr->riding;
306         row = ROW_RIDING_INFO;
307         col = COL_RIDING_INFO;
308     } else {
309         health_who = player_ptr->health_who;
310         row = ROW_INFO;
311         col = COL_INFO;
312     }
313
314     monster_type *m_ptr;
315     m_ptr = &player_ptr->current_floor_ptr->m_list[health_who];
316
317     if (w_ptr->wizard && player_ptr->phase_out) {
318         row = ROW_INFO - 1;
319         col = COL_INFO + 2;
320
321         term_putstr(col - 2, row, 12, TERM_WHITE, "      /     ");
322         term_putstr(col - 2, row + 1, 12, TERM_WHITE, "      /     ");
323         term_putstr(col - 2, row + 2, 12, TERM_WHITE, "      /     ");
324         term_putstr(col - 2, row + 3, 12, TERM_WHITE, "      /     ");
325
326         if (MonsterRace(player_ptr->current_floor_ptr->m_list[1].r_idx).is_valid()) {
327             term_putstr(col - 2, row, 2, r_info[player_ptr->current_floor_ptr->m_list[1].r_idx].x_attr,
328                 format("%c", r_info[player_ptr->current_floor_ptr->m_list[1].r_idx].x_char));
329             term_putstr(col - 1, row, 5, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[1].hp));
330             term_putstr(col + 5, row, 6, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[1].max_maxhp));
331         }
332
333         if (MonsterRace(player_ptr->current_floor_ptr->m_list[2].r_idx).is_valid()) {
334             term_putstr(col - 2, row + 1, 2, r_info[player_ptr->current_floor_ptr->m_list[2].r_idx].x_attr,
335                 format("%c", r_info[player_ptr->current_floor_ptr->m_list[2].r_idx].x_char));
336             term_putstr(col - 1, row + 1, 5, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[2].hp));
337             term_putstr(col + 5, row + 1, 6, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[2].max_maxhp));
338         }
339
340         if (MonsterRace(player_ptr->current_floor_ptr->m_list[3].r_idx).is_valid()) {
341             term_putstr(col - 2, row + 2, 2, r_info[player_ptr->current_floor_ptr->m_list[3].r_idx].x_attr,
342                 format("%c", r_info[player_ptr->current_floor_ptr->m_list[3].r_idx].x_char));
343             term_putstr(col - 1, row + 2, 5, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[3].hp));
344             term_putstr(col + 5, row + 2, 6, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[3].max_maxhp));
345         }
346
347         if (MonsterRace(player_ptr->current_floor_ptr->m_list[4].r_idx).is_valid()) {
348             term_putstr(col - 2, row + 3, 2, r_info[player_ptr->current_floor_ptr->m_list[4].r_idx].x_attr,
349                 format("%c", r_info[player_ptr->current_floor_ptr->m_list[4].r_idx].x_char));
350             term_putstr(col - 1, row + 3, 5, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[4].hp));
351             term_putstr(col + 5, row + 3, 6, TERM_WHITE, format("%5d", player_ptr->current_floor_ptr->m_list[4].max_maxhp));
352         }
353
354         return;
355     }
356
357     if (!health_who) {
358         term_erase(col, row, 12);
359         return;
360     }
361
362     if (!m_ptr->ml) {
363         term_putstr(col, row, 12, TERM_WHITE, "[----------]");
364         return;
365     }
366
367     if (player_ptr->effects()->hallucination()->is_hallucinated()) {
368         term_putstr(col, row, 12, TERM_WHITE, "[----------]");
369         return;
370     }
371
372     if (m_ptr->hp < 0) {
373         term_putstr(col, row, 12, TERM_WHITE, "[----------]");
374         return;
375     }
376
377     int pct = m_ptr->maxhp > 0 ? 100L * m_ptr->hp / m_ptr->maxhp : 0;
378     int pct2 = m_ptr->maxhp > 0 ? 100L * m_ptr->hp / m_ptr->max_maxhp : 0;
379     int len = (pct2 < 10) ? 1 : (pct2 < 90) ? (pct2 / 10 + 1)
380                                             : 10;
381     TERM_COLOR attr = TERM_RED;
382     if (monster_invulner_remaining(m_ptr)) {
383         attr = TERM_WHITE;
384     } else if (m_ptr->is_asleep()) {
385         attr = TERM_BLUE;
386     } else if (monster_fear_remaining(m_ptr)) {
387         attr = TERM_VIOLET;
388     } else if (pct >= 100) {
389         attr = TERM_L_GREEN;
390     } else if (pct >= 60) {
391         attr = TERM_YELLOW;
392     } else if (pct >= 25) {
393         attr = TERM_ORANGE;
394     } else if (pct >= 10) {
395         attr = TERM_L_RED;
396     }
397
398     term_putstr(col, row, 12, TERM_WHITE, "[----------]");
399     term_putstr(col + 1, row, len, attr, "**********");
400 }