diff options
Diffstat (limited to 'src/skills.cc')
-rw-r--r-- | src/skills.cc | 797 |
1 files changed, 443 insertions, 354 deletions
diff --git a/src/skills.cc b/src/skills.cc index 3a14a6ce..af5e46c7 100644 --- a/src/skills.cc +++ b/src/skills.cc @@ -14,6 +14,7 @@ #include "cmd3.hpp" #include "cmd5.hpp" #include "cmd7.hpp" +#include "game.hpp" #include "gods.hpp" #include "help.hpp" #include "hooks.hpp" @@ -27,11 +28,11 @@ #include "player_race_mod.hpp" #include "player_spec.hpp" #include "player_type.hpp" +#include "skill_flag.hpp" #include "skill_type.hpp" #include "spells1.hpp" #include "spells4.hpp" #include "tables.hpp" -#include "traps.hpp" #include "util.hpp" #include "util.h" #include "variable.h" @@ -43,6 +44,7 @@ #include <boost/algorithm/string/predicate.hpp> #include <cassert> #include <cmath> +#include <fmt/format.h> #include <memory> #include <vector> #include <tuple> @@ -55,6 +57,8 @@ using boost::algorithm::iequals; */ static void increase_skill(int i, s16b *invest) { + auto &s_info = game->s_info; + s32b max_skill_overage; /* No skill points to be allocated */ @@ -70,15 +74,11 @@ static void increase_skill(int i, s16b *invest) max_skill_overage = modules[game_module_idx].skills.max_skill_overage; if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1)) { - int hgt, wid; - char buf[256]; - - sprintf(buf, - "Cannot raise a skill value above " FMTs32b " + player level.", - max_skill_overage); - - Term_get_size(&wid, &hgt); - msg_box(buf, hgt / 2, wid / 2); + msg_box_auto( + fmt::format( + "Cannot raise a skill value above {} + player level.", + max_skill_overage + )); return; } @@ -97,6 +97,8 @@ static void increase_skill(int i, s16b *invest) */ static void decrease_skill(int i, s16b *invest) { + auto &s_info = game->s_info; + /* Cannot decrease more */ if (!invest[i]) return; @@ -119,31 +121,33 @@ static void decrease_skill(int i, s16b *invest) * Given the name of a skill, returns skill index or -1 if no * such skill is found */ -s16b find_skill(cptr name) +s16b find_skill(cptr needle) { - u16b i; + auto const &s_descriptors = game->edit_data.s_descriptors; /* Scan skill list */ - for (i = 1; i < max_s_idx; i++) + for (std::size_t i = 1; i < s_descriptors.size(); i++) { - if (s_info[i].name && streq(s_info[i].name, name)) + auto const &name = s_descriptors[i].name; + if (!name.empty() && (name == needle)) { - return (i); + return i; } } /* No match found */ - return ( -1); + return -1; } -s16b find_skill_i(cptr name) + +s16b find_skill_i(cptr needle) { - u16b i; + auto const &s_descriptors = game->edit_data.s_descriptors; /* Scan skill list */ - for (i = 1; i < max_s_idx; i++) + for (std::size_t i = 1; i < s_descriptors.size(); i++) { - /* The name matches */ - if (s_info[i].name && iequals(s_info[i].name, name)) + auto const &name = s_descriptors[i].name; + if (!name.empty() && iequals(name, needle)) { return (i); } @@ -159,6 +163,8 @@ s16b find_skill_i(cptr name) */ s16b get_skill(int skill) { + auto const &s_info = game->s_info; + return (s_info[skill].value / SKILL_STEP); } @@ -169,7 +175,7 @@ s16b get_skill(int skill) */ s16b get_skill_scale(int skill, u32b scale) { - s32b temp; + auto const &s_info = game->s_info; /* * SKILL_STEP shouldn't matter here because the second parameter is @@ -181,32 +187,38 @@ s16b get_skill_scale(int skill, u32b scale) * formula given above, I verified this works the same by using a tiny * scheme program... -- pelpel */ - temp = scale * s_info[skill].value; + s32b temp = scale * s_info[skill].value; return (temp / SKILL_MAX); } -static int get_idx(int i) +static std::size_t get_idx(int i) { - for (int j = 1; j < max_s_idx; j++) + auto const &s_descriptors = game->edit_data.s_descriptors; + + for (std::size_t j = 1; j < s_descriptors.size(); j++) { - if (s_info[j].order == i) - return (j); + if (s_descriptors[j].order == i) + { + return j; + } } - return (0); + + return 0; } static bool_ is_known(int s_idx) { - int i; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; if (wizard) return TRUE; if (s_info[s_idx].value || s_info[s_idx].mod) return TRUE; - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { /* It is our child, if we don't know it we continue to search, if we know it it is enough*/ - if (s_info[i].father == s_idx) + if (s_descriptors[i].father == s_idx) { if (is_known(i)) return TRUE; @@ -217,38 +229,59 @@ static bool_ is_known(int s_idx) return FALSE; } -static void init_table_aux(int table[MAX_SKILLS][2], int *idx, int father, int lev, bool_ full) +namespace { // anonymous + +struct skill_entry { + std::size_t skill_idx; + int indent_level; +}; + +} + +static void init_table_aux(std::vector<skill_entry> *table, int father, int lev, bool_ full) { - for (int j = 1; j < max_s_idx; j++) + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + + for (std::size_t j = 1; j < s_descriptors.size(); j++) { - int i = get_idx(j); - if (s_info[i].father != father) continue; + std::size_t i = get_idx(j); + + if (s_descriptors[i].father != father) continue; if (s_info[i].hidden) continue; if (!is_known(i)) continue; - table[*idx][0] = i; - table[*idx][1] = lev; - (*idx)++; - if (s_info[i].dev || full) init_table_aux(table, idx, i, lev + 1, full); + skill_entry entry; + entry.skill_idx = i; + entry.indent_level = lev; + table->emplace_back(entry); + + if (s_info[i].dev || full) + { + init_table_aux(table, i, lev + 1, full); + } } } -static void init_table(int table[MAX_SKILLS][2], int *max, bool_ full) +static void init_table(std::vector<skill_entry> *table, bool_ full) { - *max = 0; - init_table_aux(table, max, -1, 0, full); + table->clear(); + init_table_aux(table, -1, 0, full); } -static bool_ has_child(int sel) +static bool has_child(int sel) { - int i; + auto const &s_descriptors = game->edit_data.s_descriptors; - for (i = 1; i < max_s_idx; i++) + for (std::size_t i = 1; i < s_descriptors.size(); i++) { - if ((s_info[i].father == sel) && (is_known(i))) - return (TRUE); + if ((s_descriptors[i].father == sel) && is_known(i)) + { + return true; + } } - return (FALSE); + + return false; } @@ -257,42 +290,51 @@ static bool_ has_child(int sel) */ void dump_skills(FILE *fff) { - int i, j, max = 0; - int table[MAX_SKILLS][2]; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + char buf[80]; - init_table(table, &max, TRUE); + std::vector<skill_entry> table; + table.reserve(s_descriptors.size()); + init_table(&table, TRUE); fprintf(fff, "\nSkills (points left: %d)", p_ptr->skill_points); - for (j = 0; j < max; j++) + for (auto const &entry: table) { - int z; - - i = table[j][0]; + std::size_t i = entry.skill_idx; + auto const &skill = s_info[i]; + auto const &skill_name = s_descriptors[i].name; - if ((s_info[i].value == 0) && (i != SKILL_MISC)) + if ((skill.value == 0) && (i != SKILL_MISC)) { - if (s_info[i].mod == 0) continue; + if (skill.mod == 0) + { + continue; + } } sprintf(buf, "\n"); - for (z = 0; z < table[j][1]; z++) strcat(buf, " "); + for (int z = 0; z < entry.indent_level; z++) + { + strcat(buf, " "); + } if (!has_child(i)) { - strcat(buf, format(" . %s", s_info[i].name)); + strcat(buf, format(" . %s", skill_name.c_str())); } else { - strcat(buf, format(" - %s", s_info[i].name)); + strcat(buf, format(" - %s", skill_name.c_str())); } fprintf(fff, "%-49s%s%06.3f [%05.3f]", - buf, s_info[i].value < 0 ? "-" : " ", - static_cast<double>(ABS(s_info[i].value)) / SKILL_STEP, - static_cast<double>(s_info[i].mod) / 1000); + buf, skill.value < 0 ? "-" : " ", + static_cast<double>(ABS(skill.value)) / SKILL_STEP, + static_cast<double>(skill.mod) / 1000); } fprintf(fff, "\n"); @@ -302,9 +344,12 @@ void dump_skills(FILE *fff) /* * Draw the skill tree */ -void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) +static void print_skills(std::vector<skill_entry> const &table, int sel, int start) { - int i, j; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + + int j; int wid, hgt; cptr keys; @@ -316,52 +361,73 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) display_message(0, 1, strlen(keys), TERM_WHITE, keys); c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED, format("Skill points left: %d", p_ptr->skill_points), 2, 0); - print_desc_aux(s_info[table[sel][0]].desc, 3, 0); + print_desc_aux(s_descriptors[table[sel].skill_idx].desc.c_str(), 3, 0); for (j = start; j < start + (hgt - 7); j++) { byte color = TERM_WHITE; char deb = ' ', end = ' '; - if (j >= max) break; + if (j >= static_cast<int>(table.size())) + { + break; + } + + std::size_t i = table[j].skill_idx; + auto const &name = s_descriptors[i].name; + auto const &skill = s_info[i]; - i = table[j][0]; + if ((skill.value == 0) && (i != SKILL_MISC)) + { + if (skill.mod == 0) + { + color = TERM_L_DARK; + } + else + { + color = TERM_ORANGE; + } + } + else if (skill.value == SKILL_MAX) + { + color = TERM_L_BLUE; + } - if ((s_info[i].value == 0) && (i != SKILL_MISC)) + if (skill.hidden) { - if (s_info[i].mod == 0) color = TERM_L_DARK; - else color = TERM_ORANGE; + color = TERM_L_RED; } - else if (s_info[i].value == SKILL_MAX) color = TERM_L_BLUE; - if (s_info[i].hidden) color = TERM_L_RED; + if (j == sel) { color = TERM_L_GREEN; deb = '['; end = ']'; } + if (!has_child(i)) { - c_prt(color, format("%c.%c%s", deb, end, s_info[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c.%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } - else if (s_info[i].dev) + else if (skill.dev) { - c_prt(color, format("%c-%c%s", deb, end, s_info[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c-%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } else { - c_prt(color, format("%c+%c%s", deb, end, s_info[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c+%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } + c_prt(color, format("%s%02ld.%03ld [%01d.%03d]", - s_info[i].value < 0 ? "-" : " ", - ABS(s_info[i].value) / SKILL_STEP, - ABS(s_info[i].value) % SKILL_STEP, - ABS(s_info[i].mod) / 1000, - ABS(s_info[i].mod) % 1000), + skill.value < 0 ? "-" : " ", + ABS(skill.value) / SKILL_STEP, + ABS(skill.value) % SKILL_STEP, + ABS(skill.mod) / 1000, + ABS(skill.mod) % 1000), j + 7 - start, 60); } } @@ -371,6 +437,8 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) */ void recalc_skills(bool_ init) { + auto const &s_info = game->s_info; + static int thaum_level = 0; /* TODO: This should be a hook in ToME's lua */ @@ -380,16 +448,19 @@ void recalc_skills(bool_ init) } else { + auto const &random_spells = p_ptr->random_spells; + int thaum_gain = 0; - /* Gain thaum spells */ - while (thaum_level < get_skill_scale(SKILL_THAUMATURGY, 100)) + /* Gain thaum spells while there's more to be gained */ + while ((thaum_level < get_skill_scale(SKILL_THAUMATURGY, 100)) && + (random_spells.size() < MAX_SPELLS)) { - if (spell_num == MAX_SPELLS) break; thaum_level++; generate_spell((thaum_level + 1) / 2); thaum_gain++; } + if (thaum_gain) { if (thaum_gain == 1) @@ -420,49 +491,64 @@ void recalc_skills(bool_ init) /* * Recalc the skill value */ -static void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s32b *bonus) +static void recalc_skills_theory( + std::vector<s16b> &invest, + std::vector<s32b> const &base_val, + std::vector<s32b> const &base_mod, + std::vector<s32b> const &bonus) { - int i, j; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; /* First we assign the normal points */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { /* Calc the base */ s_info[i].value = base_val[i] + (base_mod[i] * invest[i]) + bonus[i]; /* It cannot exceed SKILL_MAX */ - if (s_info[i].value > SKILL_MAX) s_info[i].value = SKILL_MAX; + if (s_info[i].value > SKILL_MAX) + { + s_info[i].value = SKILL_MAX; + } } /* Then we modify related skills */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - for (j = 1; j < max_s_idx; j++) - { - /* Ignore self */ - if (j == i) continue; + auto const &s_descriptor = s_descriptors[i]; - /* Exclusive skills */ - if ((s_info[i].action[j] == SKILL_EXCLUSIVE) && invest[i]) + // Process all exlusions + if (invest[i]) + { + for (auto exclude_si: s_descriptor.excludes) { - /* Turn it off */ - p_ptr->skill_points += invest[j]; - invest[j] = 0; - s_info[j].value = 0; + // Give back skill points invested during this "session" + p_ptr->skill_points += invest[exclude_si]; + invest[exclude_si] = 0; + + // Turn it off + s_info[exclude_si].value = 0; } + } - /* Non-exclusive skills */ - else if (s_info[i].action[j]) - { - /* Increase / decrease with a % */ - s32b val = s_info[j].value + (invest[i] * s_info[j].mod * s_info[i].action[j] / 100); + // Add any bonuses + for (auto const &increase: s_descriptor.increases) + { + auto increase_si = std::get<0>(increase); + auto increase_pct = std::get<1>(increase); - /* It cannot exceed SKILL_MAX */ - if (val > SKILL_MAX) val = SKILL_MAX; + /* Increase/decrease by percentage */ + s32b val = s_info[increase_si].value + (invest[i] * s_info[increase_si].mod * increase_pct / 100); - /* Save the modified value */ - s_info[j].value = val; + /* It cannot exceed SKILL_MAX */ + if (val > SKILL_MAX) + { + val = SKILL_MAX; } + + /* Save the modified value */ + s_info[increase_si].value = val; } } } @@ -472,10 +558,11 @@ static void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s */ void do_cmd_skill() { - int sel = 0, start = 0, max; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; + + int sel = 0, start = 0; char c; - int table[MAX_SKILLS][2]; - int i; int wid, hgt; s16b skill_points_save; @@ -484,41 +571,38 @@ void do_cmd_skill() /* Save the screen */ screen_save(); - /* Allocate arrays to save skill values */ - std::unique_ptr<s32b[]> skill_values_save(new s32b[MAX_SKILLS]); - std::unique_ptr<s32b[]> skill_mods_save(new s32b[MAX_SKILLS]); - std::unique_ptr<s16b[]> skill_rates_save(new s16b[MAX_SKILLS]); - std::unique_ptr<s16b[]> skill_invest(new s16b[MAX_SKILLS]); - std::unique_ptr<s32b[]> skill_bonus(new s32b[MAX_SKILLS]); + /* Allocate arrays to save skill values and track assigned points */ + std::vector<s32b> skill_values_save; skill_values_save.resize(s_descriptors.size(), 0); + std::vector<s32b> skill_mods_save; skill_mods_save.resize(s_descriptors.size(), 0); + std::vector<s16b> skill_invest; skill_invest.resize(s_descriptors.size(), 0); + std::vector<s32b> skill_bonus; skill_bonus.resize(s_descriptors.size(), 0); /* Save skill points */ skill_points_save = p_ptr->skill_points; /* Save skill values */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - skill_type *s_ptr = &s_info[i]; - + auto s_ptr = &s_info[i]; skill_values_save[i] = s_ptr->value; skill_mods_save[i] = s_ptr->mod; - skill_rates_save[i] = s_ptr->rate; - skill_invest[i] = 0; - skill_bonus[i] = 0; } /* Clear the screen */ Term_clear(); /* Initialise the skill list */ - init_table(table, &max, FALSE); + std::vector<skill_entry> table; + table.reserve(s_descriptors.size()); + init_table(&table, FALSE); while (TRUE) { Term_get_size(&wid, &hgt); /* Display list of skills */ - recalc_skills_theory(skill_invest.get(), skill_values_save.get(), skill_mods_save.get(), skill_bonus.get()); - print_skills(table, max, sel, start); + recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus); + print_skills(table, sel, start); /* Wait for user input */ c = inkey(); @@ -529,16 +613,21 @@ void do_cmd_skill() /* Expand / collapse list of skills */ else if (c == '\r') { - if (s_info[table[sel][0]].dev) s_info[table[sel][0]].dev = FALSE; - else s_info[table[sel][0]].dev = TRUE; - init_table(table, &max, FALSE); + // Toggle the selected skill + s_info[table[sel].skill_idx].dev = !s_info[table[sel].skill_idx].dev; + // Re-populate table + init_table(&table, FALSE); } /* Next page */ else if (c == 'n') { sel += (hgt - 7); - if (sel >= max) sel = max - 1; + + if (sel >= static_cast<int>(table.size())) + { + sel = table.size() - 1; + } } /* Previous page */ @@ -563,31 +652,31 @@ void do_cmd_skill() if (dir == 8) sel--; /* Miscellaneous skills cannot be increased/decreased as a group */ - if ((sel >= 0) && (sel < max) && table[sel][0] == SKILL_MISC) continue; + if ((sel >= 0) && (sel < static_cast<int>(table.size())) && table[sel].skill_idx == SKILL_MISC) continue; /* Increase the current skill */ - if (dir == 6) increase_skill(table[sel][0], skill_invest.get()); + if (dir == 6) increase_skill(table[sel].skill_idx, skill_invest.data()); /* Decrease the current skill */ - if (dir == 4) decrease_skill(table[sel][0], skill_invest.get()); + if (dir == 4) decrease_skill(table[sel].skill_idx, skill_invest.data()); /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ /* Increase the skill */ - if (wizard && (c == '+')) skill_bonus[table[sel][0]] += SKILL_STEP; + if (wizard && (c == '+')) skill_bonus[table[sel].skill_idx] += SKILL_STEP; /* Decrease the skill */ - if (wizard && (c == '-')) skill_bonus[table[sel][0]] -= SKILL_STEP; + if (wizard && (c == '-')) skill_bonus[table[sel].skill_idx] -= SKILL_STEP; /* Contextual help */ if (c == '?') { - help_skill(s_info[table[sel][0]].name); + help_skill(s_descriptors[table[sel].skill_idx].name); } /* Handle boundaries and scrolling */ - if (sel < 0) sel = max - 1; - if (sel >= max) sel = 0; + if (sel < 0) sel = table.size() - 1; + if (sel >= static_cast<int>(table.size())) sel = 0; if (sel < start) start = sel; if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1; } @@ -601,7 +690,7 @@ void do_cmd_skill() flush(); /* Ask we can commit the change */ - if (msg_box("Save and use these skill values? (y/n)", hgt / 2, wid / 2) != 'y') + if (msg_box_auto("Save and use these skill values? (y/n)") != 'y') { /* User declines -- restore the skill values before exiting */ @@ -609,13 +698,11 @@ void do_cmd_skill() p_ptr->skill_points = skill_points_save; /* Restore skill values */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - skill_type *s_ptr = &s_info[i]; - + auto s_ptr = &s_info[i]; s_ptr->value = skill_values_save[i]; s_ptr->mod = skill_mods_save[i]; - s_ptr->rate = skill_rates_save[i]; } } } @@ -665,9 +752,11 @@ cptr get_melee_name() s16b get_melee_skills() { - int i, j = 0; + auto const &s_info = game->s_info; - for (i = 0; i < MAX_MELEE; i++) + int j = 0; + + for (std::size_t i = 0; i < MAX_MELEE; i++) { if ((s_info[melee_skills[i]].value > 0) && (!s_info[melee_skills[i]].hidden)) { @@ -778,7 +867,7 @@ void select_default_melee() /* * Print a batch of skills. */ -static void print_skill_batch(const std::vector<std::tuple<cptr, int>> &p, int start) +static void print_skill_batch(const std::vector<std::tuple<std::string, int>> &p, int start) { char buff[80]; int j = 0; @@ -794,7 +883,7 @@ static void print_skill_batch(const std::vector<std::tuple<cptr, int>> &p, int s sprintf(buff, " %c - %d) %-30s", I2A(j), std::get<1>(p[i]), - std::get<0>(p[i])); + std::get<0>(p[i]).c_str()); prt(buff, 2 + j, 20); j++; @@ -805,11 +894,15 @@ static void print_skill_batch(const std::vector<std::tuple<cptr, int>> &p, int s static int do_cmd_activate_skill_aux() { + auto const &ab_info = game->edit_data.ab_info; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + char which; int start = 0; int ret; - std::vector<std::tuple<cptr,int>> p; + std::vector<std::tuple<std::string,int>> p; /* More than 1 melee skill ? */ if (get_melee_skills() > 1) @@ -817,16 +910,16 @@ static int do_cmd_activate_skill_aux() p.push_back(std::make_tuple("Change melee mode", 0)); } - for (size_t i = 1; i < max_s_idx; i++) + for (size_t i = 1; i < s_descriptors.size(); i++) { - if (s_info[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN))) + if (s_descriptors[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN))) { bool_ next = FALSE; /* Already got it ? */ for (size_t j = 0; j < p.size(); j++) { - if (s_info[i].action_mkey == std::get<1>(p[j])) + if (s_descriptors[i].action_mkey == std::get<1>(p[j])) { next = TRUE; break; @@ -834,14 +927,14 @@ static int do_cmd_activate_skill_aux() } if (next) continue; - p.push_back(std::make_tuple(s_info[i].action_desc, - s_info[i].action_mkey)); + p.push_back(std::make_tuple(s_descriptors[i].action_desc, + s_descriptors[i].action_mkey)); } } - for (size_t i = 0; i < max_ab_idx; i++) + for (size_t i = 0; i < ab_info.size(); i++) { - if (ab_info[i].action_mkey && ab_info[i].acquired) + if (ab_info[i].action_mkey && p_ptr->has_ability(i)) { bool_ next = FALSE; @@ -912,8 +1005,10 @@ static int do_cmd_activate_skill_aux() size_t i = 0; for (; i < p.size(); i++) { - if (!strcmp(buf, std::get<0>(p[i]))) + if (std::get<0>(p[i]) == buf) + { break; + } } if (i < p.size()) @@ -949,6 +1044,10 @@ static int do_cmd_activate_skill_aux() /* Ask & execute a skill */ void do_cmd_activate_skill() { + auto const &ab_info = game->edit_data.ab_info; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + int x_idx; bool_ push = TRUE; @@ -957,26 +1056,34 @@ void do_cmd_activate_skill() { push = FALSE; } - else if (!command_arg) x_idx = do_cmd_activate_skill_aux(); + else if (!command_arg) + { + x_idx = do_cmd_activate_skill_aux(); + } else { - int i, j; - x_idx = command_arg; /* Check validity */ - for (i = 1; i < max_s_idx; i++) + std::size_t i; + for (i = 1; i < s_descriptors.size(); i++) { - if (s_info[i].value && (s_info[i].action_mkey == x_idx)) + if (s_info[i].value && (s_descriptors[i].action_mkey == x_idx)) + { break; + } } - for (j = 0; j < max_ab_idx; j++) + + std::size_t j; + for (j = 0; j < ab_info.size(); j++) { - if (ab_info[j].acquired && (ab_info[j].action_mkey == x_idx)) + if (p_ptr->has_ability(j) && (ab_info[j].action_mkey == x_idx)) + { break; + } } - if ((j == max_ab_idx) && (i == max_s_idx)) + if ((j == ab_info.size()) && (i == s_descriptors.size())) { msg_print("Uh?"); return; @@ -1017,9 +1124,6 @@ void do_cmd_activate_skill() case MKEY_POWER_MAGE: do_cmd_powermage(); break; - case MKEY_RUNE: - do_cmd_runecrafter(); - break; case MKEY_FORGING: do_cmd_archer(); break; @@ -1035,9 +1139,6 @@ void do_cmd_activate_skill() case MKEY_SYMBIOTIC: do_cmd_symbiotic(); break; - case MKEY_TRAP: - do_cmd_set_trap(); - break; case MKEY_STEAL: do_cmd_steal(); break; @@ -1114,7 +1215,7 @@ void do_cmd_activate_skill() int dir, dy, dx, targetx, targety, max_blows, flags; o_ptr = get_object(INVEN_WIELD); - if (o_ptr->tval == TV_POLEARM) + if (o_ptr->tval != TV_POLEARM) { msg_print("You will need a long polearm for this!"); return; @@ -1179,76 +1280,47 @@ bool_ forbid_non_blessed() /* - * Gets the base value of a skill, given a race/class/... + * Augment skill value/modifier with the given skill_modifiers */ -void compute_skills(s32b *v, s32b *m, int i) +static void augment_skills(s32b *v, s32b *m, std::vector<skill_modifier> const &modifiers, std::size_t i) { - s32b value, mod; - - /***** general skills *****/ - - /* If the skill correspond to the magic school lets pump them a bit */ - value = gen_skill_base[i]; - mod = gen_skill_mod[i]; - - *v = modify_aux(*v, - value, gen_skill_basem[i]); - *m = modify_aux(*m, - mod, gen_skill_modm[i]); - - /***** race skills *****/ - - value = rp_ptr->skill_base[i]; - mod = rp_ptr->skill_mod[i]; - - *v = modify_aux(*v, - value, rp_ptr->skill_basem[i]); - *m = modify_aux(*m, - mod, rp_ptr->skill_modm[i]); - - /***** race mod skills *****/ - - value = rmp_ptr->skill_base[i]; - mod = rmp_ptr->skill_mod[i]; - - *v = modify_aux(*v, - value, rmp_ptr->skill_basem[i]); - *m = modify_aux(*m, - mod, rmp_ptr->skill_modm[i]); - - /***** class skills *****/ - - value = cp_ptr->skill_base[i]; - mod = cp_ptr->skill_mod[i]; - - *v = modify_aux(*v, - value, cp_ptr->skill_basem[i]); - *m = modify_aux(*m, - mod, cp_ptr->skill_modm[i]); + if (i < modifiers.size()) // Ignore if the skill has no modifiers. + { + auto const &s = modifiers[i]; + *v = modify_aux(*v, s.base, s.basem); + *m = modify_aux(*m, s.mod, s.modm); + } +} - /***** class spec skills *****/ - value = spp_ptr->skill_base[i]; - mod = spp_ptr->skill_mod[i]; +/* + * Gets the base value of a skill, given a race/class/... + */ +void compute_skills(s32b *v, s32b *m, std::size_t i) +{ + auto const &gen_skill = game->edit_data.gen_skill; - *v = modify_aux(*v, - value, spp_ptr->skill_basem[i]); - *m = modify_aux(*m, - mod, spp_ptr->skill_modm[i]); + augment_skills(v, m, gen_skill.modifiers, i); + augment_skills(v, m, rp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, rmp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, cp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, spp_ptr->skill_modifiers.modifiers, i); } /* * Initialize a skill with given values */ -void init_skill(s32b value, s32b mod, int i) +void init_skill(s32b value, s32b mod, std::size_t i) { + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; + s_info[i].value = value; s_info[i].mod = mod; - - if (s_info[i].flags1 & SKF1_HIDDEN) - s_info[i].hidden = TRUE; - else - s_info[i].hidden = FALSE; + s_info[i].hidden = (s_descriptors[i].flags & SKF_HIDDEN) + ? true + : false + ; } /* @@ -1310,39 +1382,42 @@ static std::vector<size_t> wrs(const std::vector<s32b> &unscaled_weights) void do_get_new_skill() { - std::vector<std::string> items; - int skl[LOST_SWORD_NSKILLS]; - s32b val[LOST_SWORD_NSKILLS], mod[LOST_SWORD_NSKILLS]; - int available_skills[MAX_SKILLS]; - int max_a = 0, res, i; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; /* Check if some skills didn't influence other stuff */ recalc_skills(TRUE); /* Grab the ones we can gain */ - max_a = 0; - for (i = 0; i < max_s_idx; i++) + std::vector<size_t> available_skills; + available_skills.reserve(s_descriptors.size()); + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - if (s_info[i].flags1 & SKF1_RANDOM_GAIN) { - available_skills[max_a] = i; - max_a++; + if (s_descriptors[i].flags & SKF_RANDOM_GAIN) + { + available_skills.push_back(i); } } /* Perform the selection */ std::vector<s32b> weights; - for (i = 0; i < max_a; i++) { - weights.push_back(s_info[available_skills[i]].random_gain_chance); + for (std::size_t i = 0; i < available_skills.size(); i++) + { + weights.push_back(s_descriptors[available_skills[i]].random_gain_chance); } std::vector<size_t> indexes = wrs(weights); assert(indexes.size() >= LOST_SWORD_NSKILLS); /* Extract the information needed from the skills */ - for (i = 0; i < LOST_SWORD_NSKILLS; i++) + int skl[LOST_SWORD_NSKILLS]; + s32b val[LOST_SWORD_NSKILLS]; + s32b mod[LOST_SWORD_NSKILLS]; + std::vector<std::string> items; + for (std::size_t i = 0; i < LOST_SWORD_NSKILLS; i++) { s32b s_idx = available_skills[indexes[i]]; - skill_type *s_ptr = &s_info[s_idx]; + auto s_ptr = &s_info[s_idx]; if (s_ptr->mod) { @@ -1356,7 +1431,9 @@ void do_get_new_skill() val[i] = s_ptr->mod * 1; mod[i] = 100; if (mod[i] + s_ptr->mod > 500) + { mod[i] = 500 - s_ptr->mod; + } } else { @@ -1370,42 +1447,56 @@ void do_get_new_skill() val[i] = 1000; } - if (s_ptr->value + val[i] > SKILL_MAX) { + if (s_ptr->value + val[i] > SKILL_MAX) + { val[i] = SKILL_MAX - s_ptr->value; } skl[i] = s_idx; items.push_back(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier", - s_ptr->name, + s_descriptors[s_idx].name.c_str(), val[i] / SKILL_STEP, val[i] % SKILL_STEP, mod[i] / SKILL_STEP, mod[i] % SKILL_STEP)); } + // Ask for a skill while (TRUE) { char last = 'a' + (LOST_SWORD_NSKILLS-1); char buf[80]; - sprintf(buf, "Choose a skill to learn(a-%c to choose, ESC to cancel)?", last); - res = ask_menu(buf, items); + sprintf(buf, "Choose a skill to learn (a-%c to choose, ESC to cancel)?", last); + int res = ask_menu(buf, items); /* Ok ? lets learn ! */ if (res > -1) { - skill_type *s_ptr; + std::size_t chosen_skill = skl[res]; + bool_ oppose = FALSE; int oppose_skill = -1; - /* Check we don't oppose an existing skill */ - for (i = 0; i < max_s_idx; i++) + /* Check we don't oppose a skill the player already has */ + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - if ((s_info[i].action[skl[res]] == SKILL_EXCLUSIVE) && - (s_info[i].value != 0)) + auto const &s_descriptor = s_descriptors[i]; + + // Only bother if player has skill + if (s_info[i].value) { - oppose = TRUE; - oppose_skill = i; - break; + // Check if i'th skill opposes the chosen one. + auto found = std::find( + s_descriptor.excludes.begin(), + s_descriptor.excludes.end(), + chosen_skill); + + if (found != s_descriptor.excludes.end()) + { + oppose = TRUE; + oppose_skill = i; + break; + } } } @@ -1423,25 +1514,32 @@ void do_get_new_skill() /* Prepare prompt */ msg = format("This skill is mutually exclusive with " "at least %s, continue?", - s_info[oppose_skill].name); + s_descriptors[oppose_skill].name.c_str()); - /* The player rejected the choice */ - if (!get_check(msg)) continue; + /* The player rejected the choice; go back to prompt */ + if (!get_check(msg)) + { + continue; + } } - s_ptr = &s_info[skl[res]]; + auto const s_desc = &s_descriptors[chosen_skill]; + auto const s_ptr = &s_info[chosen_skill]; + s_ptr->value += val[res]; s_ptr->mod += mod[res]; + if (mod[res]) { msg_format("You can now learn the %s skill.", - s_ptr->name); + s_desc->name.c_str()); } else { msg_format("Your knowledge of the %s skill increases.", - s_ptr->name); + s_desc->name.c_str()); } + break; } } @@ -1461,12 +1559,13 @@ void do_get_new_skill() */ s16b find_ability(cptr name) { - u16b i; + auto const &ab_info = game->edit_data.ab_info; - /* Scan ability list */ - for (i = 0; i < max_ab_idx; i++) + for (std::size_t i = 0; i < ab_info.size(); i++) { - if (ab_info[i].name && streq(ab_info[i].name, name)) + auto const &ab_name = ab_info[i].name; + + if ((!ab_name.empty()) && (ab_name == name)) { return (i); } @@ -1476,51 +1575,40 @@ s16b find_ability(cptr name) return ( -1); } -/* - * Do the player have the ability - */ -bool_ has_ability(int ab) +/* Do we meet the requirements? */ +static bool can_learn_ability(int ab) { - return ab_info[ab].acquired; -} + auto const &ab_info = game->edit_data.ab_info; -/* Do we meet the requirements */ -static bool_ can_learn_ability(int ab) -{ - ability_type *ab_ptr = &ab_info[ab]; - int i; + auto ab_ptr = &ab_info[ab]; - if (ab_ptr->acquired) + if (p_ptr->has_ability(ab)) + { return FALSE; + } if (p_ptr->skill_points < ab_info[ab].cost) + { return FALSE; + } - for (i = 0; i < 10; i++) + for (auto const &need_skill: ab_ptr->need_skills) { - /* Must have skill level */ - if (ab_ptr->skills[i] > -1) - { - if (get_skill(ab_ptr->skills[i]) < ab_ptr->skill_levels[i]) - return FALSE; - } - - /* Must have ability */ - if (ab_ptr->need_abilities[i] > -1) + if (get_skill(need_skill.skill_idx) < need_skill.level) { - if (!ab_info[ab_ptr->need_abilities[i]].acquired) - return FALSE; + return FALSE; } + } - /* Must not have ability */ - if (ab_ptr->forbid_abilities[i] > -1) + for (auto const &need_ability: ab_ptr->need_abilities) + { + if (!p_ptr->has_ability(need_ability)) { - if (ab_info[ab_ptr->forbid_abilities[i]].acquired) - return FALSE; + return FALSE; } } - for (i = 0; i < 6; i++) + for (std::size_t i = 0; i < 6; i++) { /* Must have stat */ if (ab_ptr->stat[i] > -1) @@ -1536,12 +1624,11 @@ static bool_ can_learn_ability(int ab) /* Learn an ability */ static void gain_ability(int ab) { - int wid, hgt; - Term_get_size(&wid, &hgt); + auto const &ab_info = game->edit_data.ab_info; if (!can_learn_ability(ab)) { - msg_box("You cannot learn this ability.", hgt / 2, wid / 2); + msg_box_auto("You cannot learn this ability."); return; } @@ -1549,18 +1636,20 @@ static void gain_ability(int ab) flush(); /* Ask we can commit the change */ - if (msg_box("Learn this ability(this is permanent)? (y/n)", hgt / 2, wid / 2) != 'y') + if (msg_box_auto("Learn this ability (this is permanent)? (y/n)") != 'y') { return; } - ab_info[ab].acquired = TRUE; + p_ptr->gain_ability(ab); p_ptr->skill_points -= ab_info[ab].cost; } -static bool compare_abilities(const int ab_idx1, const int ab_idx2) +static bool compare_abilities(std::size_t ab_idx1, std::size_t ab_idx2) { - return strcmp(ab_info[ab_idx1].name, ab_info[ab_idx2].name) < 0; + auto const &ab_info = game->edit_data.ab_info; + + return ab_info[ab_idx1].name < ab_info[ab_idx2].name; } /* @@ -1568,13 +1657,13 @@ static bool compare_abilities(const int ab_idx1, const int ab_idx2) */ void dump_abilities(FILE *fff) { - int i; + auto const &ab_info = game->edit_data.ab_info; // Find all abilities that the player has. - std::vector<int> table; - for (i = 0; i < max_ab_idx; i++) + std::vector<std::size_t> table; + for (std::size_t i = 0; i < ab_info.size(); i++) { - if (ab_info[i].name && has_ability(i)) + if ((!ab_info[i].name.empty()) && p_ptr->has_ability(i)) { table.push_back(i); } @@ -1592,7 +1681,7 @@ void dump_abilities(FILE *fff) for (int i : table) { - fprintf(fff, "\n * %s", ab_info[i].name); + fprintf(fff, "\n * %s", ab_info[i].name.c_str()); } fprintf(fff, "\n"); @@ -1602,8 +1691,10 @@ void dump_abilities(FILE *fff) /* * Draw the abilities list */ -static void print_abilities(const std::vector<int> &table, int sel, int start) +static void print_abilities(const std::vector<std::size_t> &table, int sel, int start) { + auto const &ab_info = game->edit_data.ab_info; + int i, j; int wid, hgt; cptr keys; @@ -1617,7 +1708,7 @@ static void print_abilities(const std::vector<int> &table, int sel, int start) c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED, format("Skill points left: %d", p_ptr->skill_points), 2, 0); - print_desc_aux(ab_info[table[sel]].desc, 3, 0); + print_desc_aux(ab_info[table[sel]].desc.c_str(), 3, 0); for (j = start; j < start + (hgt - 7); j++) { @@ -1632,12 +1723,18 @@ static void print_abilities(const std::vector<int> &table, int sel, int start) i = table[j]; - if (ab_info[i].acquired) + if (p_ptr->has_ability(i)) + { color = TERM_L_BLUE; + } else if (can_learn_ability(i)) + { color = TERM_WHITE; + } else + { color = TERM_L_DARK; + } if (j == sel) @@ -1647,10 +1744,10 @@ static void print_abilities(const std::vector<int> &table, int sel, int start) end = ']'; } - c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name), + c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name.c_str()), j + 7 - start, 0); - if (!ab_info[i].acquired) + if (!p_ptr->has_ability(i)) { c_prt(color, format("%d", ab_info[i].cost), j + 7 - start, 60); } @@ -1662,13 +1759,14 @@ static void print_abilities(const std::vector<int> &table, int sel, int start) } /* - * Interreact with abilitiess + * Interreact with abilities */ void do_cmd_ability() { + auto const &ab_info = game->edit_data.ab_info; + int sel = 0, start = 0; char c; - int i; int wid, hgt; /* Save the screen */ @@ -1678,10 +1776,10 @@ void do_cmd_ability() Term_clear(); /* Initialise the abilities list */ - std::vector<int> table; - for (i = 0; i < max_ab_idx; i++) + std::vector<std::size_t> table; + for (std::size_t i = 0; i < ab_info.size(); i++) { - if (ab_info[i].name) + if (!ab_info[i].name.empty()) { table.push_back(i); } @@ -1742,10 +1840,16 @@ void do_cmd_ability() /* gain ability */ if (dir == 6) gain_ability(table[sel]); - /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ + /* Wizard mode allows any ability */ + if (wizard && (c == '+')) + { + p_ptr->gain_ability(table[sel]); + } - if (wizard && (c == '+')) ab_info[table[sel]].acquired = TRUE; - if (wizard && (c == '-')) ab_info[table[sel]].acquired = FALSE; + if (wizard && (c == '-')) + { + p_ptr->lose_ability(table[sel]); + } /* Contextual help */ if (c == '?') @@ -1789,41 +1893,26 @@ void do_cmd_ability() */ void apply_level_abilities(int level) { - int i; - - for (i = 0; i < 10; i++) + auto apply = [level](std::vector<player_race_ability_type> const &abilities) -> void { - if (cp_ptr->abilities[i].level == level) - { - if ((level > 1) && (!ab_info[cp_ptr->abilities[i].ability].acquired)) - { - cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[cp_ptr->abilities[i].ability].name); - } - ab_info[cp_ptr->abilities[i].ability].acquired = TRUE; - } - if (spp_ptr->abilities[i].level == level) - { - if ((level > 1) && (!ab_info[spp_ptr->abilities[i].ability].acquired)) - { - cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[spp_ptr->abilities[i].ability].name); - } - ab_info[spp_ptr->abilities[i].ability].acquired = TRUE; - } - if (rp_ptr->abilities[i].level == level) - { - if ((level > 1) && (!ab_info[rp_ptr->abilities[i].ability].acquired)) - { - cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[rp_ptr->abilities[i].ability].name); - } - ab_info[rp_ptr->abilities[i].ability].acquired = TRUE; - } - if (rmp_ptr->abilities[i].level == level) + auto const &ab_info = game->edit_data.ab_info; + + for (auto const &a: abilities) { - if ((level > 1) && (!ab_info[rmp_ptr->abilities[i].ability].acquired)) + if (a.level == level) { - cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[rmp_ptr->abilities[i].ability].name); + if ((level > 1) && (!p_ptr->has_ability(a.ability))) + { + cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[a.ability].name.c_str()); + } + + p_ptr->gain_ability(a.ability); } - ab_info[rmp_ptr->abilities[i].ability].acquired = TRUE; } - } + }; + + apply(cp_ptr->abilities); + apply(spp_ptr->abilities); + apply(rp_ptr->abilities); + apply(rmp_ptr->abilities); } |