OSDN Git Service

Merge pull request #3532 from sikabane-works/release/3.0.0.87-alpha
[hengbandforosx/hengbandosx.git] / src / racial / racial-android.cpp
1 #include "racial/racial-android.h"
2 #include "effect/attribute-types.h"
3 #include "inventory/inventory-slot-types.h"
4 #include "object-enchant/object-ego.h"
5 #include "object-enchant/trg-types.h"
6 #include "object-hook/hook-weapon.h"
7 #include "object/object-value-calc.h"
8 #include "object/object-value.h"
9 #include "object/tval-types.h"
10 #include "player-base/player-race.h"
11 #include "player-info/equipment-info.h"
12 #include "player/player-status.h"
13 #include "spell-kind/spells-launcher.h"
14 #include "sv-definition/sv-armor-types.h"
15 #include "sv-definition/sv-protector-types.h"
16 #include "sv-definition/sv-weapon-types.h"
17 #include "system/artifact-type-definition.h"
18 #include "system/baseitem-info.h"
19 #include "system/item-entity.h"
20 #include "system/player-type-definition.h"
21 #include "target/target-getter.h"
22 #include "view/display-messages.h"
23
24 bool android_inside_weapon(PlayerType *player_ptr)
25 {
26     DIRECTION dir;
27     if (!get_aim_dir(player_ptr, &dir)) {
28         return false;
29     }
30
31     if (player_ptr->lev < 10) {
32         msg_print(_("レイガンを発射した。", "You fire your ray gun."));
33         fire_bolt(player_ptr, AttributeType::MISSILE, dir, (player_ptr->lev + 1) / 2);
34         return true;
35     }
36
37     if (player_ptr->lev < 25) {
38         msg_print(_("ブラスターを発射した。", "You fire your blaster."));
39         fire_bolt(player_ptr, AttributeType::MISSILE, dir, player_ptr->lev);
40         return true;
41     }
42
43     if (player_ptr->lev < 35) {
44         msg_print(_("バズーカを発射した。", "You fire your bazooka."));
45         fire_ball(player_ptr, AttributeType::MISSILE, dir, player_ptr->lev * 2, 2);
46         return true;
47     }
48
49     if (player_ptr->lev < 45) {
50         msg_print(_("ビームキャノンを発射した。", "You fire a beam cannon."));
51         fire_beam(player_ptr, AttributeType::MISSILE, dir, player_ptr->lev * 2);
52         return true;
53     }
54
55     msg_print(_("ロケットを発射した。", "You fire a rocket."));
56     fire_rocket(player_ptr, AttributeType::ROCKET, dir, player_ptr->lev * 5, 2);
57     return true;
58 }
59
60 void calc_android_exp(PlayerType *player_ptr)
61 {
62     uint32_t total_exp = 0;
63     if (player_ptr->is_dead || !PlayerRace(player_ptr).equals(PlayerRaceType::ANDROID)) {
64         return;
65     }
66
67     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
68         auto *o_ptr = &player_ptr->inventory_list[i];
69         ItemEntity forge;
70         auto *q_ptr = &forge;
71         uint32_t value, exp;
72         DEPTH level = std::max(o_ptr->get_baseitem().level - 8, 1);
73
74         if ((i == INVEN_MAIN_RING) || (i == INVEN_SUB_RING) || (i == INVEN_NECK) || (i == INVEN_LITE)) {
75             continue;
76         }
77         if (!o_ptr->is_valid()) {
78             continue;
79         }
80
81         q_ptr->wipe();
82         q_ptr->copy_from(o_ptr);
83         q_ptr->discount = 0;
84         q_ptr->curse_flags.clear();
85
86         if (o_ptr->is_fixed_artifact()) {
87             const auto &artifact = o_ptr->get_fixed_artifact();
88             level = (level + std::max(artifact.level - 8, 5)) / 2;
89             level += std::min(20, artifact.rarity / (artifact.gen_flags.has(ItemGenerationTraitType::INSTA_ART) ? 10 : 3));
90         } else if (o_ptr->is_ego()) {
91             level += std::max(3, (o_ptr->get_ego().rating - 5) / 2);
92         } else if (o_ptr->is_random_artifact()) {
93             int32_t total_flags = flag_cost(o_ptr, o_ptr->pval);
94             int fake_level;
95
96             if (!o_ptr->is_weapon_ammo()) {
97                 if (total_flags < 15000) {
98                     fake_level = 10;
99                 } else if (total_flags < 35000) {
100                     fake_level = 25;
101                 } else {
102                     fake_level = 40;
103                 }
104             } else {
105                 if (total_flags < 20000) {
106                     fake_level = 10;
107                 } else if (total_flags < 45000) {
108                     fake_level = 25;
109                 } else {
110                     fake_level = 40;
111                 }
112             }
113
114             level = std::max(level, (level + std::max(fake_level - 8, 5)) / 2 + 3);
115         }
116
117         value = object_value_real(q_ptr);
118         if (value <= 0) {
119             continue;
120         }
121
122         const auto &bi_key = o_ptr->bi_key;
123         if ((bi_key == BaseitemKey(ItemKindType::SOFT_ARMOR, SV_ABUNAI_MIZUGI)) && (player_ptr->ppersonality != PERSONALITY_SEXY)) {
124             value /= 32;
125         }
126
127         if (value > 5000000L) {
128             value = 5000000L;
129         }
130
131         const auto tval = o_ptr->bi_key.tval();
132         if ((tval == ItemKindType::DRAG_ARMOR) || (tval == ItemKindType::CARD)) {
133             level /= 2;
134         }
135
136         auto is_dragon_protector = tval == ItemKindType::DRAG_ARMOR;
137         is_dragon_protector |= bi_key == BaseitemKey(ItemKindType::HELM, SV_DRAGON_HELM);
138         is_dragon_protector |= bi_key == BaseitemKey(ItemKindType::SHIELD, SV_DRAGON_SHIELD);
139         is_dragon_protector |= bi_key == BaseitemKey(ItemKindType::GLOVES, SV_SET_OF_DRAGON_GLOVES);
140         is_dragon_protector |= bi_key == BaseitemKey(ItemKindType::BOOTS, SV_PAIR_OF_DRAGON_GREAVE);
141         const auto is_diamond_edge = bi_key == BaseitemKey(ItemKindType::SWORD, SV_DIAMOND_EDGE);
142         if (o_ptr->is_fixed_or_random_artifact() || o_ptr->is_ego() || is_dragon_protector || is_diamond_edge) {
143             if (level > 65) {
144                 level = 35 + (level - 65) / 5;
145             } else if (level > 35) {
146                 level = 25 + (level - 35) / 3;
147             } else if (level > 15) {
148                 level = 15 + (level - 15) / 2;
149             }
150             exp = std::min<uint>(100000, value) / 2 * level * level;
151             if (value > 100000L) {
152                 exp += (value - 100000L) / 8 * level * level;
153             }
154         } else {
155             exp = std::min<uint>(100000, value) * level;
156             if (value > 100000L) {
157                 exp += (value - 100000L) / 4 * level;
158             }
159         }
160         if ((((i == INVEN_MAIN_HAND) || (i == INVEN_SUB_HAND)) && (has_melee_weapon(player_ptr, i))) || (i == INVEN_BOW)) {
161             total_exp += exp / 48;
162         } else {
163             total_exp += exp / 16;
164         }
165         if (i == INVEN_BODY) {
166             total_exp += exp / 32;
167         }
168     }
169
170     player_ptr->exp = player_ptr->max_exp = total_exp;
171     check_experience(player_ptr);
172 }