Allow items that boost skills other than the three basic stats (STR/DEX/INT)
Where stat-boosting items were already accounted for, the effects remain unchanged by this; however, some additional effects have been added. Strength-boosting items have the following new effects: - Increases hit points gained on level-up - Increases amount PCs can carry Dexterity-boosting items have the following new effects: - Increases hit chance in unarmed combat Intelligence-boosting items have the following new effects: - Increases effectiveness in a mindduel
This commit is contained in:
@@ -503,7 +503,7 @@ bool pc_combat_move(location destination) {
|
||||
|
||||
void char_parry() {
|
||||
univ.party[current_pc].parry = (univ.party[current_pc].ap / 4) *
|
||||
(2 + stat_adj(current_pc,eSkill::DEXTERITY) + univ.party[current_pc].skills[eSkill::DEFENSE]);
|
||||
(2 + stat_adj(current_pc,eSkill::DEXTERITY) + univ.party[current_pc].skill(eSkill::DEFENSE));
|
||||
univ.party[current_pc].ap = 0;
|
||||
}
|
||||
|
||||
@@ -514,9 +514,8 @@ void char_stand_ready() {
|
||||
|
||||
void pc_attack(short who_att,short target) {
|
||||
short r1,r2,weap1 = 24, weap2 = 24,i,store_hp,skill_item;
|
||||
eSkill what_skill1 = eSkill::DEXTERITY, what_skill2 = eSkill::DEXTERITY;
|
||||
cCreature *which_m;
|
||||
short hit_adj, dam_adj, spec_dam = 0,poison_amt;
|
||||
short hit_adj, dam_adj;
|
||||
|
||||
// slice out bad attacks
|
||||
if(univ.party[who_att].main_status != eMainStatus::ALIVE)
|
||||
@@ -570,7 +569,7 @@ void pc_attack(short who_att,short target) {
|
||||
r1 += 5 * (univ.party[current_pc].status[eStatus::WEBS] / 3);
|
||||
r2 = get_ran(1,1,4) + dam_adj;
|
||||
|
||||
if(r1 <= hit_chance[univ.party[who_att].skills[what_skill1]]) {
|
||||
if(r1 <= hit_chance[univ.party[who_att].skill(eSkill::DEXTERITY)]) {
|
||||
damage_monst(target, who_att, r2, 0,eDamageType::WEAPON,4);
|
||||
}
|
||||
else {
|
||||
@@ -636,7 +635,7 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt
|
||||
if(weap.ability == eItemAbil::WEAK_WEAPON)
|
||||
r2 = (r2 * (10 - weap.abil_data[0])) / 10;
|
||||
|
||||
if(r1 <= hit_chance[univ.party[who_att].skills[what_skill]]) {
|
||||
if(r1 <= hit_chance[univ.party[who_att].skill(what_skill)]) {
|
||||
eDamageType dmg_tp = eDamageType::UNBLOCKABLE;
|
||||
short spec_dam = calc_spec_dam(weap.ability,weap.abil_data[0],weap.abil_data[1],which_m,dmg_tp);
|
||||
short bonus_dam = 0;
|
||||
@@ -645,10 +644,10 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt
|
||||
if(primary) {
|
||||
// assassinate
|
||||
r1 = get_ran(1,1,100);
|
||||
if((univ.party[who_att].level >= which_m->level - 1)
|
||||
&& univ.party[who_att].skills[eSkill::ASSASSINATION] >= which_m->level / 2
|
||||
int assassin = univ.party[who_att].skill(eSkill::ASSASSINATION);
|
||||
if((univ.party[who_att].level >= which_m->level - 1) && assassin >= which_m->level / 2
|
||||
&& (!which_m->abil[eMonstAbil::SPLITS].active)) // Can't assassinate splitters
|
||||
if(r1 < hit_chance[max(univ.party[who_att].skills[eSkill::ASSASSINATION] - which_m->level,0)]) {
|
||||
if(r1 < hit_chance[max(assassin - which_m->level,0)]) {
|
||||
add_string_to_buf(" You assassinate.");
|
||||
spec_dam += r2;
|
||||
}
|
||||
@@ -1481,7 +1480,7 @@ void fire_missile(location target) {
|
||||
bool exploding = false;
|
||||
missile_firer = current_pc;
|
||||
|
||||
skill = univ.party[missile_firer].skills[univ.party[missile_firer].items[missile_inv_slot].weap_type];
|
||||
skill = univ.party[missile_firer].skill(univ.party[missile_firer].items[missile_inv_slot].weap_type);
|
||||
range = (overall_mode == MODE_FIRING) ? 12 : 8;
|
||||
dam = univ.party[missile_firer].items[ammo_inv_slot].item_level;
|
||||
dam_bonus = univ.party[missile_firer].items[ammo_inv_slot].bonus + minmax(-8,8,univ.party[missile_firer].status[eStatus::BLESS_CURSE]);
|
||||
@@ -4297,7 +4296,7 @@ bool combat_cast_mage_spell() {
|
||||
store_sp = univ.party[current_pc].cur_sp;
|
||||
if(univ.party[current_pc].cur_sp == 0)
|
||||
add_string_to_buf("Cast: No spell points. ");
|
||||
else if(univ.party[current_pc].skills[eSkill::MAGE_SPELLS] == 0)
|
||||
else if(univ.party[current_pc].skill(eSkill::MAGE_SPELLS) == 0)
|
||||
add_string_to_buf("Cast: No mage skill. ");
|
||||
else if(get_encumberance(current_pc) > 1) {
|
||||
add_string_to_buf("Cast: Too encumbered. ");
|
||||
@@ -4508,7 +4507,7 @@ bool combat_cast_priest_spell() {
|
||||
if(univ.party[current_pc].cur_sp == 0) {
|
||||
add_string_to_buf("Cast: No spell points. ");
|
||||
return false;
|
||||
} else if(univ.party[current_pc].skills[eSkill::PRIEST_SPELLS] == 0) {
|
||||
} else if(univ.party[current_pc].skill(eSkill::PRIEST_SPELLS) == 0) {
|
||||
add_string_to_buf("Cast: No priest skill. ");
|
||||
return false;
|
||||
}
|
||||
@@ -4798,8 +4797,8 @@ static void process_force_cage(location loc, short i) {
|
||||
cPlayer& who = univ.party[i];
|
||||
// We want to make sure everyone has a chance of eventually breaking a cage, because it never ends on its own,
|
||||
// and because being trapped unconditionally prevents you from ending combat mode.
|
||||
short bonus = 5 + who.skills[eSkill::MAGE_LORE];
|
||||
if(get_ran(1,1,100) < who.skills[eSkill::MAGE_SPELLS]*10 + who.skills[eSkill::PRIEST_SPELLS]*4 + bonus) {
|
||||
short bonus = 5 + who.skill(eSkill::MAGE_LORE);
|
||||
if(get_ran(1,1,100) < who.skill(eSkill::MAGE_SPELLS)*10 + who.skill(eSkill::PRIEST_SPELLS)*4 + bonus) {
|
||||
play_sound(60);
|
||||
add_string_to_buf(" " + who.name + " breaks force cage.");
|
||||
univ.town.set_force_cage(loc.x,loc.y,false);
|
||||
|
@@ -541,7 +541,11 @@ static void display_pc_info(cDialog& me, const short pc) {
|
||||
|
||||
for(i = 0; i < 19; i++) {
|
||||
eSkill skill = eSkill(i);
|
||||
me[skill_ids[i]].setTextToNum(univ.party[pc].skills[skill]);
|
||||
int bonus = univ.party[pc].get_prot_level(eItemAbil::BOOST_STAT, i);
|
||||
to_draw << univ.party[pc].skills[skill];
|
||||
if(bonus > 0) to_draw << '+' << bonus;
|
||||
me[skill_ids[i]].setText(to_draw.str());
|
||||
to_draw.str("");
|
||||
}
|
||||
store = total_encumberance(pc);
|
||||
me["encumb"].setTextToNum(store);
|
||||
|
@@ -996,7 +996,7 @@ void place_treasure(location where,short level,short loot,short mode) {
|
||||
if(new_item.variety != eItemType::NO_ITEM) {
|
||||
for(i = 0; i < 6; i++)
|
||||
if((univ.party[i].main_status == eMainStatus::ALIVE)
|
||||
&& get_ran(1,1,100) < id_odds[univ.party[i].skills[eSkill::ITEM_LORE]])
|
||||
&& get_ran(1,1,100) < id_odds[univ.party[i].skill(eSkill::ITEM_LORE)])
|
||||
new_item.ident = true;
|
||||
place_item(new_item,where,false);
|
||||
}
|
||||
|
@@ -1378,9 +1378,9 @@ short get_encumberance(short pc_num) {
|
||||
for(i = 0; i < 24; i++)
|
||||
if(univ.party[pc_num].equip[i]) {
|
||||
what_val = univ.party[pc_num].items[i].awkward;
|
||||
if(what_val == 1 && get_ran(1,0,130) < hit_chance[univ.party[pc_num].skills[eSkill::DEFENSE]])
|
||||
if(what_val == 1 && get_ran(1,0,130) < hit_chance[univ.party[pc_num].skill(eSkill::DEFENSE)])
|
||||
what_val--;
|
||||
if(what_val > 1 && get_ran(1,0,70) < hit_chance[univ.party[pc_num].skills[eSkill::DEFENSE]])
|
||||
if(what_val > 1 && get_ran(1,0,70) < hit_chance[univ.party[pc_num].skill(eSkill::DEFENSE)])
|
||||
what_val--;
|
||||
store += what_val;
|
||||
}
|
||||
|
@@ -648,8 +648,8 @@ void award_xp(short pc_num,short amt) {
|
||||
std::string level = std::to_string(univ.party[pc_num].level);
|
||||
add_string_to_buf(" " + univ.party[pc_num].name + " is level " + level + "!");
|
||||
univ.party[pc_num].skill_pts += (univ.party[pc_num].level < 20) ? 5 : 4;
|
||||
add_hp = (univ.party[pc_num].level < 26) ? get_ran(1,2,6) + skill_bonus[univ.party[pc_num].skills[eSkill::STRENGTH]]
|
||||
: max (skill_bonus[univ.party[pc_num].skills[eSkill::STRENGTH]],0);
|
||||
add_hp = (univ.party[pc_num].level < 26) ? get_ran(1,2,6) + skill_bonus[univ.party[pc_num].skill(eSkill::STRENGTH)]
|
||||
: max (skill_bonus[univ.party[pc_num].skill(eSkill::STRENGTH)],0);
|
||||
if(add_hp < 0)
|
||||
add_hp = 0;
|
||||
univ.party[pc_num].max_health += add_hp;
|
||||
@@ -687,7 +687,7 @@ static short check_party_stat_get(short pc, eSkill which_stat) {
|
||||
case eSkill::CUR_LEVEL:
|
||||
return univ.party[pc].level;
|
||||
default:
|
||||
return univ.party[pc].skills[which_stat];
|
||||
return univ.party[pc].skill(which_stat);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -739,11 +739,11 @@ bool poison_weapon( short pc_num, short how_much,short safe) {
|
||||
// Nimble?
|
||||
if(univ.party[pc_num].traits[eTrait::NIMBLE])
|
||||
r1 -= 6;
|
||||
if((r1 > p_chance[univ.party[pc_num].skills[eSkill::POISON]]) && (safe == 0)) {
|
||||
if((r1 > p_chance[univ.party[pc_num].skill(eSkill::POISON)]) && (safe == 0)) {
|
||||
add_string_to_buf(" Poison put on badly. ");
|
||||
p_level = p_level / 2;
|
||||
r1 = get_ran(1,1,100);
|
||||
if(r1 > p_chance[univ.party[pc_num].skills[eSkill::POISON]] + 10) {
|
||||
if(r1 > p_chance[univ.party[pc_num].skill(eSkill::POISON)] + 10) {
|
||||
add_string_to_buf(" You nick yourself. ");
|
||||
univ.party[pc_num].status[eStatus::POISON] += p_level;
|
||||
}
|
||||
@@ -1629,7 +1629,7 @@ void crumble_wall(location where) { // TODO: Add something like this to the spre
|
||||
void do_mindduel(short pc_num,cCreature *monst) {
|
||||
short i = 0,adjust,r1,r2,balance = 0;
|
||||
|
||||
adjust = (univ.party[pc_num].level + univ.party[pc_num].skills[eSkill::INTELLIGENCE]) / 2 - monst->level * 2;
|
||||
adjust = (univ.party[pc_num].level + univ.party[pc_num].skill(eSkill::INTELLIGENCE)) / 2 - monst->level * 2;
|
||||
adjust += univ.party[pc_num].get_prot_level(eItemAbil::WILL) * 5;
|
||||
if(monst->attitude % 2 != 1)
|
||||
make_town_hostile();
|
||||
@@ -1757,7 +1757,7 @@ bool pc_can_cast_spell(short pc_num,eSpell spell_num) {
|
||||
return false; // From Windows version. It does kinda make sense, though this function shouldn't even be called in these modes.
|
||||
if(!isMage(spell_num) && !isPriest(spell_num))
|
||||
return false;
|
||||
if(univ.party[pc_num].skills[type] < level)
|
||||
if(univ.party[pc_num].skill(type) < level)
|
||||
return false;
|
||||
if(univ.party[pc_num].main_status != eMainStatus::ALIVE)
|
||||
return false;
|
||||
@@ -2180,7 +2180,7 @@ eSpell pick_spell(short pc_num,eSkill type) { // 70 - no spell OW spell num
|
||||
}
|
||||
|
||||
if(!can_choose_caster) {
|
||||
if(univ.party[pc_num].skills[type] == 0) {
|
||||
if(univ.party[pc_num].skill(type) == 0) {
|
||||
if(type == eSkill::MAGE_SPELLS) add_string_to_buf("Cast: No mage skill.");
|
||||
else add_string_to_buf("Cast: No priest skill.");
|
||||
return eSpell::NONE;
|
||||
@@ -2277,6 +2277,8 @@ void print_spell_cast(eSpell spell,eSkill which) {
|
||||
short stat_adj(short pc_num,eSkill which) {
|
||||
short tr;
|
||||
|
||||
// This is one place where we use the base skill level instead of the adjusted skill level
|
||||
// Using the adjusted skill level here would alter the original mechanics of stat-boosting items
|
||||
tr = skill_bonus[univ.party[pc_num].skills[which]];
|
||||
if(which == eSkill::INTELLIGENCE) {
|
||||
if(univ.party[pc_num].traits[eTrait::MAGICALLY_APT])
|
||||
@@ -2366,16 +2368,16 @@ void do_alchemy() {
|
||||
play_sound(8);
|
||||
|
||||
r1 = get_ran(1,1,100);
|
||||
if(r1 < fail_chance[univ.party[pc_num].skills[eSkill::ALCHEMY] - alch_difficulty[which_p]]) {
|
||||
if(r1 < fail_chance[univ.party[pc_num].skill(eSkill::ALCHEMY) - alch_difficulty[which_p]]) {
|
||||
add_string_to_buf("Alchemy: Failed. ");
|
||||
r1 = get_ran(1,0,1);
|
||||
play_sound(41 );
|
||||
}
|
||||
else {
|
||||
cItem store_i(potion);
|
||||
if(univ.party[pc_num].skills[eSkill::ALCHEMY] - alch_difficulty[which_p] >= 5)
|
||||
if(univ.party[pc_num].skill(eSkill::ALCHEMY) - alch_difficulty[which_p] >= 5)
|
||||
store_i.charges++;
|
||||
if(univ.party[pc_num].skills[eSkill::ALCHEMY] - alch_difficulty[which_p] >= 11)
|
||||
if(univ.party[pc_num].skill(eSkill::ALCHEMY) - alch_difficulty[which_p] >= 11)
|
||||
store_i.charges++;
|
||||
store_i.graphic_num += get_ran(1,0,2);
|
||||
if(!univ.party[pc_num].give_item(store_i,false)) {
|
||||
@@ -2420,12 +2422,12 @@ eAlchemy alch_choice(short pc_num) {
|
||||
std::string n = boost::lexical_cast<std::string>(i + 1);
|
||||
chooseAlchemy["label" + n].setText(get_str("magic-names", i + 200));
|
||||
chooseAlchemy["potion" + n].attachClickHandler(alch_choice_event_filter);
|
||||
if(univ.party[pc_num].skills[eSkill::ALCHEMY] < difficulty[i] || univ.party.alchemy[i] == 0)
|
||||
if(univ.party[pc_num].skill(eSkill::ALCHEMY) < difficulty[i] || univ.party.alchemy[i] == 0)
|
||||
chooseAlchemy["potion" + n].hide();
|
||||
}
|
||||
std::ostringstream sout;
|
||||
sout << univ.party[pc_num].name;
|
||||
sout << " (skill " << univ.party[pc_num].skills[eSkill::ALCHEMY] << ")";
|
||||
sout << " (skill " << univ.party[pc_num].skill(eSkill::ALCHEMY) << ")";
|
||||
chooseAlchemy["mixer"].setText(sout.str());
|
||||
if(univ.party.help_received[20] == 0) {
|
||||
// TODO: I'm not sure if the initial draw is needed
|
||||
@@ -2624,7 +2626,7 @@ bool damage_pc(short which_pc,short how_much,eDamageType damage_type,eRace type_
|
||||
how_much = how_much - univ.party[which_pc].items[i].bonus;
|
||||
}
|
||||
r1 = get_ran(1,1,100);
|
||||
if(r1 < hit_chance[univ.party[which_pc].skills[eSkill::DEFENSE]] - 20)
|
||||
if(r1 < hit_chance[univ.party[which_pc].skill(eSkill::DEFENSE)] - 20)
|
||||
how_much -= 1;
|
||||
}
|
||||
if(univ.party[which_pc].items[i].protection > 0) {
|
||||
@@ -2651,7 +2653,7 @@ bool damage_pc(short which_pc,short how_much,eDamageType damage_type,eRace type_
|
||||
if(univ.party[which_pc].traits[eTrait::TOUGHNESS])
|
||||
how_much--;
|
||||
// luck
|
||||
if(get_ran(1,1,100) < 2 * (hit_chance[univ.party[which_pc].skills[eSkill::LUCK]] - 20))
|
||||
if(get_ran(1,1,100) < 2 * (hit_chance[univ.party[which_pc].skill(eSkill::LUCK)] - 20))
|
||||
how_much -= 1;
|
||||
}
|
||||
|
||||
@@ -2772,8 +2774,9 @@ void kill_pc(short which_pc,eMainStatus type) {
|
||||
if(type != eMainStatus::STONE)
|
||||
i = univ.party[which_pc].has_abil_equip(eItemAbil::LIFE_SAVING);
|
||||
|
||||
if(!no_save && type != eMainStatus::ABSENT && univ.party[which_pc].skills[eSkill::LUCK] > 0 &&
|
||||
get_ran(1,1,100) < hit_chance[univ.party[which_pc].skills[eSkill::LUCK]]) {
|
||||
int luck = univ.party[which_pc].skill(eSkill::LUCK);
|
||||
if(!no_save && type != eMainStatus::ABSENT && luck > 0 &&
|
||||
get_ran(1,1,100) < hit_chance[luck]) {
|
||||
add_string_to_buf(" But you luck out! ");
|
||||
univ.party[which_pc].cur_health = 0;
|
||||
}
|
||||
|
@@ -1073,7 +1073,7 @@ void pick_lock(location where,short pc_num) {
|
||||
will_break = true;
|
||||
|
||||
r1 = get_ran(1,1,100) - 5 * stat_adj(pc_num,eSkill::DEXTERITY) + univ.town.difficulty * 7
|
||||
- 5 * univ.party[pc_num].skills[eSkill::LOCKPICKING] - univ.party[pc_num].items[which_item].abil_data[0] * 7;
|
||||
- 5 * univ.party[pc_num].skill(eSkill::LOCKPICKING) - univ.party[pc_num].items[which_item].abil_data[0] * 7;
|
||||
|
||||
// Nimble?
|
||||
if(univ.party[pc_num].traits[eTrait::NIMBLE])
|
||||
|
@@ -66,8 +66,8 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) {
|
||||
if(pc_num < 6) {
|
||||
i = stat_adj(pc_num,eSkill::DEXTERITY);
|
||||
i += univ.party[pc_num].get_prot_level(eItemAbil::THIEVING) / 2;
|
||||
skill = minmax(0,20,univ.party[pc_num].skills[eSkill::DISARM_TRAPS] +
|
||||
+ univ.party[pc_num].skills[eSkill::LUCK] / 2 + 1 - univ.town.difficulty + 2 * i);
|
||||
skill = minmax(0,20,univ.party[pc_num].skill(eSkill::DISARM_TRAPS) +
|
||||
+ univ.party[pc_num].skill(eSkill::LUCK) / 2 + 1 - univ.town.difficulty + 2 * i);
|
||||
|
||||
r1 = get_ran(1,1,100) + diff;
|
||||
// Nimble?
|
||||
|
@@ -186,7 +186,7 @@ bool cPlayer::give_item(cItem item, bool do_print, bool allow_overload) {
|
||||
}
|
||||
|
||||
short cPlayer::max_weight() {
|
||||
return 100 + (15 * min(skills[eSkill::STRENGTH],20)) + (traits[eTrait::STRENGTH] * 30)
|
||||
return 100 + (15 * min(skill(eSkill::STRENGTH),20)) + (traits[eTrait::STRENGTH] * 30)
|
||||
+ (traits[eTrait::BAD_BACK] * -50);
|
||||
}
|
||||
|
||||
@@ -281,6 +281,10 @@ short cPlayer::has_abil(eItemAbil abil,short dat) {
|
||||
return 24;
|
||||
}
|
||||
|
||||
short cPlayer::skill(eSkill skill) {
|
||||
return min(20, skills[skill] + get_prot_level(eItemAbil::BOOST_STAT, int(skill)));
|
||||
}
|
||||
|
||||
eBuyStatus cPlayer::ok_to_buy(short cost,cItem item) {
|
||||
if(item.variety != eItemType::GOLD && item.variety != eItemType::FOOD) {
|
||||
for(int i = 0; i < 24; i++)
|
||||
|
@@ -69,6 +69,7 @@ public:
|
||||
short get_prot_level(eItemAbil abil, short dat = -1);
|
||||
short has_abil_equip(eItemAbil abil, short dat = -1);
|
||||
short has_abil(eItemAbil abil, short dat = -1);
|
||||
short skill(eSkill skill);
|
||||
eBuyStatus ok_to_buy(short cost,cItem item);
|
||||
|
||||
void append(legacy::pc_record_type old);
|
||||
|
Reference in New Issue
Block a user