OSDN Git Service

[Refactor] #1752 PlayerClassTypeをenumからenum classへ変更した
[hengbandforosx/hengbandosx.git] / src / load / player-info-loader.cpp
1 #include "load/player-info-loader.h"
2 #include "cmd-building/cmd-building.h"
3 #include "dungeon/dungeon.h"
4 #include "load/angband-version-comparer.h"
5 #include "load/birth-loader.h"
6 #include "load/dummy-loader.h"
7 #include "load/load-util.h"
8 #include "load/load-v1-7-0.h"
9 #include "load/load-zangband.h"
10 #include "load/player-attack-loader.h"
11 #include "load/player-class-specific-data-loader.h"
12 #include "load/world-loader.h"
13 #include "market/arena.h"
14 #include "monster-race/race-ability-flags.h"
15 #include "mutation/mutation-calculator.h"
16 #include "player-base/player-class.h"
17 #include "player-info/mane-data-type.h"
18 #include "player-info/sniper-data-type.h"
19 #include "player/attack-defense-types.h"
20 #include "player/player-skill.h"
21 #include "spell-realm/spells-song.h"
22 #include "system/floor-type-definition.h"
23 #include "system/player-type-definition.h"
24 #include "timed-effect/player-cut.h"
25 #include "timed-effect/player-stun.h"
26 #include "timed-effect/timed-effects.h"
27 #include "world/world.h"
28
29 /*!
30  * @brief セーブデータから領域情報を読み込む / Read player realms
31  * @param player_ptr プレイヤーへの参照ポインタ
32  */
33 static void rd_realms(player_type *player_ptr)
34 {
35     byte tmp8u;
36
37     rd_byte(&tmp8u);
38     if (player_ptr->pclass == PlayerClassType::ELEMENTALIST)
39         player_ptr->element = (int16_t)tmp8u;
40     else
41         player_ptr->realm1 = (int16_t)tmp8u;
42
43     rd_byte(&tmp8u);
44     player_ptr->realm2 = (int16_t)tmp8u;
45     if (player_ptr->realm2 == 255)
46         player_ptr->realm2 = 0;
47 }
48
49 /*!
50  * @brief セーブデータからプレイヤー基本情報を読み込む / Read player's basic info
51  * @param player_ptr プレイヤーへの参照ポインタ
52  */
53 void rd_base_info(player_type *player_ptr)
54 {
55     rd_string(player_ptr->name, sizeof(player_ptr->name));
56     rd_string(player_ptr->died_from, sizeof(player_ptr->died_from));
57     if (!h_older_than(1, 7, 0, 1)) {
58         char buf[1024];
59         rd_string(buf, sizeof buf);
60         if (buf[0])
61             player_ptr->last_message = string_make(buf);
62     }
63
64     load_quick_start();
65     const int max_history_lines = 4;
66     for (int i = 0; i < max_history_lines; i++)
67         rd_string(player_ptr->history[i], sizeof(player_ptr->history[i]));
68
69     byte tmp8u;
70     rd_byte(&tmp8u);
71     player_ptr->prace = (PlayerRaceType)tmp8u;
72
73     rd_byte(&tmp8u);
74     player_ptr->pclass = (PlayerClassType)tmp8u;
75
76     rd_byte(&tmp8u);
77     player_ptr->ppersonality = (player_personality_type)tmp8u;
78
79     rd_byte(&tmp8u);
80     player_ptr->psex = i2enum<player_sex>(tmp8u);
81
82     rd_realms(player_ptr);
83
84     rd_byte(&tmp8u);
85     if (h_older_than(0, 4, 4))
86         set_zangband_realm(player_ptr);
87
88     rd_byte(&tmp8u);
89     player_ptr->hitdie = (DICE_SID)tmp8u;
90     rd_u16b(&player_ptr->expfact);
91
92     rd_s16b(&player_ptr->age);
93     rd_s16b(&player_ptr->ht);
94     rd_s16b(&player_ptr->wt);
95 }
96
97 void rd_experience(player_type *player_ptr)
98 {
99     rd_s32b(&player_ptr->max_exp);
100     if (h_older_than(1, 5, 4, 1))
101         player_ptr->max_max_exp = player_ptr->max_exp;
102     else
103         rd_s32b(&player_ptr->max_max_exp);
104
105     rd_s32b(&player_ptr->exp);
106     if (h_older_than(1, 7, 0, 3))
107         set_exp_frac_old(player_ptr);
108     else
109         rd_u32b(&player_ptr->exp_frac);
110
111     rd_s16b(&player_ptr->lev);
112     for (int i = 0; i < 64; i++)
113         rd_s16b(&player_ptr->spell_exp[i]);
114
115     if ((player_ptr->pclass == PlayerClassType::SORCERER) && h_older_than(0, 4, 2))
116         for (int i = 0; i < 64; i++)
117             player_ptr->spell_exp[i] = SPELL_EXP_MASTER;
118
119     const int max_weapon_exp_size = h_older_than(0, 3, 6) ? 60 : 64;
120     for (int i = 0; i < 5; i++)
121         for (int j = 0; j < max_weapon_exp_size; j++)
122             rd_s16b(&player_ptr->weapon_exp[i][j]);
123
124     for (int i = 0; i < MAX_SKILLS; i++)
125         rd_s16b(&player_ptr->skill_exp[i]);
126 }
127
128 void rd_skills(player_type *player_ptr)
129 {
130     if (h_older_than(0, 4, 1))
131         set_zangband_skill(player_ptr);
132
133     PlayerClass(player_ptr).init_specific_data();
134     std::visit(PlayerClassSpecificDataLoader(), player_ptr->class_specific_data);
135
136     if (music_singing_any(player_ptr))
137         player_ptr->action = ACTION_SING;
138 }
139
140 static void set_race(player_type *player_ptr)
141 {
142     byte tmp8u;
143     rd_byte(&tmp8u);
144     player_ptr->start_race = (PlayerRaceType)tmp8u;
145     int32_t tmp32s;
146     rd_s32b(&tmp32s);
147     player_ptr->old_race1 = (BIT_FLAGS)tmp32s;
148     rd_s32b(&tmp32s);
149     player_ptr->old_race2 = (BIT_FLAGS)tmp32s;
150     rd_s16b(&player_ptr->old_realm);
151 }
152
153 void rd_race(player_type *player_ptr)
154 {
155     if (h_older_than(1, 0, 7)) {
156         set_zangband_race(player_ptr);
157         return;
158     }
159
160     set_race(player_ptr);
161 }
162
163 void rd_bounty_uniques(player_type *player_ptr)
164 {
165     if (h_older_than(0, 0, 3)) {
166         set_zangband_bounty_uniques(player_ptr);
167         return;
168     }
169
170     for (int i = 0; i < MAX_BOUNTY; i++)
171         rd_s16b(&w_ptr->bounty_r_idx[i]);
172 }
173
174 /*!
175  * @brief 腕力などの基本ステータス情報を読み込む
176  * @param player_ptr プレイヤーへの参照ポインタ
177  */
178 static void rd_base_status(player_type *player_ptr)
179 {
180     for (int i = 0; i < A_MAX; i++)
181         rd_s16b(&player_ptr->stat_max[i]);
182
183     for (int i = 0; i < A_MAX; i++)
184         rd_s16b(&player_ptr->stat_max_max[i]);
185
186     for (int i = 0; i < A_MAX; i++)
187         rd_s16b(&player_ptr->stat_cur[i]);
188 }
189
190 static void set_imitation(player_type *player_ptr)
191 {
192     if (h_older_than(0, 0, 1)) {
193         return;
194     }
195
196     if (h_older_than(0, 2, 3)) {
197         int16_t tmp16s;
198         const int OLD_MAX_MANE = 22;
199         for (int i = 0; i < OLD_MAX_MANE; i++) {
200             rd_s16b(&tmp16s);
201             rd_s16b(&tmp16s);
202         }
203
204         rd_s16b(&tmp16s);
205         return;
206     }
207
208     if (loading_savefile_version_is_older_than(9)) {
209         auto mane_data = PlayerClass(player_ptr).get_specific_data<mane_data_type>();
210         if (!mane_data) {
211             // ものまね師でない場合に読み捨てるためのダミーデータ領域
212             mane_data = std::make_shared<mane_data_type>();
213         }
214
215         for (int i = 0; i < MAX_MANE; ++i) {
216             int16_t spell, damage;
217             rd_s16b(&spell);
218             rd_s16b(&damage);
219             mane_data->mane_list.push_back({ i2enum<RF_ABILITY>(spell), damage });
220         }
221         int16_t count;
222         rd_s16b(&count);
223         mane_data->mane_list.resize(count);
224     }
225 }
226
227 static void rd_phase_out(player_type *player_ptr)
228 {
229     int16_t tmp16s;
230     rd_s16b(&tmp16s);
231     player_ptr->current_floor_ptr->inside_arena = (bool)tmp16s;
232     rd_s16b(&player_ptr->current_floor_ptr->inside_quest);
233     if (h_older_than(0, 3, 5))
234         player_ptr->phase_out = false;
235     else {
236         rd_s16b(&tmp16s);
237         player_ptr->phase_out = (bool)tmp16s;
238     }
239 }
240
241 static void rd_arena(player_type *player_ptr)
242 {
243     if (h_older_than(0, 0, 3))
244         update_gambling_monsters(player_ptr);
245     else
246         set_gambling_monsters();
247
248     rd_s16b(&player_ptr->town_num);
249     rd_s16b(&player_ptr->arena_number);
250     if (h_older_than(1, 5, 0, 1))
251         if (player_ptr->arena_number >= 99)
252             player_ptr->arena_number = ARENA_DEFEATED_OLD_VER;
253
254     rd_phase_out(player_ptr);
255     byte tmp8u;
256     rd_byte(&player_ptr->exit_bldg);
257     rd_byte(&tmp8u);
258
259     int16_t tmp16s;
260     rd_s16b(&tmp16s);
261     player_ptr->oldpx = (POSITION)tmp16s;
262     rd_s16b(&tmp16s);
263     player_ptr->oldpy = (POSITION)tmp16s;
264     if (h_older_than(0, 3, 13) && !is_in_dungeon(player_ptr) && !player_ptr->current_floor_ptr->inside_arena) {
265         player_ptr->oldpy = 33;
266         player_ptr->oldpx = 131;
267     }
268 }
269
270 /*!
271  * @brief プレイヤーの最大HP/現在HPを読み込む
272  * @param player_ptr プレイヤーへの参照ポインタ
273  */
274 static void rd_hp(player_type *player_ptr)
275 {
276     if (h_older_than(1, 7, 0, 3)) {
277         set_hp_old(player_ptr);
278         return;
279     }
280
281     rd_s32b(&player_ptr->mhp);
282     rd_s32b(&player_ptr->chp);
283     rd_u32b(&player_ptr->chp_frac);
284 }
285
286 /*!
287  * @brief プレイヤーの最大MP/現在MPを読み込む
288  * @param player_ptr プレイヤーへの参照ポインタ
289  */
290 static void rd_mana(player_type *player_ptr)
291 {
292     if (h_older_than(1, 7, 0, 3)) {
293         set_mana_old(player_ptr);
294         return;
295     }
296
297     rd_s32b(&player_ptr->msp);
298     rd_s32b(&player_ptr->csp);
299     rd_u32b(&player_ptr->csp_frac);
300 }
301
302 /*!
303  * @brief プレイヤーのバッドステータス (と空腹)を読み込む
304  * @param player_ptr プレイヤーへの参照ポインタ
305  */
306 static void rd_bad_status(player_type *player_ptr)
307 {
308     strip_bytes(2); /* Old "rest" */
309     rd_s16b(&player_ptr->blind);
310     rd_s16b(&player_ptr->paralyzed);
311     rd_s16b(&player_ptr->confused);
312     rd_s16b(&player_ptr->food);
313     strip_bytes(4); /* Old "food_digested" / "protection" */
314 }
315
316 static void rd_energy(player_type *player_ptr)
317 {
318     rd_s16b(&player_ptr->energy_need);
319     if (h_older_than(1, 0, 13))
320         player_ptr->energy_need = 100 - player_ptr->energy_need;
321
322     if (h_older_than(2, 1, 2, 0))
323         player_ptr->enchant_energy_need = 0;
324     else
325         rd_s16b(&player_ptr->enchant_energy_need);
326 }
327
328 /*!
329  * @brief プレイヤーのグッド/バッドステータスを読み込む
330  * @param player_ptr プレイヤーへの参照ポインタ
331  * @todo 明らかに関数名がビッグワードだが他に思いつかなかった
332  */
333 static void rd_status(player_type *player_ptr)
334 {
335     int16_t tmp16s;
336     rd_s16b(&player_ptr->fast);
337     rd_s16b(&player_ptr->slow);
338     rd_s16b(&player_ptr->afraid);
339     rd_s16b(&tmp16s);
340     player_ptr->effects()->cut()->set(tmp16s);
341     rd_s16b(&tmp16s);
342     player_ptr->effects()->stun()->set(tmp16s);
343     rd_s16b(&player_ptr->poisoned);
344     rd_s16b(&player_ptr->hallucinated);
345     rd_s16b(&player_ptr->protevil);
346     rd_s16b(&player_ptr->invuln);
347     if (h_older_than(0, 0, 0))
348         player_ptr->ult_res = 0;
349     else
350         rd_s16b(&player_ptr->ult_res);
351 }
352
353 static void rd_tsuyoshi(player_type *player_ptr)
354 {
355     if (h_older_than(0, 0, 2))
356         player_ptr->tsuyoshi = 0;
357     else
358         rd_s16b(&player_ptr->tsuyoshi);
359 }
360
361 static void set_timed_effects(player_type *player_ptr)
362 {
363     rd_s16b(&player_ptr->tim_esp);
364     rd_s16b(&player_ptr->wraith_form);
365     rd_s16b(&player_ptr->resist_magic);
366     rd_s16b(&player_ptr->tim_regen);
367     rd_s16b(&player_ptr->tim_pass_wall);
368     rd_s16b(&player_ptr->tim_stealth);
369     rd_s16b(&player_ptr->tim_levitation);
370     rd_s16b(&player_ptr->tim_sh_touki);
371     rd_s16b(&player_ptr->lightspeed);
372     rd_s16b(&player_ptr->tsubureru);
373     if (h_older_than(0, 4, 7))
374         player_ptr->magicdef = 0;
375     else
376         rd_s16b(&player_ptr->magicdef);
377
378     rd_s16b(&player_ptr->tim_res_nether);
379     if (h_older_than(0, 4, 11))
380         set_zangband_mimic(player_ptr);
381     else {
382         rd_s16b(&player_ptr->tim_res_time);
383
384         byte tmp8u;
385         rd_byte(&tmp8u);
386         player_ptr->mimic_form = (IDX)tmp8u;
387         rd_s16b(&player_ptr->tim_mimic);
388         rd_s16b(&player_ptr->tim_sh_fire);
389     }
390
391     if (h_older_than(1, 0, 99))
392         set_zangband_holy_aura(player_ptr);
393     else {
394         rd_s16b(&player_ptr->tim_sh_holy);
395         rd_s16b(&player_ptr->tim_eyeeye);
396     }
397
398     if (h_older_than(1, 0, 3))
399         set_zangband_reflection(player_ptr);
400     else {
401         rd_s16b(&player_ptr->tim_reflect);
402         rd_s16b(&player_ptr->multishadow);
403         rd_s16b(&player_ptr->dustrobe);
404     }
405 }
406
407 static void set_mutations(player_type *player_ptr)
408 {
409     if (loading_savefile_version_is_older_than(2)) {
410         for (int i = 0; i < 3; i++) {
411             uint32_t tmp32u;
412             rd_u32b(&tmp32u);
413             migrate_bitflag_to_flaggroup(player_ptr->muta, tmp32u, i * 32);
414         }
415     } else {
416         rd_FlagGroup(player_ptr->muta, rd_byte);
417     }
418 }
419
420 static void set_virtues(player_type *player_ptr)
421 {
422     for (int i = 0; i < 8; i++)
423         rd_s16b(&player_ptr->virtues[i]);
424
425     for (int i = 0; i < 8; i++)
426         rd_s16b(&player_ptr->vir_types[i]);
427 }
428
429 /*!
430  * @brief 各種時限効果を読み込む
431  * @param player_ptr プレイヤーへの参照ポインタ
432  */
433 static void rd_timed_effects(player_type *player_ptr)
434 {
435     set_timed_effects(player_ptr);
436     rd_s16b(&player_ptr->chaos_patron);
437     set_mutations(player_ptr);
438     set_virtues(player_ptr);
439 }
440
441 static void rd_player_status(player_type *player_ptr)
442 {
443     rd_base_status(player_ptr);
444     strip_bytes(24);
445     rd_s32b(&player_ptr->au);
446     rd_experience(player_ptr);
447     rd_skills(player_ptr);
448     rd_race(player_ptr);
449     set_imitation(player_ptr);
450     rd_bounty_uniques(player_ptr);
451     rd_arena(player_ptr);
452     rd_dummy1();
453     rd_hp(player_ptr);
454     rd_mana(player_ptr);
455     rd_s16b(&player_ptr->max_plv);
456     rd_dungeons(player_ptr);
457     strip_bytes(8);
458     rd_s16b(&player_ptr->sc);
459     if (loading_savefile_version_is_older_than(9)) {
460         auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
461         if (sniper_data) {
462             rd_s16b(&sniper_data->concent);
463         } else {
464             // 職業がスナイパーではないので読み捨てる
465             int16_t tmp16s;
466             rd_s16b(&tmp16s);
467         }
468     }
469     rd_bad_status(player_ptr);
470     rd_energy(player_ptr);
471     rd_status(player_ptr);
472     rd_s16b(&player_ptr->hero);
473     rd_s16b(&player_ptr->shero);
474     rd_s16b(&player_ptr->shield);
475     rd_s16b(&player_ptr->blessed);
476     rd_s16b(&player_ptr->tim_invis);
477     rd_s16b(&player_ptr->word_recall);
478     rd_alter_reality(player_ptr);
479     rd_s16b(&player_ptr->see_infra);
480     rd_s16b(&player_ptr->tim_infra);
481     rd_s16b(&player_ptr->oppose_fire);
482     rd_s16b(&player_ptr->oppose_cold);
483     rd_s16b(&player_ptr->oppose_acid);
484     rd_s16b(&player_ptr->oppose_elec);
485     rd_s16b(&player_ptr->oppose_pois);
486     rd_tsuyoshi(player_ptr);
487     rd_timed_effects(player_ptr);
488     player_ptr->mutant_regenerate_mod = calc_mutant_regenerate_mod(player_ptr);
489 }
490
491 void rd_player_info(player_type *player_ptr)
492 {
493     rd_player_status(player_ptr);
494     rd_special_attack(player_ptr);
495     rd_special_action(player_ptr);
496     rd_special_defense(player_ptr);
497     rd_byte(&player_ptr->knowledge);
498     rd_autopick(player_ptr);
499     rd_action(player_ptr);
500 }