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"
30 * @brief セーブデータから領域情報を読み込む / Read player realms
31 * @param player_ptr プレイヤーへの参照ポインタ
33 static void rd_realms(player_type *player_ptr)
38 if (player_ptr->pclass == PlayerClassType::ELEMENTALIST)
39 player_ptr->element = (int16_t)tmp8u;
41 player_ptr->realm1 = (int16_t)tmp8u;
44 player_ptr->realm2 = (int16_t)tmp8u;
45 if (player_ptr->realm2 == 255)
46 player_ptr->realm2 = 0;
50 * @brief セーブデータからプレイヤー基本情報を読み込む / Read player's basic info
51 * @param player_ptr プレイヤーへの参照ポインタ
53 void rd_base_info(player_type *player_ptr)
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)) {
59 rd_string(buf, sizeof buf);
61 player_ptr->last_message = string_make(buf);
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]));
71 player_ptr->prace = (PlayerRaceType)tmp8u;
74 player_ptr->pclass = (PlayerClassType)tmp8u;
77 player_ptr->ppersonality = (player_personality_type)tmp8u;
80 player_ptr->psex = i2enum<player_sex>(tmp8u);
82 rd_realms(player_ptr);
85 if (h_older_than(0, 4, 4))
86 set_zangband_realm(player_ptr);
89 player_ptr->hitdie = (DICE_SID)tmp8u;
90 rd_u16b(&player_ptr->expfact);
92 rd_s16b(&player_ptr->age);
93 rd_s16b(&player_ptr->ht);
94 rd_s16b(&player_ptr->wt);
97 void rd_experience(player_type *player_ptr)
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;
103 rd_s32b(&player_ptr->max_max_exp);
105 rd_s32b(&player_ptr->exp);
106 if (h_older_than(1, 7, 0, 3))
107 set_exp_frac_old(player_ptr);
109 rd_u32b(&player_ptr->exp_frac);
111 rd_s16b(&player_ptr->lev);
112 for (int i = 0; i < 64; i++)
113 rd_s16b(&player_ptr->spell_exp[i]);
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;
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]);
124 for (int i = 0; i < MAX_SKILLS; i++)
125 rd_s16b(&player_ptr->skill_exp[i]);
128 void rd_skills(player_type *player_ptr)
130 if (h_older_than(0, 4, 1))
131 set_zangband_skill(player_ptr);
133 PlayerClass(player_ptr).init_specific_data();
134 std::visit(PlayerClassSpecificDataLoader(), player_ptr->class_specific_data);
136 if (music_singing_any(player_ptr))
137 player_ptr->action = ACTION_SING;
140 static void set_race(player_type *player_ptr)
144 player_ptr->start_race = (PlayerRaceType)tmp8u;
147 player_ptr->old_race1 = (BIT_FLAGS)tmp32s;
149 player_ptr->old_race2 = (BIT_FLAGS)tmp32s;
150 rd_s16b(&player_ptr->old_realm);
153 void rd_race(player_type *player_ptr)
155 if (h_older_than(1, 0, 7)) {
156 set_zangband_race(player_ptr);
160 set_race(player_ptr);
163 void rd_bounty_uniques(player_type *player_ptr)
165 if (h_older_than(0, 0, 3)) {
166 set_zangband_bounty_uniques(player_ptr);
170 for (int i = 0; i < MAX_BOUNTY; i++)
171 rd_s16b(&w_ptr->bounty_r_idx[i]);
175 * @brief 腕力などの基本ステータス情報を読み込む
176 * @param player_ptr プレイヤーへの参照ポインタ
178 static void rd_base_status(player_type *player_ptr)
180 for (int i = 0; i < A_MAX; i++)
181 rd_s16b(&player_ptr->stat_max[i]);
183 for (int i = 0; i < A_MAX; i++)
184 rd_s16b(&player_ptr->stat_max_max[i]);
186 for (int i = 0; i < A_MAX; i++)
187 rd_s16b(&player_ptr->stat_cur[i]);
190 static void set_imitation(player_type *player_ptr)
192 if (h_older_than(0, 0, 1)) {
196 if (h_older_than(0, 2, 3)) {
198 const int OLD_MAX_MANE = 22;
199 for (int i = 0; i < OLD_MAX_MANE; i++) {
208 if (loading_savefile_version_is_older_than(9)) {
209 auto mane_data = PlayerClass(player_ptr).get_specific_data<mane_data_type>();
211 // ものまね師でない場合に読み捨てるためのダミーデータ領域
212 mane_data = std::make_shared<mane_data_type>();
215 for (int i = 0; i < MAX_MANE; ++i) {
216 int16_t spell, damage;
219 mane_data->mane_list.push_back({ i2enum<RF_ABILITY>(spell), damage });
223 mane_data->mane_list.resize(count);
227 static void rd_phase_out(player_type *player_ptr)
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;
237 player_ptr->phase_out = (bool)tmp16s;
241 static void rd_arena(player_type *player_ptr)
243 if (h_older_than(0, 0, 3))
244 update_gambling_monsters(player_ptr);
246 set_gambling_monsters();
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;
254 rd_phase_out(player_ptr);
256 rd_byte(&player_ptr->exit_bldg);
261 player_ptr->oldpx = (POSITION)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;
271 * @brief プレイヤーの最大HP/現在HPを読み込む
272 * @param player_ptr プレイヤーへの参照ポインタ
274 static void rd_hp(player_type *player_ptr)
276 if (h_older_than(1, 7, 0, 3)) {
277 set_hp_old(player_ptr);
281 rd_s32b(&player_ptr->mhp);
282 rd_s32b(&player_ptr->chp);
283 rd_u32b(&player_ptr->chp_frac);
287 * @brief プレイヤーの最大MP/現在MPを読み込む
288 * @param player_ptr プレイヤーへの参照ポインタ
290 static void rd_mana(player_type *player_ptr)
292 if (h_older_than(1, 7, 0, 3)) {
293 set_mana_old(player_ptr);
297 rd_s32b(&player_ptr->msp);
298 rd_s32b(&player_ptr->csp);
299 rd_u32b(&player_ptr->csp_frac);
303 * @brief プレイヤーのバッドステータス (と空腹)を読み込む
304 * @param player_ptr プレイヤーへの参照ポインタ
306 static void rd_bad_status(player_type *player_ptr)
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" */
316 static void rd_energy(player_type *player_ptr)
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;
322 if (h_older_than(2, 1, 2, 0))
323 player_ptr->enchant_energy_need = 0;
325 rd_s16b(&player_ptr->enchant_energy_need);
329 * @brief プレイヤーのグッド/バッドステータスを読み込む
330 * @param player_ptr プレイヤーへの参照ポインタ
331 * @todo 明らかに関数名がビッグワードだが他に思いつかなかった
333 static void rd_status(player_type *player_ptr)
336 rd_s16b(&player_ptr->fast);
337 rd_s16b(&player_ptr->slow);
338 rd_s16b(&player_ptr->afraid);
340 player_ptr->effects()->cut()->set(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;
350 rd_s16b(&player_ptr->ult_res);
353 static void rd_tsuyoshi(player_type *player_ptr)
355 if (h_older_than(0, 0, 2))
356 player_ptr->tsuyoshi = 0;
358 rd_s16b(&player_ptr->tsuyoshi);
361 static void set_timed_effects(player_type *player_ptr)
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;
376 rd_s16b(&player_ptr->magicdef);
378 rd_s16b(&player_ptr->tim_res_nether);
379 if (h_older_than(0, 4, 11))
380 set_zangband_mimic(player_ptr);
382 rd_s16b(&player_ptr->tim_res_time);
386 player_ptr->mimic_form = (IDX)tmp8u;
387 rd_s16b(&player_ptr->tim_mimic);
388 rd_s16b(&player_ptr->tim_sh_fire);
391 if (h_older_than(1, 0, 99))
392 set_zangband_holy_aura(player_ptr);
394 rd_s16b(&player_ptr->tim_sh_holy);
395 rd_s16b(&player_ptr->tim_eyeeye);
398 if (h_older_than(1, 0, 3))
399 set_zangband_reflection(player_ptr);
401 rd_s16b(&player_ptr->tim_reflect);
402 rd_s16b(&player_ptr->multishadow);
403 rd_s16b(&player_ptr->dustrobe);
407 static void set_mutations(player_type *player_ptr)
409 if (loading_savefile_version_is_older_than(2)) {
410 for (int i = 0; i < 3; i++) {
413 migrate_bitflag_to_flaggroup(player_ptr->muta, tmp32u, i * 32);
416 rd_FlagGroup(player_ptr->muta, rd_byte);
420 static void set_virtues(player_type *player_ptr)
422 for (int i = 0; i < 8; i++)
423 rd_s16b(&player_ptr->virtues[i]);
425 for (int i = 0; i < 8; i++)
426 rd_s16b(&player_ptr->vir_types[i]);
431 * @param player_ptr プレイヤーへの参照ポインタ
433 static void rd_timed_effects(player_type *player_ptr)
435 set_timed_effects(player_ptr);
436 rd_s16b(&player_ptr->chaos_patron);
437 set_mutations(player_ptr);
438 set_virtues(player_ptr);
441 static void rd_player_status(player_type *player_ptr)
443 rd_base_status(player_ptr);
445 rd_s32b(&player_ptr->au);
446 rd_experience(player_ptr);
447 rd_skills(player_ptr);
449 set_imitation(player_ptr);
450 rd_bounty_uniques(player_ptr);
451 rd_arena(player_ptr);
455 rd_s16b(&player_ptr->max_plv);
456 rd_dungeons(player_ptr);
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>();
462 rd_s16b(&sniper_data->concent);
464 // 職業がスナイパーではないので読み捨てる
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);
491 void rd_player_info(player_type *player_ptr)
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);