OSDN Git Service

[Refactor] #919 Removed cave_los_grid() and moved cave_has_los_grid() from cave.cpp...
[hengbandforosx/hengbandosx.git] / src / pet / pet-fall-off.cpp
1 /*!
2  * @brief 落馬処理
3  * @date 2020/05/31
4  * @author Hourier
5  */
6
7 #include "pet/pet-fall-off.h"
8 #include "core/player-redraw-types.h"
9 #include "core/player-update-types.h"
10 #include "core/stuff-handler.h"
11 #include "core/window-redrawer.h"
12 #include "floor/cave.h"
13 #include "floor/geometry.h"
14 #include "grid/feature.h"
15 #include "grid/grid.h"
16 #include "monster-attack/monster-attack-util.h"
17 #include "monster-race/monster-race.h"
18 #include "monster/monster-describer.h"
19 #include "pet/pet-util.h"
20 #include "player/player-damage.h"
21 #include "player/player-move.h"
22 #include "player/player-skill.h"
23 #include "system/floor-type-definition.h"
24 #include "system/grid-type-definition.h"
25 #include "system/monster-race-definition.h"
26 #include "system/monster-type-definition.h"
27 #include "system/player-type-definition.h"
28 #include "target/target-checker.h"
29 #include "view/display-messages.h"
30
31 /*!
32  * @brief モンスターから直接攻撃を受けた時に落馬するかどうかを判定し、判定アウトならば落馬させる
33  * @param creature_ptr プレーヤーへの参照ポインタ
34  * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
35  */
36 void check_fall_off_horse(player_type *creature_ptr, monap_type *monap_ptr)
37 {
38     if ((creature_ptr->riding == 0) || (monap_ptr->damage == 0))
39         return;
40
41     char m_steed_name[MAX_NLEN];
42     monster_desc(creature_ptr, m_steed_name, &creature_ptr->current_floor_ptr->m_list[creature_ptr->riding], 0);
43     if (process_fall_off_horse(creature_ptr, (monap_ptr->damage > 200) ? 200 : monap_ptr->damage, false))
44         msg_format(_("%^sから落ちてしまった!", "You have fallen from %s."), m_steed_name);
45 }
46
47 /*!
48  * @brief 落馬する可能性を計算する
49  * @param creature_ptr プレーヤーへの参照ポインタ
50  * @param dam 落馬判定を発した際に受けたダメージ量
51  * @param force TRUEならば強制的に落馬する
52  * @param 乗馬中のモンスターのレベル
53  * @return FALSEなら落馬しないことで確定、TRUEなら処理続行
54  * @details レベルの低い乗馬からは落馬しにくい
55  */
56 static bool calc_fall_off_possibility(player_type *creature_ptr, const HIT_POINT dam, const bool force, monster_race *r_ptr)
57 {
58     if (force)
59         return true;
60
61     int cur = creature_ptr->skill_exp[SKILL_RIDING];
62     int max = s_info[creature_ptr->pclass].s_max[SKILL_RIDING];
63     int ridinglevel = r_ptr->level;
64
65     int fall_off_level = r_ptr->level;
66     if (creature_ptr->riding_ryoute)
67         fall_off_level += 20;
68
69     if ((cur < max) && (max > 1000) && (dam / 2 + ridinglevel) > (cur / 30 + 10)) {
70         int inc = 0;
71         if (ridinglevel > (cur / 100 + 15))
72             inc += 1 + (ridinglevel - cur / 100 - 15);
73         else
74             inc += 1;
75
76         creature_ptr->skill_exp[SKILL_RIDING] = MIN(max, cur + inc);
77     }
78
79     if (randint0(dam / 2 + fall_off_level * 2) >= cur / 30 + 10)
80         return true;
81
82     if ((((creature_ptr->pclass == CLASS_BEASTMASTER) || (creature_ptr->pclass == CLASS_CAVALRY)) && !creature_ptr->riding_ryoute)
83         || !one_in_(creature_ptr->lev * (creature_ptr->riding_ryoute ? 2 : 3) + 30)) {
84         return false;
85     }
86
87     return true;
88 }
89
90 /*!
91  * @brief プレイヤーの落馬判定処理
92  * @param dam 落馬判定を発した際に受けたダメージ量
93  * @param force TRUEならば強制的に落馬する
94  * @return 実際に落馬したらTRUEを返す
95  */
96 bool process_fall_off_horse(player_type *creature_ptr, HIT_POINT dam, bool force)
97 {
98     POSITION sy = 0;
99     POSITION sx = 0;
100     int sn = 0;
101     GAME_TEXT m_name[MAX_NLEN];
102     monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->riding];
103     monster_race *r_ptr = &r_info[m_ptr->r_idx];
104
105     if (!creature_ptr->riding || creature_ptr->wild_mode)
106         return false;
107
108     if (dam >= 0 || force) {
109         if (!calc_fall_off_possibility(creature_ptr, dam, force, r_ptr))
110             return false;
111
112         /* Check around the player */
113         for (DIRECTION i = 0; i < 8; i++) {
114             POSITION y = creature_ptr->y + ddy_ddd[i];
115             POSITION x = creature_ptr->x + ddx_ddd[i];
116
117             grid_type *g_ptr;
118             g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
119
120             if (g_ptr->m_idx)
121                 continue;
122
123             /* Skip non-empty grids */
124             if (!g_ptr->cave_has_flag(FF_MOVE) && !g_ptr->cave_has_flag(FF_CAN_FLY)) {
125                 if (!can_player_ride_pet(creature_ptr, g_ptr, false))
126                     continue;
127             }
128
129             if (g_ptr->cave_has_flag(FF_PATTERN))
130                 continue;
131
132             /* Count "safe" grids */
133             sn++;
134
135             /* Randomize choice */
136             if (randint0(sn) > 0)
137                 continue;
138
139             /* Save the safe location */
140             sy = y;
141             sx = x;
142         }
143
144         if (!sn) {
145             monster_desc(creature_ptr, m_name, m_ptr, 0);
146             msg_format(_("%sから振り落とされそうになって、壁にぶつかった。", "You have nearly fallen from %s but bumped into a wall."), m_name);
147             take_hit(creature_ptr, DAMAGE_NOESCAPE, r_ptr->level + 3, _("壁への衝突", "bumping into a wall"));
148             return false;
149         }
150
151         POSITION old_y = creature_ptr->y;
152         POSITION old_x = creature_ptr->x;
153         creature_ptr->y = sy;
154         creature_ptr->x = sx;
155         lite_spot(creature_ptr, old_y, old_x);
156         lite_spot(creature_ptr, creature_ptr->y, creature_ptr->x);
157         verify_panel(creature_ptr);
158     }
159
160     creature_ptr->riding = 0;
161     creature_ptr->pet_extra_flags &= ~(PF_TWO_HANDS);
162     creature_ptr->riding_ryoute = creature_ptr->old_riding_ryoute = false;
163
164     creature_ptr->update |= (PU_BONUS | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
165     handle_stuff(creature_ptr);
166
167     creature_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
168     creature_ptr->redraw |= (PR_EXTRA);
169
170     /* Update health track of mount */
171     creature_ptr->redraw |= (PR_UHEALTH);
172
173     bool fall_dam = false;
174     if (creature_ptr->levitation && !force) {
175         monster_desc(creature_ptr, m_name, m_ptr, 0);
176         msg_format(_("%sから落ちたが、空中でうまく体勢を立て直して着地した。", "You are thrown from %s but make a good landing."), m_name);
177     } else {
178         take_hit(creature_ptr, DAMAGE_NOESCAPE, r_ptr->level + 3, _("落馬", "Falling from riding"));
179         fall_dam = true;
180     }
181
182     if (sy && !creature_ptr->is_dead)
183         (void)move_player_effect(creature_ptr, creature_ptr->y, creature_ptr->x, MPE_DONT_PICKUP | MPE_DONT_SWAP_MON);
184
185     return fall_dam;
186 }