OSDN Git Service

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