OSDN Git Service

[Refactor] #40392 Separated decide_initial_items() from player_outfit()
[hengbandforosx/hengbandosx.git] / src / birth / inventory-initializer.c
1 #include "system/angband.h"
2 #include "birth/inventory-initializer.h"
3 #include "monster/monsterrace-hook.h"
4 #include "player/player-personality.h"
5 #include "birth/initial-equipments-table.h"
6 #include "object/object-ego.h"
7 #include "object/object-kind.h"
8 #include "autopick/autopick.h"
9
10 /*!
11  * @brief 所持状態にあるアイテムの中から一部枠の装備可能なものを装備させる。
12  * @return なし
13  */
14 void wield_all(player_type *creature_ptr)
15 {
16     object_type object_type_body;
17     for (INVENTORY_IDX item = INVEN_PACK - 1; item >= 0; item--) {
18         object_type *o_ptr;
19         o_ptr = &creature_ptr->inventory_list[item];
20         if (!o_ptr->k_idx)
21             continue;
22
23         int slot = wield_slot(creature_ptr, o_ptr);
24         if (slot < INVEN_RARM)
25             continue;
26         if (slot == INVEN_LITE)
27             continue;
28         if (creature_ptr->inventory_list[slot].k_idx)
29             continue;
30
31         object_type *i_ptr;
32         i_ptr = &object_type_body;
33         object_copy(i_ptr, o_ptr);
34         i_ptr->number = 1;
35
36         if (item >= 0) {
37             inven_item_increase(creature_ptr, item, -1);
38             inven_item_optimize(creature_ptr, item);
39         } else {
40             floor_item_increase(creature_ptr->current_floor_ptr, 0 - item, -1);
41             floor_item_optimize(creature_ptr, 0 - item);
42         }
43
44         o_ptr = &creature_ptr->inventory_list[slot];
45         object_copy(o_ptr, i_ptr);
46         creature_ptr->total_weight += i_ptr->weight;
47         creature_ptr->equip_cnt++;
48     }
49 }
50
51 /*!
52  * @brief 初期所持アイテムの処理 / Add an outfit object
53  * @details アイテムを既知のものとした上でwield_all()関数により装備させる。
54  * @param o_ptr 処理したいオブジェクト構造体の参照ポインタ
55  * @return なし
56  */
57 void add_outfit(player_type *creature_ptr, object_type *o_ptr)
58 {
59     object_aware(creature_ptr, o_ptr);
60     object_known(o_ptr);
61     s16b slot = inven_carry(creature_ptr, o_ptr);
62     autopick_alter_item(creature_ptr, slot, FALSE);
63     wield_all(creature_ptr);
64 }
65
66 static void decide_initial_items(player_type *creature_ptr, object_type *q_ptr)
67 {
68     switch (creature_ptr->prace) {
69     case RACE_VAMPIRE:
70         /* Nothing! */
71         /* Vampires can drain blood of creatures */
72         break;
73     case RACE_DEMON:
74         /* Demon can drain vitality from humanoid corpse */
75         get_mon_num_prep(creature_ptr, monster_hook_human, NULL);
76         for (int i = rand_range(3, 4); i > 0; i--) {
77             object_prep(q_ptr, lookup_kind(TV_CORPSE, SV_CORPSE));
78             q_ptr->pval = get_mon_num(creature_ptr, 2, 0);
79             if (q_ptr->pval) {
80                 q_ptr->number = 1;
81                 add_outfit(creature_ptr, q_ptr);
82             }
83         }
84
85         break;
86     case RACE_SKELETON:
87     case RACE_GOLEM:
88     case RACE_ZOMBIE:
89     case RACE_SPECTRE:
90         /* Staff (of Nothing) */
91         object_prep(q_ptr, lookup_kind(TV_STAFF, SV_STAFF_NOTHING));
92         q_ptr->number = 1;
93         add_outfit(creature_ptr, q_ptr);
94         break;
95     case RACE_ENT:
96         /* Potions of Water */
97         object_prep(q_ptr, lookup_kind(TV_POTION, SV_POTION_WATER));
98         q_ptr->number = (ITEM_NUMBER)rand_range(15, 23);
99         add_outfit(creature_ptr, q_ptr);
100         break;
101     case RACE_ANDROID:
102         /* Flasks of oil */
103         object_prep(q_ptr, lookup_kind(TV_FLASK, SV_ANY));
104         apply_magic(creature_ptr, q_ptr, 1, AM_NO_FIXED_ART);
105         q_ptr->number = (ITEM_NUMBER)rand_range(7, 12);
106         add_outfit(creature_ptr, q_ptr);
107         break;
108     default:
109         /* Food rations */
110         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));
111         q_ptr->number = (ITEM_NUMBER)rand_range(3, 7);
112         add_outfit(creature_ptr, q_ptr);
113     }
114 }
115
116 /*!
117  * @brief 種族/職業/性格などに基づき初期所持アイテムを設定するメインセット関数。 / Init players with some belongings
118  * @details Having an item makes the player "aware" of its purpose.
119  * @return なし
120  */
121 void player_outfit(player_type *creature_ptr)
122 {
123     object_type *q_ptr;
124     object_type forge;
125     q_ptr = &forge;
126
127     decide_initial_items(creature_ptr, q_ptr);
128     q_ptr = &forge;
129
130     if ((creature_ptr->prace == RACE_VAMPIRE) && (creature_ptr->pclass != CLASS_NINJA)) {
131         object_prep(q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_DARKNESS));
132         q_ptr->number = (ITEM_NUMBER)rand_range(2, 5);
133         add_outfit(creature_ptr, q_ptr);
134     } else if (creature_ptr->pclass != CLASS_NINJA) {
135         object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_TORCH));
136         q_ptr->number = (ITEM_NUMBER)rand_range(3, 7);
137         q_ptr->xtra4 = rand_range(3, 7) * 500;
138
139         add_outfit(creature_ptr, q_ptr);
140     }
141
142     q_ptr = &forge;
143     if (creature_ptr->prace == RACE_MERFOLK) {
144         object_prep(q_ptr, lookup_kind(TV_RING, SV_RING_LEVITATION_FALL));
145         q_ptr->number = 1;
146         add_outfit(creature_ptr, q_ptr);
147     }
148
149     if ((creature_ptr->pclass == CLASS_RANGER) || (creature_ptr->pclass == CLASS_CAVALRY)) {
150         object_prep(q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL));
151         q_ptr->number = (byte)rand_range(15, 20);
152         add_outfit(creature_ptr, q_ptr);
153     }
154
155     if (creature_ptr->pclass == CLASS_RANGER) {
156         object_prep(q_ptr, lookup_kind(TV_BOW, SV_SHORT_BOW));
157         add_outfit(creature_ptr, q_ptr);
158     } else if (creature_ptr->pclass == CLASS_ARCHER) {
159         object_prep(q_ptr, lookup_kind(TV_ARROW, SV_AMMO_NORMAL));
160         q_ptr->number = (ITEM_NUMBER)rand_range(15, 20);
161         add_outfit(creature_ptr, q_ptr);
162     } else if (creature_ptr->pclass == CLASS_HIGH_MAGE) {
163         object_prep(q_ptr, lookup_kind(TV_WAND, SV_WAND_MAGIC_MISSILE));
164         q_ptr->number = 1;
165         q_ptr->pval = (PARAMETER_VALUE)rand_range(25, 30);
166         add_outfit(creature_ptr, q_ptr);
167     } else if (creature_ptr->pclass == CLASS_SORCERER) {
168         OBJECT_TYPE_VALUE book_tval;
169         for (book_tval = TV_LIFE_BOOK; book_tval <= TV_LIFE_BOOK + MAX_MAGIC - 1; book_tval++) {
170             object_prep(q_ptr, lookup_kind(book_tval, 0));
171             q_ptr->number = 1;
172             add_outfit(creature_ptr, q_ptr);
173         }
174     } else if (creature_ptr->pclass == CLASS_TOURIST) {
175         if (creature_ptr->pseikaku != SEIKAKU_SEXY) {
176             object_prep(q_ptr, lookup_kind(TV_SHOT, SV_AMMO_LIGHT));
177             q_ptr->number = rand_range(15, 20);
178             add_outfit(creature_ptr, q_ptr);
179         }
180
181         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_BISCUIT));
182         q_ptr->number = rand_range(2, 4);
183
184         add_outfit(creature_ptr, q_ptr);
185
186         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_WAYBREAD));
187         q_ptr->number = rand_range(2, 4);
188
189         add_outfit(creature_ptr, q_ptr);
190
191         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_JERKY));
192         q_ptr->number = rand_range(1, 3);
193
194         add_outfit(creature_ptr, q_ptr);
195
196         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_ALE));
197         q_ptr->number = rand_range(2, 4);
198
199         add_outfit(creature_ptr, q_ptr);
200
201         object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_PINT_OF_WINE));
202         q_ptr->number = rand_range(2, 4);
203
204         add_outfit(creature_ptr, q_ptr);
205     } else if (creature_ptr->pclass == CLASS_NINJA) {
206         object_prep(q_ptr, lookup_kind(TV_SPIKE, 0));
207         q_ptr->number = rand_range(15, 20);
208         add_outfit(creature_ptr, q_ptr);
209     } else if (creature_ptr->pclass == CLASS_SNIPER) {
210         object_prep(q_ptr, lookup_kind(TV_BOLT, SV_AMMO_NORMAL));
211         q_ptr->number = rand_range(15, 20);
212         add_outfit(creature_ptr, q_ptr);
213     }
214
215     if (creature_ptr->pseikaku == SEIKAKU_SEXY) {
216         player_init[creature_ptr->pclass][2][0] = TV_HAFTED;
217         player_init[creature_ptr->pclass][2][1] = SV_WHIP;
218     }
219
220     for (int i = 0; i < 3; i++) {
221         OBJECT_TYPE_VALUE tv = player_init[creature_ptr->pclass][i][0];
222         OBJECT_SUBTYPE_VALUE sv = player_init[creature_ptr->pclass][i][1];
223         if ((creature_ptr->prace == RACE_ANDROID) && ((tv == TV_SOFT_ARMOR) || (tv == TV_HARD_ARMOR)))
224             continue;
225
226         if (tv == TV_SORCERY_BOOK)
227             tv = TV_LIFE_BOOK + creature_ptr->realm1 - 1;
228         else if (tv == TV_DEATH_BOOK)
229             tv = TV_LIFE_BOOK + creature_ptr->realm2 - 1;
230         else if (tv == TV_RING && sv == SV_RING_RES_FEAR && creature_ptr->prace == RACE_BARBARIAN)
231             sv = SV_RING_SUSTAIN_STR;
232         else if (tv == TV_RING && sv == SV_RING_SUSTAIN_INT && creature_ptr->prace == RACE_MIND_FLAYER) {
233             tv = TV_POTION;
234             sv = SV_POTION_RESTORE_MANA;
235         }
236
237         q_ptr = &forge;
238         object_prep(q_ptr, lookup_kind(tv, sv));
239         if ((tv == TV_SWORD || tv == TV_HAFTED) && (creature_ptr->pclass == CLASS_ROGUE && creature_ptr->realm1 == REALM_DEATH)) /* Only assassins get a poisoned weapon */
240             q_ptr->name2 = EGO_BRAND_POIS;
241
242         add_outfit(creature_ptr, q_ptr);
243     }
244
245     k_info[lookup_kind(TV_POTION, SV_POTION_WATER)].aware = TRUE;
246 }