Move most of the methods affecting specific status effects into the appropriate files

Other changes:
- PC-on-PC attacks now account for the target's dexterity, evasion items, and parry status
- Harmful spells that inflict a status effect now work if targeted on a PC
- Turn Undead, Dispel Undead, Ravage Spirit spells, when cast by a PC, now consider the possibility of undead/demon party members, and work if targeted on them
- Forcecage is now allowed for monster touch/ray abilities
- Items that inflict curses, slowing, or webs now account for items that grant resistance
This commit is contained in:
2015-02-01 15:43:31 -05:00
parent 4f93e8ea5a
commit 07054eb465
11 changed files with 529 additions and 397 deletions

View File

@@ -61,6 +61,7 @@
9107074C18F1D18400F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; };
9107074D18F1D18400F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; };
9107074E18F1D18500F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; };
9117A4111A7EC06700CD6EB4 /* living.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914698FB1A7362D900F20F5E /* living.cpp */; };
91222FC11A72366D008413A5 /* spell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91597A6E1A3BEDC700BE7BF9 /* spell.cpp */; };
912283C90FD0E16C00B21642 /* undo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 912283C80FD0E16C00B21642 /* undo.cpp */; };
912286F80FD330E500B21642 /* dlogutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBADA0FB91D2A001E34EA /* dlogutil.cpp */; };
@@ -1568,6 +1569,7 @@
91E30F2C1A74819D0057C54A /* fileio_party.cpp in Sources */,
91E30F2F1A7481C50057C54A /* fileio.cpp in Sources */,
91E30F311A748ABA0057C54A /* fileio_scen.cpp in Sources */,
9117A4111A7EC06700CD6EB4 /* living.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -567,6 +567,15 @@ void pc_attack(short who_att,iLiving* target) {
r1 += 5 * (univ.party[current_pc].status[eStatus::WEBS] / 3);
r2 = get_ran(1,1,4) + dam_adj;
if(cPlayer* pc_target = dynamic_cast<cPlayer*>(target)) {
// PCs get some additional defensive perks
// These calculations were taken straight from the monster-on-PC attack code
r1 += 5 * pc_target->stat_adj(eSkill::DEXTERITY);
r1 += pc_target->get_prot_level(eItemAbil::EVASION);
if(pc_target->parry < 100)
r1 += 5 * pc_target->parry;
}
if(r1 <= hit_chance[attacker.skill(eSkill::DEXTERITY)]) {
size_t i_monst = univ.get_target_i(*target);
// TODO: Change to damage_target()
@@ -663,12 +672,19 @@ static void apply_weapon_status(eStatus status, int how_much, int dmg, iLiving&
case eStatus::FORCECAGE:
add_string_to_buf(" " + weap_type + " emits a green flash.");
which_m.sleep(eStatus::FORCECAGE, 0, dmg - how_much / 2);
if(which_m.status[eStatus::FORCECAGE] > 0)
univ.town.set_force_cage(which_m.get_loc().x, which_m.get_loc().y, true);
break;
case eStatus::MARTYRS_SHIELD:
add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura.");
which_m.apply_status(eStatus::MARTYRS_SHIELD, how_much / -2);
break;
}
if(dynamic_cast<cPlayer*>(&which_m)) {
put_pc_screen();
if(status == eStatus::DUMB)
adjust_spell_menus();
}
}
// primary: 0 - secondary weapon, 1 - primary (and only) weapon, 2 - primary of two weapons
@@ -702,6 +718,15 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
if(weap.ability == eItemAbil::WEAK_WEAPON)
r2 = (r2 * (10 - weap.abil_data[0])) / 10;
if(cPlayer* pc_target = dynamic_cast<cPlayer*>(&target)) {
// PCs get some additional defensive perks
// These calculations were taken straight from the monster-on-PC attack code
r1 += 5 * pc_target->stat_adj(eSkill::DEXTERITY);
r1 += pc_target->get_prot_level(eItemAbil::EVASION);
if(pc_target->parry < 100)
r1 += 5 * pc_target->parry;
}
if(weap.ability == eItemAbil::EXPLODING_WEAPON) {
add_string_to_buf(" The weapon produces an explosion!");
if(PSD[SDF_GAME_SPEED] == 0)
@@ -787,6 +812,8 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
if(univ.party[who_att].has_abil_equip(eItemAbil::POISON_AUGMENT) < 24)
poison_amt += 2;
target.poison(poison_amt);
if(dynamic_cast<cPlayer*>(&target))
put_pc_screen();
move_to_zero(univ.party[who_att].status[eStatus::POISONED_WEAPON]);
}
}
@@ -1273,7 +1300,7 @@ void do_combat_cast(location target) {
default:
if(!(victim = univ.target_there(target, TARG_MONST)))
if(!(victim = univ.target_there(target)))
add_string_to_buf(" Nobody there.");
else {
cCreature* cur_monst = dynamic_cast<cCreature*>(victim);
@@ -1282,12 +1309,12 @@ void do_combat_cast(location target) {
switch(spell_being_cast) {
case eSpell::ACID_SPRAY:
store_m_type = 0;
cur_monst->acid(level);
victim->acid(level);
store_sound = 24;
break;
case eSpell::PARALYZE_BEAM:
store_m_type = 9;
cur_monst->sleep(eStatus::PARALYZED,500,0);
victim->sleep(eStatus::PARALYZED,500,0);
store_sound = 24;
break;
case eSpell::UNHOLY_RAVAGING:
@@ -1296,11 +1323,15 @@ void do_combat_cast(location target) {
r1 = get_ran(4,1,8);
r2 = get_ran(1,0,2);
damage_monst(targ_num, 7, r1, eDamageType::MAGIC,0);
cur_monst->slow(4 + r2);
cur_monst->poison(5 + r2);
victim->slow(4 + r2);
victim->poison(5 + r2);
break;
case eSpell::SCRY_MONSTER:
if(cur_monst == nullptr) {
add_string_to_buf(" Nobody there.");
break;
}
store_m_type = -1;
play_sound(52);
univ.party.m_noted[cur_monst->number] = true;
@@ -1309,12 +1340,21 @@ void do_combat_cast(location target) {
store_sound = 25;
break;
case eSpell::CAPTURE_SOUL:
if(cur_monst == nullptr) {
add_string_to_buf(" Nobody there.");
break;
}
store_m_type = 15;
record_monst(cur_monst);
store_sound = 25;
break;
case eSpell::MINDDUEL:
if(cur_monst == nullptr) {
// TODO: Support PC-on-PC mindduels? Might be no point though...
add_string_to_buf(" Nobody there.");
break;
}
store_m_type = -1;
if((cur_monst->mu == 0) && (cur_monst->cl == 0))
add_string_to_buf(" Can't duel: no magic.");
@@ -1334,118 +1374,135 @@ void do_combat_cast(location target) {
case eSpell::CHARM_FOE:
store_m_type = 14;
cur_monst->sleep(eStatus::CHARM,0,-1 * (bonus + caster.level / 8));
victim->sleep(eStatus::CHARM,0,-1 * (bonus + caster.level / 8));
store_sound = 24;
break;
case eSpell::DISEASE:
store_m_type = 0;
r1 = get_ran(1,0,1);
cur_monst->disease(2 + r1 + bonus);
victim->disease(2 + r1 + bonus);
store_sound = 24;
break;
case eSpell::STRENGTHEN_TARGET:
store_m_type = 14;
cur_monst->health += 20;
victim->heal(20);
store_sound = 55;
break;
case eSpell::DUMBFOUND:
store_m_type = 14;
cur_monst->dumbfound(1 + bonus / 3);
victim->dumbfound(1 + bonus / 3);
store_sound = 53;
break;
case eSpell::SCARE:
store_m_type = 11;
cur_monst->scare(get_ran(2 + bonus,1,6));
victim->scare(get_ran(2 + bonus,1,6));
store_sound = 54;
break;
case eSpell::FEAR:
store_m_type = 11;
cur_monst->scare(get_ran(min(20,caster.level / 2 + bonus),1,8));
victim->scare(get_ran(min(20,caster.level / 2 + bonus),1,8));
store_sound = 54;
break;
case eSpell::SLOW:
store_m_type = 11;
r1 = get_ran(1,0,1);
cur_monst->slow(2 + r1 + bonus);
victim->slow(2 + r1 + bonus);
store_sound = 25;
break;
case eSpell::POISON_MINOR: case eSpell::ARROWS_VENOM:
store_m_type = (spell_being_cast == eSpell::ARROWS_VENOM) ? 4 : 11;
cur_monst->poison(2 + bonus / 2);
victim->poison(2 + bonus / 2);
store_sound = 55;
break;
case eSpell::PARALYZE:
store_m_type = 9;
cur_monst->sleep(eStatus::PARALYZED,1000,-10);
victim->sleep(eStatus::PARALYZED,1000,-10);
store_sound = 25;
break;
case eSpell::POISON:
store_m_type = 11;
cur_monst->poison(4 + bonus / 2);
victim->poison(4 + bonus / 2);
store_sound = 55;
break;
case eSpell::POISON_MAJOR:
store_m_type = 11;
cur_monst->poison(8 + bonus / 2);
victim->poison(8 + bonus / 2);
store_sound = 55;
break;
case eSpell::STUMBLE:
store_m_type = 8;
cur_monst->curse(4 + bonus);
victim->curse(4 + bonus);
store_sound = 24;
break;
case eSpell::CURSE:
store_m_type = 8;
cur_monst->curse(2 + bonus);
victim->curse(2 + bonus);
store_sound = 24;
break;
case eSpell::HOLY_SCOURGE:
store_m_type = 8;
cur_monst->curse(2 + caster.level / 2);
victim->curse(2 + caster.level / 2);
store_sound = 24;
break;
case eSpell::TURN_UNDEAD: case eSpell::DISPEL_UNDEAD:
if(cur_monst->m_type != eRace::UNDEAD && cur_monst->m_type != eRace::SKELETAL) {
if(cur_monst != nullptr && cur_monst->m_type != eRace::UNDEAD && cur_monst->m_type != eRace::SKELETAL) {
add_string_to_buf(" Not undead.");
store_m_type = -1;
break;
} else if(cPlayer* who = dynamic_cast<cPlayer*>(victim)) {
if(who->race != eRace::UNDEAD && who->race != eRace::SKELETAL) {
add_string_to_buf(" Not undead.");
store_m_type = -1;
break;
}
}
store_m_type = 8;
r1 = get_ran(1,0,90);
if(r1 > hit_chance[minmax(0,19,bonus * 2 + level * 4 - (cur_monst->level / 2) + 3)])
if(r1 > hit_chance[minmax(0,19,bonus * 2 + level * 4 - (victim->get_level() / 2) + 3)])
add_string_to_buf(" Monster resisted.");
else {
r1 = get_ran((spell_being_cast == eSpell::TURN_UNDEAD) ? 2 : 6, 1, 14);
hit_space(cur_monst->cur_loc,r1,eDamageType::UNBLOCKABLE,0,current_pc);
size_t i_targ = univ.get_target_i(*victim);
if(i_targ < 100)
damage_pc(i_targ, r1, eDamageType::UNBLOCKABLE, eRace::UNKNOWN, 0);
else damage_monst(i_targ, current_pc, r1, eDamageType::UNBLOCKABLE, 0);
}
store_sound = 24;
break;
case eSpell::RAVAGE_SPIRIT:
if(cur_monst->m_type != eRace::DEMON) {
if(cur_monst != nullptr && cur_monst->m_type != eRace::DEMON) {
add_string_to_buf(" Not a demon.");
store_m_type = -1;
break;
} else if(cPlayer* who = dynamic_cast<cPlayer*>(victim)) {
if(who->race != eRace::DEMON) {
add_string_to_buf(" Not a demon.");
store_m_type = -1;
break;
}
}
r1 = get_ran(1,1,100);
if(r1 > hit_chance[minmax(0,19,level * 4 - cur_monst->level + 10)])
if(r1 > hit_chance[minmax(0,19,level * 4 - victim->get_level() + 10)])
add_string_to_buf(" Demon resisted.");
else {
r1 = get_ran(8 + bonus * 2, 1, 11);
if(univ.party[spell_caster].status[eStatus::DUMB] < 0)
r1 += -25 * univ.party[spell_caster].status[eStatus::DUMB] / 3;
hit_space(cur_monst->cur_loc,r1,eDamageType::UNBLOCKABLE,0,current_pc);
size_t i_targ = univ.get_target_i(*victim);
if(i_targ < 100)
damage_pc(i_targ, r1, eDamageType::UNBLOCKABLE, eRace::UNKNOWN, 0);
else damage_monst(i_targ, current_pc, r1, eDamageType::UNBLOCKABLE, 0);
}
store_sound = 24;
break;
@@ -1453,9 +1510,11 @@ void do_combat_cast(location target) {
add_string_to_buf(" Error: Spell " + (*spell_being_cast).name() + " not implemented for combat mode.", 4);
break;
}
if(store_m_type >= 0)
add_missile(target,store_m_type,1,
14 * (cur_monst->x_width - 1),18 * (cur_monst->y_width - 1));
if(store_m_type >= 0) {
int w = cur_monst ? cur_monst->x_width : 1;
int h = cur_monst ? cur_monst->y_width : 1;
add_missile(target,store_m_type,1, 14 * (w - 1),18 * (h - 1));
}
}
break;
@@ -1481,6 +1540,9 @@ void do_combat_cast(location target) {
handle_marked_damage();
combat_posing_monster = current_working_monster = -1;
if(dynamic_cast<cPlayer*>(victim))
put_pc_screen();
print_buf();
}
@@ -1717,6 +1779,8 @@ void fire_missile(location target) {
if(missile_firer.has_abil_equip(eItemAbil::POISON_AUGMENT) < 24)
poison_amt++;
victim->poison(poison_amt);
if(dynamic_cast<cPlayer*>(victim))
put_pc_screen();
}
if((ammo.ability == eItemAbil::STATUS_WEAPON) && (get_ran(1,0,1) == 1)) {
apply_weapon_status(eStatus(ammo.abil_data[1]), ammo.abil_data[0], r2 + spec_dam, *victim, "Missile");
@@ -2650,7 +2714,6 @@ void monster_attack(short who_att,iLiving* target) {
r1 += 5 * target->status[eStatus::BLESS_CURSE] - 15;
r1 += 5 * (attacker->status[eStatus::WEBS] / 3);
if(pc_target != nullptr) {
// TODO: Consider this stuff in PC-on-PC attacks
r1 += 5 * pc_target->stat_adj(eSkill::DEXTERITY);
r1 += pc_target->get_prot_level(eItemAbil::EVASION);
if(pc_target->parry < 100)
@@ -2706,6 +2769,8 @@ void monster_attack(short who_att,iLiving* target) {
if(i == 0 && attacker->status[eStatus::POISONED_WEAPON] > 0) {
short poison_amt = attacker->status[eStatus::POISONED_WEAPON];
target->poison(poison_amt);
if(dynamic_cast<cPlayer*>(target))
put_pc_screen();
move_to_zero(attacker->status[eStatus::POISONED_WEAPON]);
}
@@ -3087,14 +3152,18 @@ void monst_basic_abil(short m_num, std::pair<eMonstAbil,uAbility> abil, iLiving*
case eStatus::MARTYRS_SHIELD:
target->apply_status(abil.second.gen.stat, -abil.second.gen.strength);
break;
case eStatus::FORCECAGE:
target->sleep(abil.second.gen.stat, 8, abil.second.gen.strength);
if(target->status[eStatus::FORCECAGE] > 0)
univ.town.set_force_cage(target->get_loc().x, target->get_loc().y, true);
break;
// This only works on monsters
case eStatus::CHARM:
target->sleep(abil.second.gen.stat, univ.town.monst[m_num].attitude, abil.second.gen.strength);
break;
// These three don't make sense in this context
// These two don't make sense in this context
case eStatus::MAIN:
case eStatus::POISONED_WEAPON:
case eStatus::FORCECAGE:
return;
}
break;
@@ -3157,6 +3226,13 @@ void monst_basic_abil(short m_num, std::pair<eMonstAbil,uAbility> abil, iLiving*
case eMonstAbil::SPECIAL: case eMonstAbil::SPLITS: case eMonstAbil::SUMMON:
break;
}
if(pc_target != nullptr) {
put_pc_screen();
if(abil.first == eMonstAbil::STUN || abil.first == eMonstAbil::STATUS || abil.first == eMonstAbil::STATUS2) {
if(abil.second.gen.stat == eStatus::DUMB)
adjust_spell_menus();
}
}
}
bool monst_breathe(cCreature *caster,location targ_space,uAbility abil) {
@@ -3522,6 +3598,12 @@ bool monst_cast_mage(cCreature *caster,short targ) {
end_missile_anim();
handle_marked_damage();
if(dynamic_cast<cPlayer*>(&victim)) {
put_pc_screen();
if(spell == eSpell::DUMBFOUND)
adjust_spell_menus();
}
return acted;
}
@@ -3828,6 +3910,9 @@ bool monst_cast_priest(cCreature *caster,short targ) {
end_missile_anim();
handle_marked_damage();
if(dynamic_cast<cPlayer*>(&victim))
put_pc_screen();
return acted;
}
@@ -4112,6 +4197,7 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho
}
}
}
put_pc_screen();
fast_bang = 0;
@@ -4416,9 +4502,10 @@ void handle_disease() {
break;
case 8:
univ.party[i].dumbfound(3);
adjust_spell_menus();
break;
case 9: case 10:
add_string_to_buf(" " + univ.party[i].name + "unaffected.");
add_string_to_buf(" " + univ.party[i].name + " unaffected.");
break;
}
r1 = get_ran(1,0,7);
@@ -4904,6 +4991,7 @@ void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie)
i = get_ran(3,1,6);
univ.party[target].apply_status(eStatus::DUMB, i / -3);
univ.party[target].cur_sp += i * 2;
adjust_spell_menus();
}
break;
default:

View File

@@ -114,6 +114,7 @@ int main(int /*argc*/, char* argv[]) {
init_menubar(); // Do this first of all because otherwise a default File and Window menu will be seen
sync_prefs();
cUniverse::print_result = iLiving::print_result = add_string_to_buf;
cPlayer::give_help = give_help;
init_graph_tool();
Initialize();
init_fileio();

View File

@@ -1066,141 +1066,6 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon
return can_enter;
}
void cCreature::poison(int how_much) {
if(how_much > 0) {
how_much *= poison_res;
how_much /= 100;
}
apply_status(eStatus::POISON, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 4);
else
spell_note(34);
}
void cCreature::acid(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::ACID, how_much);
if(how_much >= 0)
spell_note(31);
else
spell_note(48);
}
void cCreature::slow(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::HASTE_SLOW, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 2);
else
spell_note(35);
}
void cCreature::curse(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::BLESS_CURSE, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 5);
else
spell_note(36);
}
void cCreature::web(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::WEBS, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 19);
else
spell_note(37);
}
void cCreature::scare(int how_much) {
how_much = magic_adjust(how_much);
morale -= how_much;
// TODO: I don't think there's currently any way to increase monster morale at the moment - add one!
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 1);
else
spell_note(47);
}
void cCreature::disease(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DISEASE, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 25);
else
spell_note(38);
}
void cCreature::dumbfound(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DUMB, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 22);
else
spell_note(39);
}
// For charm, amount is the resulting attitude of the charmed monster; if 0, attitude is 2.
void cCreature::sleep(eStatus which_status,int amount,int penalty) {
if(which_status != eStatus::CHARM && which_status != eStatus::FORCECAGE && amount < 0) {
status[which_status] -= amount;
if(which_status == eStatus::PARALYZED)
status[which_status] = max(0, status[which_status]);
return;
}
if((which_status == eStatus::ASLEEP) &&
(m_type == eRace::UNDEAD || m_type == eRace::SKELETAL || m_type == eRace::SLIME ||
m_type == eRace::STONE || m_type == eRace::PLANT))
return;
short r1 = get_ran(1,1,100);
if(magic_res > 0) {
r1 *= 100;
r1 /= magic_res;
} else r1 = 200;
r1 += penalty;
if(which_status == eStatus::ASLEEP)
r1 -= 25;
if(which_status == eStatus::PARALYZED)
r1 -= 15;
if(which_status == eStatus::ASLEEP && abil[eMonstAbil::FIELD].active && abil[eMonstAbil::FIELD].gen.fld == eFieldType::CLOUD_SLEEP)
return;
if(r1 > charm_odds[level / 2]) {
//one_sound(68);
spell_note(10);
}
else {
if(which_status == eStatus::CHARM) {
if(amount == 0 || amount > 3) amount = 2;
attitude = amount;
spell_note(23);
} else if(which_status == eStatus::FORCECAGE) {
status[eStatus::FORCECAGE] = 8;
univ.town.set_force_cage(cur_loc.x, cur_loc.y, true);
spell_note(52);
} else {
status[which_status] = amount;
if(which_status == eStatus::ASLEEP && (amount >= 0))
spell_note(28);
if(which_status == eStatus::PARALYZED && (amount >= 0))
spell_note(30);
if(amount < 0)
spell_note(40);
}
//one_sound(53);
}
}
void record_monst(cCreature *which_m) {
short r1;

View File

@@ -349,166 +349,6 @@ bool take_sp(short pc_num,short amt) {
return true;
}
void cPlayer::heal(int amt) {
if(!is_alive()) return;
if(cur_health >= max_health) return;
cur_health += amt;
if(cur_health > max_health)
cur_health = max_health;
if(cur_health < 0)
cur_health = 0;
}
void cPlayer::cure(int amt) {
if(!is_alive()) return;
if(status[eStatus::POISON] <= amt)
status[eStatus::POISON] = 0;
else status[eStatus::POISON] -= amt;
one_sound(51);
}
// if how_much < 0, bless
void cPlayer::curse(int how_much) {
if(!is_alive()) return;
if(how_much > 0)
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::BLESS_CURSE)) / 2;
apply_status(eStatus::BLESS_CURSE, -how_much);
if(how_much < 0)
add_string_to_buf(" " + name + " blessed.");
else if(how_much > 0)
add_string_to_buf(" " + name + " cursed.");
put_pc_screen();
if(how_much > 0)
give_help(59,0);
else if(how_much > 0)
give_help(34,0);
}
void cPlayer::dumbfound(int how_much) {
if(!is_alive()) return;
short r1 = get_ran(1,0,90);
if(has_abil_equip(eItemAbil::WILL) < 24) {
add_string_to_buf(" Ring of Will glows.");
r1 -= 10;
}
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DUMB)) / 4;
if(r1 < level)
how_much -= 2;
if(how_much <= 0) {
add_string_to_buf(" " + name + " saved.");
return;
}
apply_status(eStatus::DUMB, how_much);
add_string_to_buf(" " + name + " dumbfounded.");
one_sound(67);
put_pc_screen();
adjust_spell_menus();
give_help(28,0);
}
void cPlayer::disease(int how_much) {
if(is_alive()) return;
short r1 = get_ran(1,1,100);
if(r1 < level * 2)
how_much -= 2;
if(how_much <= 0) {
add_string_to_buf(" " + name + " saved.");
return;
}
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DISEASE)) / 2;
if(traits[eTrait::FRAIL] && how_much > 1)
how_much++;
if(traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0)
how_much++;
apply_status(eStatus::DISEASE, how_much);
add_string_to_buf(" " + name + " diseased.");
one_sound(66);
put_pc_screen();
give_help(29,0);
}
void cPlayer::sleep(eStatus what_type,int how_much,int adjust) {
if(what_type == eStatus::CHARM) return;
short level = 0;
if(!is_alive()) return;
if(how_much == 0) return;
if((what_type == eStatus::ASLEEP) &&
(race == eRace::UNDEAD || race == eRace::SKELETAL || race == eRace::SLIME ||
race == eRace::STONE || race == eRace::PLANT))
return;
if(what_type == eStatus::ASLEEP || what_type == eStatus::PARALYZED) {
how_much -= get_prot_level(eItemAbil::WILL) / 2;
level = get_prot_level(eItemAbil::FREE_ACTION);
how_much -= (what_type == eStatus::ASLEEP) ? level : level * 300;
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(what_type)) / 4;
}
short r1 = get_ran(1,1,100) + adjust;
if(r1 < 30 + level * 2)
how_much = -1;
if(what_type == eStatus::ASLEEP && (traits[eTrait::HIGHLY_ALERT] || status[eStatus::ASLEEP] < 0))
how_much = -1;
if(how_much <= 0) {
add_string_to_buf(" " + name + " resisted.");
return;
}
status[what_type] = how_much;
if(what_type == eStatus::FORCECAGE)
univ.town.set_force_cage(get_loc().x, get_loc().y, true);
if(what_type == eStatus::ASLEEP)
add_string_to_buf(" " + name + " falls asleep.");
else if(what_type == eStatus::FORCECAGE)
add_string_to_buf(" " + name + " is trapped!");
else add_string_to_buf(" " + name + " paralyzed.");
if(what_type == eStatus::ASLEEP)
play_sound(96);
else play_sound(90);
if(what_type != eStatus::FORCECAGE)
ap = 0;
put_pc_screen();
if(what_type == eStatus::ASLEEP)
give_help(30,0);
else if(what_type == eStatus::PARALYZED)
give_help(32,0);
}
// if how_much < 0, haste
void cPlayer::slow(int how_much) {
if(!is_alive()) return;
if(how_much > 0)
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::HASTE_SLOW)) / 2;
apply_status(eStatus::HASTE_SLOW, -how_much);
if(how_much < 0)
add_string_to_buf(" " + name + " hasted.");
else if(how_much > 0)
add_string_to_buf(" " + name + " slowed.");
put_pc_screen();
give_help(35,0);
}
void cPlayer::web(int how_much) {
if(!is_alive()) return;
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::WEBS)) / 2;
apply_status(eStatus::WEBS, how_much);
add_string_to_buf(" " + name + " webbed.");
one_sound(17);
put_pc_screen();
give_help(31,0);
}
void cPlayer::acid(int how_much) {
if(!is_alive()) return;
if(has_abil_equip(eItemAbil::STATUS_PROTECTION,int(eStatus::ACID)) < 24) {
add_string_to_buf(" " + name + " resists acid.");
return;
}
status[eStatus::ACID] += how_much;
add_string_to_buf(" " + name + " covered with acid!");
one_sound(42);
put_pc_screen();
}
void increase_light(short amt) {
short i;
location where;
@@ -529,16 +369,6 @@ void increase_light(short amt) {
put_pc_screen();
}
void cPlayer::restore_sp(int amt) {
if(!is_alive()) return;
if(cur_sp >= max_sp) return;
cur_sp += amt;
if(cur_sp > max_sp)
cur_sp = max_sp;
if(cur_sp < 0)
cur_sp = 0;
}
void award_party_xp(short amt) {
short i;
@@ -2260,24 +2090,6 @@ void print_spell_cast(eSpell spell,eSkill which) {
add_string_to_buf("Spell: " + name);
}
short cPlayer::stat_adj(eSkill which) const {
// 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
short tr = skill_bonus[skills[which]];
if(which == eSkill::INTELLIGENCE) {
if(traits[eTrait::MAGICALLY_APT])
tr++;
}
if(which == eSkill::STRENGTH) {
if(traits[eTrait::STRENGTH])
tr++;
}
// TODO: Use ability strength?
if(has_abil_equip(eItemAbil::BOOST_STAT,int(which)) < 24)
tr++;
return tr;
}
void start_town_targeting(eSpell s_num,short who_c,bool freebie,eSpellPat pat) {
add_string_to_buf(" Target spell.");
overall_mode = MODE_TOWN_TARGET;
@@ -2504,33 +2316,6 @@ bool flying() {
else return true;
}
void cPlayer::poison(int how_much) {
if(!is_alive()) return;
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::POISON)) / 2;
how_much -= get_prot_level(eItemAbil::FULL_PROTECTION) / 3;
if(traits[eTrait::FRAIL] && how_much > 1)
how_much++;
if(traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0)
how_much++;
if(how_much > 0) {
apply_status(eStatus::POISON, how_much);
add_string_to_buf(" " + name + " poisoned.");
one_sound(17);
give_help(33,0);
}
put_pc_screen();
}
void iLiving::void_sanctuary() {
if(status[eStatus::INVISIBLE] > 0) {
if(dynamic_cast<cPlayer*const>(this))
add_string_to_buf("You become visible!");
status[eStatus::INVISIBLE] = 0;
}
}
void hit_party(short how_much,eDamageType damage_type,short snd_type) {
short i;
bool dummy;

View File

@@ -30,6 +30,7 @@
#include "fileio.hpp"
#include <array>
#include "spell.hpp"
#include "boe.menus.h"
extern sf::RenderWindow mainPtr;
extern eGameMode overall_mode;
@@ -235,9 +236,9 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
r1 = get_ran(1,2,3);
univ.party[i].web(r1);
}
put_pc_screen();
}
else univ.party[current_pc].web(get_ran(1,2,3));
put_pc_screen();
univ.town.set_web(where_check.x,where_check.y,false);
}
if(univ.town.is_force_barr(where_check.x,where_check.y)) {
@@ -416,6 +417,8 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
case eStatus::FORCECAGE:
if(is_out()) break;
univ.party[i].sleep(eStatus::FORCECAGE,ter_flag1,ter_flag1 / 2);
if(univ.party[i].status[eStatus::FORCECAGE] > 0)
univ.town.set_force_cage(univ.party[i].get_loc().x, univ.party[i].get_loc().y, true);
// TODO: Do we need to process fields here? Or is it done after returning from this function?
break;
case eStatus::MAIN: case eStatus::CHARM: // These magic values are illegal in this context
@@ -424,6 +427,9 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
if(mode == eSpecCtx::COMBAT_MOVE) break; // only damage once in combat!
}
}
put_pc_screen();
if(ter_flag3 == int(eStatus::DUMB))
adjust_spell_menus();
//print_nums(1,which_pc,current_pc);
break;
case eTerSpec::CALL_SPECIAL: {
@@ -525,7 +531,6 @@ void check_fields(location where_check,eSpecCtx mode,cPlayer& which_pc) {
if(univ.town.is_sleep_cloud(where_check.x,where_check.y)) {
add_string_to_buf(" Sleep cloud!");
univ.party[current_pc].sleep(eStatus::ASLEEP,3,0);
put_pc_screen();
}
if(univ.town.is_fire_barr(where_check.x,where_check.y)) {
add_string_to_buf(" Magic barrier!");
@@ -541,6 +546,7 @@ void check_fields(location where_check,eSpecCtx mode,cPlayer& which_pc) {
add_string_to_buf(" Trapped in force cage!");
which_pc.status[eStatus::FORCECAGE] = 8;
} else which_pc.status[eStatus::FORCECAGE] = 0;
put_pc_screen();
}
void use_spec_item(short item) {
@@ -668,24 +674,24 @@ void use_item(short pc,short item) {
break;
case eStatus::BLESS_CURSE:
play_sound(4);
if(the_item.abil_harms()) {
ASB(" You feel awkward.");
if(!the_item.abil_harms()) {
ASB(" You feel blessed.");
str = str * -1;
}else ASB(" You feel blessed.");
}else ASB(" You feel awkward.");
if(the_item.abil_group())
univ.party.apply_status(status,str);
else univ.party[pc].apply_status(status,str);
univ.party.curse(str);
else univ.party[pc].curse(str);
break;
case eStatus::HASTE_SLOW:
// TODO: Is this the right sound?
play_sound(75);
if(the_item.abil_harms()) {
ASB(" You feel sluggish.");
if(!the_item.abil_harms()) {
ASB(" You feel speedy.");
str = str * -1;
}else ASB(" You feel speedy.");
}else ASB(" You feel sluggish.");
if(the_item.abil_group())
univ.party.apply_status(status,str);
else univ.party[pc].apply_status(status,str);
univ.party.slow(str);
else univ.party[pc].slow(str);
break;
case eStatus::INVULNERABLE:
// TODO: Is this the right sound?
@@ -700,6 +706,7 @@ void use_item(short pc,short item) {
break;
case eStatus::MAGIC_RESISTANCE:
// TODO: Is this the right sound?
// TODO: This ignores resistances if it's negative
play_sound(51);
if(the_item.abil_harms()) {
ASB(" You feel odd.");
@@ -717,8 +724,8 @@ void use_item(short pc,short item) {
str = str * -1;
}
if(the_item.abil_group())
univ.party.apply_status(status,str);
else univ.party[pc].apply_status(status,str);
univ.party.web(str);
else univ.party[pc].web(str);
break;
case eStatus::INVISIBLE:
// TODO: Is this the right sound?
@@ -801,6 +808,7 @@ void use_item(short pc,short item) {
univ.party.dumbfound(str);
break;
}
adjust_spell_menus();
break;
case eStatus::ASLEEP:
switch(type) {
@@ -869,6 +877,8 @@ void use_item(short pc,short item) {
break;
case eItemUse::HARM_ONE:
univ.party[pc].sleep(eStatus::FORCECAGE, str, str / 2);
if(univ.party[pc].status[eStatus::FORCECAGE] > 0)
univ.town.set_force_cage(univ.party[pc].get_loc().x, univ.party[pc].get_loc().y, true);
break;
case eItemUse::HELP_ALL:
for(i = 0; i < 6; i++)
@@ -876,6 +886,9 @@ void use_item(short pc,short item) {
break;
case eItemUse::HARM_ALL:
univ.party.sleep(eStatus::FORCECAGE, str, str / 2);
for(i = 0; i < 6; i++)
if(univ.party[i].status[eStatus::FORCECAGE] > 0)
univ.town.set_force_cage(univ.party[i].get_loc().x, univ.party[i].get_loc().y, true);
break;
}
break;
@@ -909,6 +922,8 @@ void use_item(short pc,short item) {
}
break;
}
if(the_item.abil_harms())
adjust_spell_menus();
break;
case eItemAbil::AFFECT_EXPERIENCE:
switch(type) {
@@ -2978,6 +2993,9 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
case eStatus::FORCECAGE:
break;
}
put_pc_screen();
if(spec.ex2a == int(eStatus::DUMB))
adjust_spell_menus();
break;
case eSpecType::AFFECT_STAT:
if(pc_num >= 100) break;

View File

@@ -16,6 +16,7 @@
#include "mathutil.hpp"
#include "dlogutil.hpp"
#include "winutil.hpp"
#include "boe.menus.h"
extern eGameMode overall_mode;
extern short current_pc,stat_window;
@@ -128,6 +129,7 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) {
case TRAP_DUMBFOUND:
add_string_to_buf(" You feel disoriented.");
univ.party.dumbfound(2 + trap_level * 2);
adjust_spell_menus();
break;
case TRAP_DISEASE:

View File

@@ -127,6 +127,140 @@ void cCreature::drain_sp(int drain) {
}
}
void cCreature::poison(int how_much) {
if(how_much > 0) {
how_much *= poison_res;
how_much /= 100;
}
apply_status(eStatus::POISON, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 4);
else
spell_note(34);
}
void cCreature::acid(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::ACID, how_much);
if(how_much >= 0)
spell_note(31);
else
spell_note(48);
}
void cCreature::slow(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::HASTE_SLOW, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 2);
else
spell_note(35);
}
void cCreature::curse(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::BLESS_CURSE, -how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 5);
else
spell_note(36);
}
void cCreature::web(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::WEBS, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 19);
else
spell_note(37);
}
void cCreature::scare(int how_much) {
how_much = magic_adjust(how_much);
morale -= how_much;
// TODO: I don't think there's currently any way to increase monster morale at the moment - add one!
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 1);
else
spell_note(47);
}
void cCreature::disease(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DISEASE, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 25);
else
spell_note(38);
}
void cCreature::dumbfound(int how_much) {
how_much = magic_adjust(how_much);
apply_status(eStatus::DUMB, how_much);
if(how_much >= 0)
spell_note((how_much == 0) ? 10 : 22);
else
spell_note(39);
}
// For charm, amount is the resulting attitude of the charmed monster; if 0, attitude is 2.
void cCreature::sleep(eStatus which_status,int amount,int penalty) {
if(which_status != eStatus::CHARM && which_status != eStatus::FORCECAGE && amount < 0) {
status[which_status] -= amount;
if(which_status == eStatus::PARALYZED)
status[which_status] = max(0, status[which_status]);
return;
}
if((which_status == eStatus::ASLEEP) &&
(m_type == eRace::UNDEAD || m_type == eRace::SKELETAL || m_type == eRace::SLIME ||
m_type == eRace::STONE || m_type == eRace::PLANT))
return;
short r1 = get_ran(1,1,100);
if(magic_res > 0) {
r1 *= 100;
r1 /= magic_res;
} else r1 = 200;
r1 += penalty;
if(which_status == eStatus::ASLEEP)
r1 -= 25;
if(which_status == eStatus::PARALYZED)
r1 -= 15;
if(which_status == eStatus::ASLEEP && abil[eMonstAbil::FIELD].active && abil[eMonstAbil::FIELD].gen.fld == eFieldType::CLOUD_SLEEP)
return;
if(r1 > charm_odds[level / 2]) {
//one_sound(68);
spell_note(10);
}
else {
if(which_status == eStatus::CHARM) {
if(amount == 0 || amount > 3) amount = 2;
attitude = amount;
spell_note(23);
} else if(which_status == eStatus::FORCECAGE) {
status[eStatus::FORCECAGE] = 8;
spell_note(52);
} else {
status[which_status] = amount;
if(which_status == eStatus::ASLEEP && (amount >= 0))
spell_note(28);
if(which_status == eStatus::PARALYZED && (amount >= 0))
spell_note(30);
if(amount < 0)
spell_note(40);
}
//one_sound(53);
}
}
bool cCreature::is_alive() const {
return active > 0;
}

View File

@@ -55,4 +55,9 @@ void iLiving::clear_bad_status() {
status[eStatus::MAGIC_RESISTANCE] = 0;
}
void iLiving::void_sanctuary() {
if(status[eStatus::INVISIBLE] > 0)
status[eStatus::INVISIBLE] = 0;
}
void(* iLiving::print_result)(std::string) = nullptr;

View File

@@ -17,6 +17,8 @@
#include "oldstructs.h"
#include "mathutil.hpp"
extern short skill_bonus[21];
void cPlayer::append(legacy::pc_record_type old){
int i;
main_status = (eMainStatus) old.main_status;
@@ -107,6 +109,232 @@ void cPlayer::scare(int) {
// TODO: Not implemented
}
void cPlayer::void_sanctuary() {
if(status[eStatus::INVISIBLE] > 0 && print_result)
print_result("You become visible!");
iLiving::void_sanctuary();
}
void cPlayer::heal(int amt) {
if(!is_alive()) return;
if(cur_health >= max_health) return;
cur_health += amt;
if(cur_health > max_health)
cur_health = max_health;
if(cur_health < 0)
cur_health = 0;
}
void cPlayer::cure(int amt) {
if(!is_alive()) return;
if(status[eStatus::POISON] <= amt)
status[eStatus::POISON] = 0;
else status[eStatus::POISON] -= amt;
one_sound(51);
}
// if how_much < 0, bless
void cPlayer::curse(int how_much) {
if(!is_alive()) return;
if(how_much > 0)
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::BLESS_CURSE)) / 2;
apply_status(eStatus::BLESS_CURSE, -how_much);
if(print_result) {
if(how_much < 0)
print_result(" " + name + " blessed.");
else if(how_much > 0)
print_result(" " + name + " cursed.");
}
if(give_help) {
if(how_much > 0)
give_help(59,0);
else if(how_much > 0)
give_help(34,0);
}
}
void cPlayer::dumbfound(int how_much) {
if(!is_alive()) return;
short r1 = get_ran(1,0,90);
if(has_abil_equip(eItemAbil::WILL) < 24) {
if(print_result)
print_result(" Ring of Will glows.");
r1 -= 10;
}
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DUMB)) / 4;
if(r1 < level)
how_much -= 2;
if(how_much <= 0) {
if(print_result)
print_result(" " + name + " saved.");
return;
}
apply_status(eStatus::DUMB, how_much);
if(print_result)
print_result(" " + name + " dumbfounded.");
one_sound(67);
if(give_help)
give_help(28,0);
}
void cPlayer::disease(int how_much) {
if(is_alive()) return;
short r1 = get_ran(1,1,100);
if(r1 < level * 2)
how_much -= 2;
if(how_much <= 0) {
if(print_result)
print_result(" " + name + " saved.");
return;
}
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DISEASE)) / 2;
if(traits[eTrait::FRAIL] && how_much > 1)
how_much++;
if(traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0)
how_much++;
apply_status(eStatus::DISEASE, how_much);
if(print_result)
print_result(" " + name + " diseased.");
one_sound(66);
if(give_help)
give_help(29,0);
}
void cPlayer::sleep(eStatus what_type,int how_much,int adjust) {
if(what_type == eStatus::CHARM) return;
short level = 0;
if(!is_alive()) return;
if(how_much == 0) return;
if((what_type == eStatus::ASLEEP) &&
(race == eRace::UNDEAD || race == eRace::SKELETAL || race == eRace::SLIME ||
race == eRace::STONE || race == eRace::PLANT))
return;
if(what_type == eStatus::ASLEEP || what_type == eStatus::PARALYZED) {
how_much -= get_prot_level(eItemAbil::WILL) / 2;
level = get_prot_level(eItemAbil::FREE_ACTION);
how_much -= (what_type == eStatus::ASLEEP) ? level : level * 300;
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(what_type)) / 4;
}
short r1 = get_ran(1,1,100) + adjust;
if(r1 < 30 + level * 2)
how_much = -1;
if(what_type == eStatus::ASLEEP && (traits[eTrait::HIGHLY_ALERT] || status[eStatus::ASLEEP] < 0))
how_much = -1;
if(how_much <= 0) {
if(print_result)
print_result(" " + name + " resisted.");
return;
}
status[what_type] = how_much;
if(print_result) {
if(what_type == eStatus::ASLEEP)
print_result(" " + name + " falls asleep.");
else if(what_type == eStatus::FORCECAGE)
print_result(" " + name + " is trapped!");
else print_result(" " + name + " paralyzed.");
}
if(what_type == eStatus::ASLEEP)
play_sound(96);
else play_sound(90);
if(what_type != eStatus::FORCECAGE)
ap = 0;
if(give_help) {
if(what_type == eStatus::ASLEEP)
give_help(30,0);
else if(what_type == eStatus::PARALYZED)
give_help(32,0);
}
}
// if how_much < 0, haste
void cPlayer::slow(int how_much) {
if(!is_alive()) return;
if(how_much > 0)
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::HASTE_SLOW)) / 2;
apply_status(eStatus::HASTE_SLOW, -how_much);
if(print_result) {
if(how_much < 0)
print_result(" " + name + " hasted.");
else if(how_much > 0)
print_result(" " + name + " slowed.");
}
if(give_help)
give_help(35,0);
}
void cPlayer::web(int how_much) {
if(!is_alive()) return;
if(how_much > 0)
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::WEBS)) / 2;
apply_status(eStatus::WEBS, how_much);
if(print_result)
print_result(" " + name + " webbed.");
one_sound(17);
give_help(31,0);
}
void cPlayer::acid(int how_much) {
if(!is_alive()) return;
if(has_abil_equip(eItemAbil::STATUS_PROTECTION,int(eStatus::ACID)) < 24) {
if(print_result)
print_result(" " + name + " resists acid.");
return;
}
status[eStatus::ACID] += how_much;
if(print_result)
print_result(" " + name + " covered with acid!");
one_sound(42);
}
void cPlayer::restore_sp(int amt) {
if(!is_alive()) return;
if(cur_sp >= max_sp) return;
cur_sp += amt;
if(cur_sp > max_sp)
cur_sp = max_sp;
if(cur_sp < 0)
cur_sp = 0;
}
void cPlayer::poison(int how_much) {
if(!is_alive()) return;
how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::POISON)) / 2;
how_much -= get_prot_level(eItemAbil::FULL_PROTECTION) / 3;
if(traits[eTrait::FRAIL] && how_much > 1)
how_much++;
if(traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0)
how_much++;
if(how_much > 0) {
apply_status(eStatus::POISON, how_much);
if(print_result)
print_result(" " + name + " poisoned.");
one_sound(17);
give_help(33,0);
}
}
short cPlayer::stat_adj(eSkill which) const {
// 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
short tr = skill_bonus[skills[which]];
if(which == eSkill::INTELLIGENCE) {
if(traits[eTrait::MAGICALLY_APT])
tr++;
}
if(which == eSkill::STRENGTH) {
if(traits[eTrait::STRENGTH])
tr++;
}
// TODO: Use ability strength?
if(has_abil_equip(eItemAbil::BOOST_STAT,int(which)) < 24)
tr++;
return tr;
}
bool cPlayer::is_alive() const {
return main_status == eMainStatus::ALIVE;
}
@@ -779,3 +1007,5 @@ std::istream& operator >> (std::istream& in, eMainStatus& e){
else e = eMainStatus::ABSENT;
return in;
}
void(* cPlayer::give_help)(short,short) = nullptr;

View File

@@ -28,6 +28,7 @@ class cParty;
class cPlayer : public iLiving {
cParty& party;
public:
static void(* give_help)(short,short);
eMainStatus main_status;
std::string name;
// HACK: This is only really marked mutable so that I can use operator[] from const methods
@@ -65,6 +66,7 @@ public:
location get_loc() const;
void finish_create();
void void_sanctuary();
void heal(int how_much);
void poison(int how_much);
void cure(int how_much);