1 #include "birth/birth-stat.h"
2 #include "birth/auto-roller.h"
3 #include "core/player-redraw-types.h"
4 #include "player-base/player-class.h"
5 #include "player-base/player-race.h"
6 #include "player-info/class-info.h"
7 #include "player-info/race-info.h"
8 #include "player-info/race-types.h"
9 #include "player/player-personality-types.h"
10 #include "player/player-personality.h"
11 #include "player/player-skill.h"
12 #include "spell/spells-status.h"
13 #include "sv-definition/sv-weapon-types.h"
14 #include "system/player-type-definition.h"
16 /*! オートロール能力値の乱数分布 / emulate 5 + 1d3 + 1d4 + 1d5 by randint0(60) */
17 BASE_STATUS rand3_4_5[60] = {
18 8, 9, 9, 9, 10, 10, 10, 10, 10, 10, /*00-09*/
19 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, /*10-19*/
20 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /*20-29*/
21 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /*30-49*/
22 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, /*40-49*/
23 15, 15, 15, 15, 15, 15, 16, 16, 16, 17 /*50-59*/
27 * @brief プレイヤーの能力値表現に基づいて加減算を行う。
29 * @param amount 加減算する値
32 int adjust_stat(int value, int amount)
35 for (int i = 0; i < (0 - amount); i++) {
36 if (value >= 18 + 10) {
38 } else if (value > 18) {
40 } else if (value > 3) {
44 } else if (amount > 0) {
45 for (int i = 0; i < amount; i++) {
58 * @brief プレイヤーの能力値を一通りロールする。 / Roll for a characters stats
59 * @param player_ptr プレイヤーへの参照ポインタ
61 * calc_bonuses()による、独立ステータスからの副次ステータス算出も行っている。
62 * For efficiency, we include a chunk of "calc_bonuses()".\n
64 void get_stats(PlayerType *player_ptr)
68 for (int i = 0; i < 2; i++) {
69 int32_t tmp = randint0(60 * 60 * 60);
72 for (int j = 0; j < 3; j++) {
75 /* Extract 5 + 1d3 + 1d4 + 1d5 */
76 val = rand3_4_5[tmp % 60];
79 player_ptr->stat_cur[stat] = player_ptr->stat_max[stat] = val;
85 if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6)) {
94 uint16_t get_expfact(PlayerType *player_ptr)
96 uint16_t expfact = rp_ptr->r_exp;
98 PlayerRace pr(player_ptr);
99 if (!pr.equals(PlayerRaceType::ANDROID)) {
100 expfact += cp_ptr->c_exp;
103 auto is_race_gaining_additional_speed = pr.equals(PlayerRaceType::KLACKON) || pr.equals(PlayerRaceType::SPRITE);
104 auto is_class_gaining_additional_speed = PlayerClass(player_ptr).has_additional_speed();
105 if (is_race_gaining_additional_speed && is_class_gaining_additional_speed) {
113 * @brief その他「オートローラ中は算出の対象にしない」副次ステータスを処理する / Roll for some info that the auto-roller ignores
115 void get_extra(PlayerType *player_ptr, bool roll_hitdie)
117 player_ptr->expfact = get_expfact(player_ptr);
119 /* Reset record of race/realm changes */
120 player_ptr->start_race = player_ptr->prace;
121 player_ptr->old_race1 = 0L;
122 player_ptr->old_race2 = 0L;
123 player_ptr->old_realm = 0;
125 PlayerClass pc(player_ptr);
126 auto is_sorcerer = pc.equals(PlayerClassType::SORCERER);
127 for (int i = 0; i < 64; i++) {
129 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::MASTER);
130 } else if (pc.equals(PlayerClassType::RED_MAGE)) {
131 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::SKILLED);
133 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::UNSKILLED);
137 auto pclass = enum2i(player_ptr->pclass);
138 player_ptr->weapon_exp = s_info[pclass].w_start;
139 player_ptr->weapon_exp_max = s_info[pclass].w_max;
141 if (player_ptr->ppersonality == PERSONALITY_SEXY) {
142 auto &whip_exp = player_ptr->weapon_exp[ItemKindType::HAFTED][SV_WHIP];
143 whip_exp = std::max(whip_exp, PlayerSkill::weapon_exp_at(PlayerSkillRank::BEGINNER));
146 for (auto i : PLAYER_SKILL_KIND_TYPE_RANGE) {
147 player_ptr->skill_exp[i] = s_info[pclass].s_start[i];
150 player_ptr->hitdie = cp_ptr->c_mhp + ap_ptr->a_mhp;
151 player_ptr->hitdie += is_sorcerer ? rp_ptr->r_mhp / 2 : rp_ptr->r_mhp;
153 roll_hitdice(player_ptr, SPOP_NO_UPDATE);
156 player_ptr->mhp = player_ptr->player_hp[0];
160 * @brief プレイヤーの限界ステータスを決める。
161 * @param player_ptr プレイヤーへの参照ポインタ
162 * @details 新生の薬やステータスシャッフルでもこの関数が呼ばれる
164 void get_max_stats(PlayerType *player_ptr)
169 for (int i = 0; i < A_MAX; i++) {
170 dice[i] = randint1(7);
179 for (int i = 0; i < A_MAX; i++) {
180 BASE_STATUS max_max = 18 + 60 + dice[i] * 10;
181 player_ptr->stat_max_max[i] = max_max;
182 if (player_ptr->stat_max[i] > max_max) {
183 player_ptr->stat_max[i] = max_max;
185 if (player_ptr->stat_cur[i] > max_max) {
186 player_ptr->stat_cur[i] = max_max;
190 player_ptr->knowledge &= ~(KNOW_STAT);
191 player_ptr->redraw |= (PR_STATS);