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:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user