summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/ability_type.hpp2
-rw-r--r--src/birth.cc5
-rw-r--r--src/cmd1.cc4
-rw-r--r--src/cmd4.cc2
-rw-r--r--src/cmd6.cc2
-rw-r--r--src/dungeon.cc4
-rw-r--r--src/init1.cc1
-rw-r--r--src/loadsave.cc17
-rw-r--r--src/lua_bind.cc2
-rw-r--r--src/player_type.cc28
-rw-r--r--src/player_type.hpp20
-rw-r--r--src/skills.cc55
-rw-r--r--src/skills.hpp1
-rw-r--r--src/spells1.cc2
-rw-r--r--src/spells2.cc2
-rw-r--r--src/squelch/condition.cc2
-rw-r--r--src/xtra1.cc4
18 files changed, 95 insertions, 59 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7b4d025b..8ac5e097 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,6 +57,7 @@ SET(SRCS_COMMON
object_filter.cc
object_flag_meta.cc
options.cc
+ player_type.cc
powers.cc
q_betwen.cc
q_bounty.cc
diff --git a/src/ability_type.hpp b/src/ability_type.hpp
index ea8a921d..3a2a51ee 100644
--- a/src/ability_type.hpp
+++ b/src/ability_type.hpp
@@ -16,8 +16,6 @@ struct ability_type
s16b cost; /* Skill points cost */
- bool_ acquired; /* Do the player actualylg ot it ? */
-
/* Prereqs */
s16b skills[10]; /* List of prereq skills(10 max) */
s16b skill_levels[10]; /* List of prereq skills(10 max) */
diff --git a/src/birth.cc b/src/birth.cc
index 1fc5d515..f426fca9 100644
--- a/src/birth.cc
+++ b/src/birth.cc
@@ -1142,7 +1142,7 @@ static void player_outfit(void)
}
/* Rogues have a better knowledge of traps */
- if (has_ability(AB_TRAPPING))
+ if (p_ptr->has_ability(AB_TRAPPING))
{
t_info[TRAP_OF_DAGGER_I].known = randint(50) + 50;
t_info[TRAP_OF_POISON_NEEDLE].known = randint(50) + 50;
@@ -3083,8 +3083,7 @@ void player_birth(void)
recalc_skills(FALSE);
/* grab level 1 abilities */
- for (i = 0; i < max_ab_idx; i++)
- ab_info[i].acquired = FALSE;
+ p_ptr->abilities.clear();
apply_level_abilities(1);
/* Complete the god */
diff --git a/src/cmd1.cc b/src/cmd1.cc
index c54e3dbd..f8e064c2 100644
--- a/src/cmd1.cc
+++ b/src/cmd1.cc
@@ -2369,7 +2369,7 @@ void py_attack(int y, int x, int max_blow)
/* Hack -- High-level warriors can spread their attacks out
* among weaker foes.
*/
- if ((has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) &&
+ if ((p_ptr->has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) &&
(energy_use))
{
energy_use = energy_use * num / num_blow;
@@ -2587,7 +2587,7 @@ bool_ player_can_enter(byte feature)
{
if (p_ptr->fly ||
pass_wall ||
- (has_ability(AB_TREE_WALK)) ||
+ p_ptr->has_ability(AB_TREE_WALK) ||
(p_ptr->mimic_form == resolve_mimic_name("Ent")) ||
((p_ptr->grace >= 9000) && praying_to(GOD_YAVANNA)))
return (TRUE);
diff --git a/src/cmd4.cc b/src/cmd4.cc
index 01452090..724d5a1f 100644
--- a/src/cmd4.cc
+++ b/src/cmd4.cc
@@ -3457,7 +3457,7 @@ static void do_cmd_knowledge_pets(void)
// Calculate upkeep
int show_upkeep = 0;
- int upkeep_divider = has_ability(AB_PERFECT_CASTING) ? 15 : 20;
+ int upkeep_divider = p_ptr->has_ability(AB_PERFECT_CASTING) ? 15 : 20;
if (t_friends > 1 + (p_ptr->lev / (upkeep_divider)))
{
diff --git a/src/cmd6.cc b/src/cmd6.cc
index 4490b5de..1663b5c1 100644
--- a/src/cmd6.cc
+++ b/src/cmd6.cc
@@ -5318,7 +5318,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item)
msg_print("The stone reveals hidden mysteries...");
if (!ident_spell()) break;
- if (has_ability(AB_PERFECT_CASTING))
+ if (p_ptr->has_ability(AB_PERFECT_CASTING))
{
/* Sufficient mana */
if (20 <= p_ptr->csp)
diff --git a/src/dungeon.cc b/src/dungeon.cc
index b02b2a87..00bee6f4 100644
--- a/src/dungeon.cc
+++ b/src/dungeon.cc
@@ -1489,7 +1489,7 @@ static void process_world(void)
int feature = cave[p_ptr->py][p_ptr->px].feat;
/* Player can walk through or fly over trees */
- if ((has_ability(AB_TREE_WALK) || p_ptr->fly) && (feature == FEAT_TREES))
+ if ((p_ptr->has_ability(AB_TREE_WALK) || p_ptr->fly) && (feature == FEAT_TREES))
{
/* Do nothing */
}
@@ -1673,7 +1673,7 @@ static void process_world(void)
{
int upkeep_divider = 20;
- if (has_ability(AB_PERFECT_CASTING))
+ if (p_ptr->has_ability(AB_PERFECT_CASTING))
upkeep_divider = 15;
if (total_friends > 1 + (p_ptr->lev / (upkeep_divider)))
diff --git a/src/init1.cc b/src/init1.cc
index de92ae90..3f803fbe 100644
--- a/src/init1.cc
+++ b/src/init1.cc
@@ -3419,7 +3419,6 @@ errr init_ab_info_txt(FILE *fp)
/* Init */
ab_ptr->action_mkey = 0;
- ab_ptr->acquired = FALSE;
for (z = 0; z < 10; z++)
{
ab_ptr->skills[z] = -1;
diff --git a/src/loadsave.cc b/src/loadsave.cc
index 2e3ac33f..e6f4cefa 100644
--- a/src/loadsave.cc
+++ b/src/loadsave.cc
@@ -1,7 +1,6 @@
#include "loadsave.hpp"
#include "loadsave.h"
-#include "ability_type.hpp"
#include "artifact_type.hpp"
#include "birth.hpp"
#include "cave_type.hpp"
@@ -619,21 +618,7 @@ static bool_ do_extra(ls_flag_t flag)
}
// Abilities
- {
- u16b tmp16u = max_ab_idx;
-
- do_u16b(&tmp16u, flag);
-
- if ((flag == ls_flag_t::LOAD) && (tmp16u > max_ab_idx))
- {
- quit("Too many abilities");
- }
-
- for (std::size_t i = 0; i < tmp16u; ++i)
- {
- do_bool(&ab_info[i].acquired, flag);
- }
- }
+ do_vector(flag, p_ptr->abilities, do_u16b);
// Miscellaneous
do_s16b(&p_ptr->luck_base, flag);
diff --git a/src/lua_bind.cc b/src/lua_bind.cc
index 151ba3b8..1612fb29 100644
--- a/src/lua_bind.cc
+++ b/src/lua_bind.cc
@@ -146,7 +146,7 @@ static s32b spell_chance_school(s32b s)
minfail = adj_mag_fail[stat_ind];
/* Must have Perfect Casting to get below 5% */
- if (!(has_ability(AB_PERFECT_CASTING)))
+ if (!(p_ptr->has_ability(AB_PERFECT_CASTING)))
{
if (minfail < 5) minfail = 5;
}
diff --git a/src/player_type.cc b/src/player_type.cc
new file mode 100644
index 00000000..0cc66de7
--- /dev/null
+++ b/src/player_type.cc
@@ -0,0 +1,28 @@
+#include "player_type.hpp"
+
+#include <algorithm>
+
+bool player_type::has_ability(u16b ability_idx) const
+{
+ return std::find(
+ abilities.begin(),
+ abilities.end(),
+ ability_idx) != abilities.end();
+}
+
+void player_type::gain_ability(u16b ability_idx)
+{
+ // Duplicates don't really matter, so let's just
+ // accept whatever value we get without checking
+ // anything.
+ abilities.push_back(ability_idx);
+}
+
+void player_type::lose_ability(u16b ability_idx)
+{
+ abilities.erase(
+ std::remove(
+ abilities.begin(),
+ abilities.end(),
+ ability_idx));
+}
diff --git a/src/player_type.hpp b/src/player_type.hpp
index 1285e018..8f3c06dc 100644
--- a/src/player_type.hpp
+++ b/src/player_type.hpp
@@ -378,6 +378,9 @@ struct player_type
bool_ powers[POWER_MAX] = { FALSE }; /* Actual powers */
bool_ powers_mod[POWER_MAX] = { FALSE }; /* Intrinsinc powers */
+ /* Acquired abilities; indexes into ab_info[] */
+ std::vector<u16b> abilities;
+
/* Skills */
s16b skill_points = 0;
s16b skill_last_level = 0; /* Prevents gaining skills by losing level and regaining them */
@@ -400,5 +403,20 @@ struct player_type
bool_ did_nothing = FALSE; /* True if the last action wasnt a real action */
bool_ leaving = FALSE; /* True if player is leaving */
-};
+ /**
+ * Does the player have the given ability?
+ */
+ bool has_ability(u16b ability_idx) const;
+
+ /**
+ * Gain the given ability.
+ */
+ void gain_ability(u16b ability_idx);
+
+ /**
+ * Lose the given ability.
+ */
+ void lose_ability(u16b ability_idx);
+
+};
diff --git a/src/skills.cc b/src/skills.cc
index 70665a49..fc5b068c 100644
--- a/src/skills.cc
+++ b/src/skills.cc
@@ -839,7 +839,7 @@ static int do_cmd_activate_skill_aux()
for (size_t i = 0; i < max_ab_idx; 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;
@@ -970,7 +970,7 @@ void do_cmd_activate_skill()
}
for (j = 0; j < max_ab_idx; 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;
}
@@ -1436,21 +1436,13 @@ s16b find_ability(cptr name)
return ( -1);
}
-/*
- * Do the player have the ability
- */
-bool_ has_ability(int ab)
-{
- return ab_info[ab].acquired;
-}
-
/* Do we meet the requirements */
static bool_ can_learn_ability(int ab)
{
ability_type *ab_ptr = &ab_info[ab];
int i;
- if (ab_ptr->acquired)
+ if (p_ptr->has_ability(ab))
return FALSE;
if (p_ptr->skill_points < ab_info[ab].cost)
@@ -1468,15 +1460,19 @@ static bool_ can_learn_ability(int ab)
/* Must have ability */
if (ab_ptr->need_abilities[i] > -1)
{
- if (!ab_info[ab_ptr->need_abilities[i]].acquired)
+ if (!p_ptr->has_ability(ab_ptr->need_abilities[i]))
+ {
return FALSE;
+ }
}
/* Must not have ability */
if (ab_ptr->forbid_abilities[i] > -1)
{
- if (ab_info[ab_ptr->forbid_abilities[i]].acquired)
+ if (p_ptr->has_ability(ab_ptr->forbid_abilities[i]))
+ {
return FALSE;
+ }
}
}
@@ -1509,12 +1505,12 @@ 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("Learn this ability (this is permanent)? (y/n)", hgt / 2, wid / 2) != 'y')
{
return;
}
- ab_info[ab].acquired = TRUE;
+ p_ptr->gain_ability(ab);
p_ptr->skill_points -= ab_info[ab].cost;
}
@@ -1534,7 +1530,7 @@ void dump_abilities(FILE *fff)
std::vector<int> table;
for (i = 0; i < max_ab_idx; i++)
{
- if (ab_info[i].name && has_ability(i))
+ if (ab_info[i].name && p_ptr->has_ability(i))
{
table.push_back(i);
}
@@ -1592,12 +1588,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)
@@ -1610,7 +1612,7 @@ static void print_abilities(const std::vector<int> &table, int sel, int start)
c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name),
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);
}
@@ -1702,10 +1704,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 == '?')
@@ -1755,11 +1763,12 @@ void apply_level_abilities(int level)
{
if (a.level == level)
{
- if ((level > 1) && (!ab_info[a.ability].acquired))
+ 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);
}
- ab_info[a.ability].acquired = TRUE;
+
+ p_ptr->gain_ability(a.ability);
}
}
};
diff --git a/src/skills.hpp b/src/skills.hpp
index 6c1880a6..4cd63358 100644
--- a/src/skills.hpp
+++ b/src/skills.hpp
@@ -22,6 +22,5 @@ extern void init_skill(s32b value, s32b mod, int i);
extern s16b find_ability(cptr name);
extern void dump_abilities(FILE *fff);
extern void do_cmd_ability(void);
-extern bool_ has_ability(int ab);
extern void apply_level_abilities(int level);
extern void recalc_skills(bool_ init);
diff --git a/src/spells1.cc b/src/spells1.cc
index 1fe14c5a..0054a1d6 100644
--- a/src/spells1.cc
+++ b/src/spells1.cc
@@ -1322,7 +1322,7 @@ void take_hit(int damage, cptr hit_from)
if (p_ptr->chp < 0)
{
/* Necromancers get a special treatment */
- if (((!has_ability(AB_UNDEAD_FORM)) || ((p_ptr->necro_extra & CLASS_UNDEAD))))
+ if (((!p_ptr->has_ability(AB_UNDEAD_FORM)) || ((p_ptr->necro_extra & CLASS_UNDEAD))))
{
/* Hack -- Note death */
if (!options->last_words)
diff --git a/src/spells2.cc b/src/spells2.cc
index 0cdf08ed..bc5b8642 100644
--- a/src/spells2.cc
+++ b/src/spells2.cc
@@ -3623,7 +3623,7 @@ bool_ recharge(int power)
/*** Determine Seriousness of Failure ***/
/* Mages recharge objects more safely. */
- if (has_ability(AB_PERFECT_CASTING))
+ if (p_ptr->has_ability(AB_PERFECT_CASTING))
{
/* 10% chance to blow up one rod, otherwise draining. */
if (o_ptr->tval == TV_ROD_MAIN)
diff --git a/src/squelch/condition.cc b/src/squelch/condition.cc
index c3b8c3f5..41806feb 100644
--- a/src/squelch/condition.cc
+++ b/src/squelch/condition.cc
@@ -891,7 +891,7 @@ void SymbolCondition::to_json(json_t *j) const
bool AbilityCondition::is_match(object_type *) const
{
- return has_ability(m_ability_idx);
+ return p_ptr->has_ability(m_ability_idx);
}
std::shared_ptr<Condition> AbilityCondition::from_json(json_t *j)
diff --git a/src/xtra1.cc b/src/xtra1.cc
index 16edf4bf..280cc61a 100644
--- a/src/xtra1.cc
+++ b/src/xtra1.cc
@@ -2246,8 +2246,8 @@ void calc_body_bonus()
static int get_extra_blows_ability() {
/* Count bonus abilities */
int num = 0;
- if (has_ability(AB_MAX_BLOW1)) num++;
- if (has_ability(AB_MAX_BLOW2)) num++;
+ if (p_ptr->has_ability(AB_MAX_BLOW1)) num++;
+ if (p_ptr->has_ability(AB_MAX_BLOW2)) num++;
return num;
}