diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj index f04ad3f5..783a873d 100644 --- a/src/BoE.xcodeproj/project.pbxproj +++ b/src/BoE.xcodeproj/project.pbxproj @@ -124,6 +124,7 @@ 913D05BE0FA1EA0A00184C18 /* pc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D05BB0FA1EA0A00184C18 /* pc.cpp */; }; 913D6C050FC57A8E00E12527 /* boeresources.icns in Resources */ = {isa = PBXBuildFile; fileRef = 913D6C040FC57A8E00E12527 /* boeresources.icns */; }; 914698F81A73434400F20F5E /* shop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91FDB5791A4E774E00DE5983 /* shop.cpp */; }; + 914698FC1A74216F00F20F5E /* living.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914698FB1A7362D900F20F5E /* living.cpp */; }; 914701A718F62ABF008A6DC9 /* dungeon.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 914701A418F629D4008A6DC9 /* dungeon.ttf */; }; 914701A818F62AC0008A6DC9 /* maidenword.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 914701A518F629D4008A6DC9 /* maidenword.ttf */; }; 914B2AA318E7E507007B6799 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA118E7E500007B6799 /* Cocoa.framework */; }; @@ -581,6 +582,8 @@ 913D05BB0FA1EA0A00184C18 /* pc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pc.cpp; sourceTree = ""; }; 913D6C040FC57A8E00E12527 /* boeresources.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = boeresources.icns; sourceTree = ""; }; 913FB40A1A5C90840067B9D2 /* pictypes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = pictypes.hpp; sourceTree = ""; }; + 914698FA1A7362C200F20F5E /* living.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = living.hpp; sourceTree = ""; }; + 914698FB1A7362D900F20F5E /* living.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = living.cpp; sourceTree = ""; }; 914701A418F629D4008A6DC9 /* dungeon.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = dungeon.ttf; sourceTree = ""; }; 914701A518F629D4008A6DC9 /* maidenword.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = maidenword.ttf; sourceTree = ""; }; 914701A918F64A85008A6DC9 /* dialog.xsd */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = dialog.xsd; path = schemas/dialog.xsd; sourceTree = ""; }; @@ -873,6 +876,7 @@ children = ( 91AC620A0FA2853700EEAE67 /* creatlist.cpp */, 91279D3D0F9D1D6A007B0D52 /* item.cpp */, + 914698FB1A7362D900F20F5E /* living.cpp */, 91279BE10F9D0F73007B0D52 /* location.cpp */, 91279CC10F9D19DA007B0D52 /* monster.cpp */, 91E5C79D0F9F60FA00C21460 /* outdoors.cpp */, @@ -898,6 +902,7 @@ children = ( 91AC62090FA2853700EEAE67 /* creatlist.h */, 91279D3C0F9D1D6A007B0D52 /* item.h */, + 914698FA1A7362C200F20F5E /* living.hpp */, 91279BE00F9D0F73007B0D52 /* location.h */, 91279CC00F9D19DA007B0D52 /* monster.h */, 91E5C79C0F9F60FA00C21460 /* outdoors.h */, @@ -1490,6 +1495,7 @@ 91597A6F1A3C021400BE7BF9 /* spell.cpp in Sources */, 9179A4671A48683100FEF872 /* stack.cpp in Sources */, 91FDB57B1A4E77CA00DE5983 /* shop.cpp in Sources */, + 914698FC1A74216F00F20F5E /* living.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/boe.actions.cpp b/src/boe.actions.cpp index 235b670e..764e2efe 100644 --- a/src/boe.actions.cpp +++ b/src/boe.actions.cpp @@ -1513,7 +1513,7 @@ void initiate_outdoor_combat(short i) { draw_terrain(); // Is combat too easy? - if((party_total_level() > ((out_enc_lev_tot(i) * 5) / 3) ) && (out_enc_lev_tot(i) < 200) + if((univ.party.get_level() > ((out_enc_lev_tot(i) * 5) / 3) ) && (out_enc_lev_tot(i) < 200) && (univ.party.out_c[i].what_monst.cant_flee % 10 != 1)) { add_string_to_buf("Combat: Monsters fled! "); univ.party.out_c[i].exists = false; @@ -1772,19 +1772,7 @@ bool handle_keystroke(sf::Event& event){ case 'C': if(!in_scen_debug) break; - for(i = 0; i < 6; i++) { - univ.party[i].status[eStatus::POISON] = 0; - if(univ.party[i].status[eStatus::BLESS_CURSE] < 0) - univ.party[i].status[eStatus::BLESS_CURSE] = 0; - if(univ.party[i].status[eStatus::HASTE_SLOW] < 0) - univ.party[i].status[eStatus::HASTE_SLOW] = 0; - univ.party[i].status[eStatus::WEBS] = 0; - univ.party[i].status[eStatus::DISEASE] = 0; - univ.party[i].status[eStatus::DUMB] = 0; - univ.party[i].status[eStatus::ASLEEP] = 0; - univ.party[i].status[eStatus::PARALYZED] = 0; - univ.party[i].status[eStatus::ACID] = 0; - } + univ.party.clear_bad_status(); add_string_to_buf("Debug: You get cleaned up!"); print_buf(); put_pc_screen(); @@ -1833,8 +1821,8 @@ bool handle_keystroke(sf::Event& event){ if(isDead(univ.party[i].main_status)) univ.party[i].main_status = eMainStatus::ALIVE; } - heal_party(250); - restore_sp_party(100); + univ.party.heal(250); + univ.party.restore_sp(100); add_string_to_buf("Debug: Heal party."); print_buf(); put_pc_screen(); @@ -2184,8 +2172,8 @@ void do_rest(long length, int hp_restore, int mp_restore) { unsigned long age_before = univ.party.age; univ.party.age += length; if(!PSD[SDF_TIMERS_DURING_REST]) { - heal_party(hp_restore); - restore_sp_party(mp_restore); + univ.party.heal(hp_restore); + univ.party.restore_sp(mp_restore); put_pc_screen(); return; } @@ -2220,16 +2208,16 @@ void do_rest(long length, int hp_restore, int mp_restore) { if(length > 4000 || age_before / 4000 < univ.party.age / 4000) refresh_store_items(); // Heal party - heal_party(hp_restore); - restore_sp_party(mp_restore); + univ.party.heal(hp_restore); + univ.party.restore_sp(mp_restore); // Recuperation and chronic disease disads for(int i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) { if(univ.party[i].traits[eTrait::RECUPERATION] && univ.party[i].cur_health < univ.party[i].max_health) { - heal_pc(i,hp_restore / 5); + univ.party[i].heal(hp_restore / 5); } if(univ.party[i].traits[eTrait::CHRONIC_DISEASE] && get_ran(1,0,110) == 1) { - disease_pc(i,6); + univ.party[i].disease(6); } short item = univ.party[i].has_abil_equip(eItemAbil::REGENERATE); if(item < 24 && univ.party[i].cur_health < univ.party[i].max_health && (overall_mode > MODE_OUTDOORS || get_ran(1,0,10) == 5)){ @@ -2237,7 +2225,7 @@ void do_rest(long length, int hp_restore, int mp_restore) { if(univ.party[i].items[item].abil_data[0] / 3 == 0) j = get_ran(1,0,1); if(is_out()) j = j * 4; - heal_pc(i,j); + univ.party[i].heal(j); } } special_increase_age(length, true); @@ -2348,9 +2336,9 @@ void increase_age() { // Protection, etc. for(i = 0; i < 6; i++) { // Process some status things, and check if stats updated - if(univ.party[i].status[eStatus::INVULNERABLE] == 1 || univ.party[i].status[eStatus::MAGIC_RESISTANCE] == 1 + if(univ.party[i].status[eStatus::INVULNERABLE] == 1 || abs(univ.party[i].status[eStatus::MAGIC_RESISTANCE]) == 1 || univ.party[i].status[eStatus::INVISIBLE] == 1 || univ.party[i].status[eStatus::MARTYRS_SHIELD] == 1 - || univ.party[i].status[eStatus::ASLEEP] == 1 || univ.party[i].status[eStatus::PARALYZED] == 1) + || abs(univ.party[i].status[eStatus::ASLEEP]) == 1 || univ.party[i].status[eStatus::PARALYZED] == 1) update_stat = true; move_to_zero(univ.party[i].status[eStatus::INVULNERABLE]); move_to_zero(univ.party[i].status[eStatus::MAGIC_RESISTANCE]); @@ -2417,7 +2405,7 @@ void increase_age() { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE && univ.party[i].cur_health < univ.party[i].max_health) update_stat = true; - heal_party(2); + univ.party.heal(2); } } else { @@ -2425,7 +2413,7 @@ void increase_age() { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE && univ.party[i].cur_health < univ.party[i].max_health) update_stat = true; - heal_party(1); + univ.party.heal(1); } } if(is_out()) { @@ -2433,7 +2421,7 @@ void increase_age() { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE && univ.party[i].cur_sp < univ.party[i].max_sp) update_stat = true; - restore_sp_party(2); + univ.party.restore_sp(2); } } else { @@ -2441,7 +2429,7 @@ void increase_age() { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE && univ.party[i].cur_sp < univ.party[i].max_sp) update_stat = true; - restore_sp_party(1); + univ.party.restore_sp(1); } } @@ -2449,11 +2437,11 @@ void increase_age() { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) { if(univ.party[i].traits[eTrait::RECUPERATION] && get_ran(1,0,10) == 1 && univ.party[i].cur_health < univ.party[i].max_health) { - heal_pc(i,2); + univ.party[i].heal(2); update_stat = true; } if(univ.party[i].traits[eTrait::CHRONIC_DISEASE] && get_ran(1,0,110) == 1) { - disease_pc(i,4); + univ.party[i].disease(4); update_stat = true; } @@ -2474,7 +2462,7 @@ void increase_age() { if(univ.party[i].items[item].abil_data[0] / 3 == 0) j = get_ran(1,0,1); if(is_out()) j = j * 4; - heal_pc(i,j); + univ.party[i].heal(j); update_stat = true; } } diff --git a/src/boe.combat.cpp b/src/boe.combat.cpp index b26b8567..bf7451d7 100644 --- a/src/boe.combat.cpp +++ b/src/boe.combat.cpp @@ -351,7 +351,7 @@ void start_outdoor_combat(cOutdoors::cCreature encounter,ter_num_t in_which_terr for(i = 0; i < 6; i++) { univ.party[i].parry = 0; - univ.party[i].last_attacked = univ.town.monst.size() + 10; + univ.party[i].last_attacked = univ.town.monst.size() + 100; } univ.town.items.clear(); @@ -374,10 +374,11 @@ void start_outdoor_combat(cOutdoors::cCreature encounter,ter_num_t in_which_terr bool pc_combat_move(location destination) { std::string create_line; - short dir,monst_hit,s1,s2,i,monst_exist,switch_pc; + short monst_hit,s1,s2,i,monst_exist,switch_pc; bool keep_going = true,forced = false,check_f = false; location monst_loc,store_loc; short spec_num; + eDirection dir; monst_hit = monst_there(destination); @@ -430,8 +431,8 @@ bool pc_combat_move(location destination) { if((s2 == 2) && (s1 % 2 != 1)) make_town_hostile(); if(s2 == 2) { - univ.party[current_pc].last_attacked = monst_hit; - pc_attack(current_pc,monst_hit); + univ.party[current_pc].last_attacked = 100 + monst_hit; + pc_attack(current_pc,100 + monst_hit); return true; } } @@ -476,7 +477,6 @@ bool pc_combat_move(location destination) { // move if still alive if(univ.party[current_pc].main_status == eMainStatus::ALIVE) { - univ.party[current_pc].dir = set_direction(univ.party[current_pc].combat_pos,destination); univ.party[current_pc].combat_pos = destination; univ.party[current_pc].direction = dir; take_ap(1); @@ -512,7 +512,6 @@ void char_stand_ready() { void pc_attack(short who_att,short target) { short r1,r2,weap1 = 24, weap2 = 24,i,store_hp,skill_item; - cCreature *which_m; short hit_adj, dam_adj; // slice out bad attacks @@ -522,7 +521,7 @@ void pc_attack(short who_att,short target) { return; univ.party[who_att].last_attacked = target; - which_m = &univ.town.monst[target]; + iLiving& which_m = univ.get_target(target); for(i = 0; i < 24; i++) if(((univ.party[who_att].items[i].variety == eItemType::ONE_HANDED) || (univ.party[who_att].items[i].variety == eItemType::TWO_HANDED)) && @@ -532,13 +531,13 @@ void pc_attack(short who_att,short target) { else weap2 = i; } - hit_adj = (-5 * minmax(-8,8,univ.party[who_att].status[eStatus::BLESS_CURSE])) + 5 * minmax(-8,8,which_m->status[eStatus::BLESS_CURSE]) + hit_adj = (-5 * minmax(-8,8,univ.party[who_att].status[eStatus::BLESS_CURSE])) + 5 * minmax(-8,8,which_m.status[eStatus::BLESS_CURSE]) - stat_adj(who_att,eSkill::DEXTERITY) * 5 + (get_encumberance(who_att)) * 5; - dam_adj = minmax(-8,8,univ.party[who_att].status[eStatus::BLESS_CURSE]) - minmax(-8,8,which_m->status[eStatus::BLESS_CURSE]) + dam_adj = minmax(-8,8,univ.party[who_att].status[eStatus::BLESS_CURSE]) - minmax(-8,8,which_m.status[eStatus::BLESS_CURSE]) + stat_adj(who_att,eSkill::STRENGTH); - if(which_m->status[eStatus::ASLEEP] > 0 || which_m->status[eStatus::PARALYZED] > 0) { + if(which_m.status[eStatus::ASLEEP] > 0 || which_m.status[eStatus::PARALYZED] > 0) { hit_adj -= 80; dam_adj += 10; } @@ -555,7 +554,7 @@ void pc_attack(short who_att,short target) { void_sanctuary(who_att); - store_hp = univ.town.monst[target].health; + store_hp = which_m.get_health(); combat_posing_monster = current_working_monster = who_att; @@ -568,7 +567,7 @@ void pc_attack(short who_att,short target) { r2 = get_ran(1,1,4) + dam_adj; if(r1 <= hit_chance[univ.party[who_att].skill(eSkill::DEXTERITY)]) { - damage_monst(target, who_att, r2, 0,eDamageType::WEAPON,4); + damage_monst(target - 100, who_att, r2, 0,eDamageType::WEAPON,4); } else { draw_terrain(2); @@ -582,19 +581,14 @@ void pc_attack(short who_att,short target) { short weap_poisoned = univ.party[who_att].weap_poisoned; if(weap1 < 24) pc_attack_weapon(who_att, target, hit_adj, dam_adj, univ.party[who_att].items[weap1],weap2 < 24 ? 2 : 1,weap_poisoned == weap1); - if(weap2 < 24 && which_m->active > 0) + if(weap2 < 24 && which_m.is_alive()) pc_attack_weapon(who_att, target, hit_adj, dam_adj, univ.party[who_att].items[weap2],0,weap_poisoned == weap2); move_to_zero(univ.party[who_att].status[eStatus::POISONED_WEAPON]); take_ap(4); - if(store_hp - univ.town.monst[target].health > 0) { - cCreature& who = univ.town.monst[target]; - if(who.status[eStatus::MARTYRS_SHIELD] > 0 || (who.abil[eMonstAbil::MARTYRS_SHIELD].active && get_ran(1,1,1000) <= who.abil[eMonstAbil::MARTYRS_SHIELD].special.extra1)) { - int how_much = store_hp - who.health; - if(who.abil[eMonstAbil::MARTYRS_SHIELD].active) { - how_much *= who.abil[eMonstAbil::MARTYRS_SHIELD].special.extra2; - how_much /= 100; - } + if(store_hp - which_m.get_health() > 0) { + if(which_m.is_shielded()) { + int how_much = which_m.get_shared_dmg(store_hp - which_m.get_health()); add_string_to_buf(" Shares damage! "); damage_pc(who_att, how_much, eDamageType::MAGIC,eRace::UNKNOWN,0); } @@ -603,8 +597,7 @@ void pc_attack(short who_att,short target) { } static void apply_weapon_status(eStatus status, int how_much, int dmg, int who, std::string weap_type) { - cCreature* which_m; - if(who >= 100) which_m = &univ.town.monst[who - 100]; + iLiving& which_m = univ.get_target(who); switch(status) { // TODO: It should be possible to make monsters support magic resistance and invulnerability, at least. // Maybe also poisoned weapon and invisibility. @@ -612,84 +605,70 @@ static void apply_weapon_status(eStatus status, int how_much, int dmg, int who, case eStatus::INVISIBLE: if(who >= 100) break; // Not supported by monsters add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura."); - univ.party[who].apply_status(eStatus::INVISIBLE, how_much / -2); + which_m.apply_status(eStatus::INVISIBLE, how_much / -2); break; case eStatus::MAGIC_RESISTANCE: if(who >= 100) break; // Not supported by monsters add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura."); - univ.party[who].apply_status(eStatus::MAGIC_RESISTANCE, how_much / -2); + which_m.apply_status(eStatus::MAGIC_RESISTANCE, how_much / -2); break; case eStatus::INVULNERABLE: if(who >= 100) break; // Not supported by monsters add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura."); - univ.party[who].apply_status(eStatus::INVULNERABLE, how_much / -2); + which_m.apply_status(eStatus::INVULNERABLE, how_much / -2); break; case eStatus::POISONED_WEAPON: if(who >= 100) break; // Not supported by monsters add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura."); - univ.party[who].apply_status(eStatus::POISONED_WEAPON, how_much / -2); + which_m.apply_status(eStatus::POISONED_WEAPON, how_much / -2); break; case eStatus::POISON: add_string_to_buf(" " + weap_type + " drips venom."); - if(who < 6) poison_pc(who, how_much / 2); - else poison_monst(which_m, how_much / 2); + which_m.poison(how_much / 2); break; case eStatus::ACID: add_string_to_buf(" " + weap_type + " drips acid."); - if(who < 6) acid_pc(who, how_much / 2); - else acid_monst(which_m, how_much / 2); + which_m.acid(how_much / 2); break; case eStatus::BLESS_CURSE: add_string_to_buf(" " + weap_type + " leaks a dark aura."); - if(who < 6) curse_pc(who, how_much / 2); - else curse_monst(which_m, how_much / 2); + which_m.curse(how_much / 2); break; case eStatus::HASTE_SLOW: add_string_to_buf(" " + weap_type + " leaks a smoky aura."); - if(who < 6) slow_pc(who, how_much / 2); - else slow_monst(which_m, how_much / 2); + which_m.slow(how_much / 2); break; case eStatus::WEBS: add_string_to_buf(" " + weap_type + " drips goo."); - if(who < 6) web_pc(who, how_much / 1); - else web_monst(which_m, how_much / 2); + which_m.web(how_much / 2); break; case eStatus::DISEASE: add_string_to_buf(" " + weap_type + " drips bile."); - if(who < 6) disease_pc(who, how_much / 2); - else disease_monst(which_m, how_much / 2); + which_m.disease(how_much / 2); break; case eStatus::DUMB: add_string_to_buf(" " + weap_type + " leaks a misty aura."); - if(who < 6) dumbfound_pc(who, how_much / 2); - else dumbfound_monst(which_m, how_much / 2); + which_m.dumbfound(how_much / 2); break; case eStatus::ASLEEP: add_string_to_buf(" " + weap_type + " emits coruscating lights."); - if(who < 6) sleep_pc(who, how_much / 2, eStatus::ASLEEP, 20 + dmg); - else charm_monst(which_m, 20 + dmg, eStatus::ASLEEP, how_much / 2); + which_m.sleep(eStatus::ASLEEP, how_much / 2, 20 + dmg); break; case eStatus::PARALYZED: add_string_to_buf(" " + weap_type + " emits a purple flash."); - if(who < 6) sleep_pc(who, how_much / 2, eStatus::PARALYZED, 20 + dmg); - else charm_monst(which_m, 20 + dmg, eStatus::PARALYZED, how_much / 2); + which_m.sleep(eStatus::PARALYZED, how_much / 2, 20 + dmg); break; case eStatus::CHARM: - if(who < 6) break; add_string_to_buf(" " + weap_type + " leaks a bright aura."); - // Higher penalty means more likely to resist. - charm_monst(which_m, 20 + dmg - how_much / 2, eStatus::CHARM, 0); + which_m.sleep(eStatus::CHARM, 0, 20 + dmg - how_much / 2); break; case eStatus::FORCECAGE: add_string_to_buf(" " + weap_type + " emits a green flash."); - if(who < 6) sleep_pc(who, 0, eStatus::FORCECAGE, dmg - how_much / 2); - else charm_monst(which_m, dmg - how_much / 2, eStatus::FORCECAGE, 0); + which_m.sleep(eStatus::FORCECAGE, 0, dmg - how_much / 2); break; case eStatus::MARTYRS_SHIELD: add_string_to_buf(" " + weap_type + " leaks an odd-coloured aura."); - if(who < 6) univ.party[who].apply_status(eStatus::MARTYRS_SHIELD, how_much / -2); - else which_m->status[eStatus::MARTYRS_SHIELD] -= how_much / 2; - // TODO: Maybe clip it to 0? + which_m.apply_status(eStatus::MARTYRS_SHIELD, how_much / -2); break; } } @@ -697,7 +676,7 @@ static void apply_weapon_status(eStatus status, int how_much, int dmg, int who, // primary: 0 - secondary weapon, 1 - primary (and only) weapon, 2 - primary of two weapons void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cItem& weap,short primary,bool do_poison) { short r1, r2; - cCreature* which_m = &univ.town.monst[target]; + iLiving& which_m = univ.get_target(target); eSkill what_skill = weap.weap_type; // safety valve @@ -732,7 +711,7 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt else pause(5); play_sound(5); start_missile_anim(); - place_spell_pattern(radius2, which_m->cur_loc, eDamageType(weap.abil_data[1]), weap.abil_data[0] * 2, who_att); + place_spell_pattern(radius2, which_m.get_loc(), eDamageType(weap.abil_data[1]), weap.abil_data[0] * 2, who_att); do_explosion_anim(5,0); end_missile_anim(); handle_marked_damage(); @@ -743,44 +722,47 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt if(dmg_tp != eDamageType::UNBLOCKABLE) std::swap(spec_dam, bonus_dam); if(primary) { + bool splits = false; + if(cCreature* who = dynamic_cast(&which_m)) + splits = who->abil[eMonstAbil::SPLITS].active; // assassinate r1 = get_ran(1,1,100); 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(assassin - which_m->level,0)]) { + if((univ.party[who_att].level >= which_m.get_level() - 1) && assassin >= which_m.get_level() / 2 + && !splits) // Can't assassinate splitters + if(r1 < hit_chance[max(assassin - which_m.get_level(),0)]) { add_string_to_buf(" You assassinate."); spec_dam += r2; } } if(weap.ability == eItemAbil::HEALING_WEAPON) { ASB(" There is a flash of light."); - which_m->health = min(which_m->health + r2, which_m->m_health); + which_m.heal(r2); } else switch(what_skill) { case eSkill::EDGED_WEAPONS: if(weap.item_level < 8) - damage_monst(target, who_att, r2, spec_dam, eDamageType::WEAPON,1); - else damage_monst(target, who_att, r2, spec_dam, eDamageType::WEAPON,2); + damage_monst(target - 100, who_att, r2, spec_dam, eDamageType::WEAPON,1); + else damage_monst(target - 100, who_att, r2, spec_dam, eDamageType::WEAPON,2); break; case eSkill::BASHING_WEAPONS: - damage_monst(target, who_att, r2, spec_dam, eDamageType::WEAPON,4); + damage_monst(target - 100, who_att, r2, spec_dam, eDamageType::WEAPON,4); break; case eSkill::POLE_WEAPONS: - damage_monst(target, who_att, r2, spec_dam, eDamageType::WEAPON,3); + damage_monst(target - 100, who_att, r2, spec_dam, eDamageType::WEAPON,3); break; default: // TODO: Not sure what sound to play for unconventional weapons, but let's just go with the generic "ouch" for now - damage_monst(target, who_att, r2, spec_dam, eDamageType::WEAPON, 0); + damage_monst(target - 100, who_att, r2, spec_dam, eDamageType::WEAPON, 0); break; } if(bonus_dam) - damage_monst(target, who_att, bonus_dam, 0, dmg_tp, 0); + damage_monst(target - 100, who_att, bonus_dam, 0, dmg_tp, 0); if(do_poison) { // poison if(univ.party[who_att].status[eStatus::POISONED_WEAPON] > 0) { short poison_amt = univ.party[who_att].status[eStatus::POISONED_WEAPON]; if(univ.party[who_att].has_abil_equip(eItemAbil::POISON_AUGMENT) < 24) poison_amt += 2; - poison_monst(which_m,poison_amt); + which_m.poison(poison_amt); move_to_zero(univ.party[who_att].status[eStatus::POISONED_WEAPON]); } } @@ -788,27 +770,23 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt apply_weapon_status(eStatus(weap.abil_data[1]), weap.abil_data[0], r2 + spec_dam, target + 100, "Blade"); } else if(weap.ability == eItemAbil::SOULSUCKER && get_ran(1,0,1) == 1) { add_string_to_buf(" Blade drains life."); - heal_pc(who_att,weap.abil_data[0] / 2); - } else if(weap.ability == eItemAbil::ANTIMAGIC_WEAPON && which_m->mu + which_m->cl > 0 && get_ran(1,0,1) == 1) { - short drain = weap.abil_data[0]; - magic_adjust(which_m, &drain); - if(drain > 0) { + univ.party[who_att].heal(weap.abil_data[0] / 2); + } else if(weap.ability == eItemAbil::ANTIMAGIC_WEAPON) { + short before = which_m.get_magic(); + which_m.drain_sp(weap.abil_data[0]); + if(before > which_m.get_magic()) { add_string_to_buf(" Blade drains energy."); - if(which_m->mu > 0 && which_m->mp > 4) - drain = min(which_m->mp, drain / 3); - else if(which_m->cl > 0 && which_m->mp > 10) - drain = min(which_m->mp, drain / 2); - which_m->mp -= drain; - restore_sp_pc(who_att, drain / 3); + univ.party[who_att].restore_sp((before > which_m.get_magic()) / 3); } } else if(weap.ability == eItemAbil::WEAPON_CALL_SPECIAL) { short s1,s2,s3; univ.party.force_ptr(21, 301, 5); univ.party.force_ptr(22, 301, 6); univ.party.force_ptr(20, 301, 7); - PSD[SDF_SPEC_TARGLOC_X] = which_m->cur_loc.x; - PSD[SDF_SPEC_TARGLOC_Y] = which_m->cur_loc.y; - PSD[SDF_SPEC_TARGET] = 100 + target; // ready to be passed to SELECT_TARGET node + PSD[SDF_SPEC_TARGLOC_X] = which_m.get_loc().x; + PSD[SDF_SPEC_TARGLOC_Y] = which_m.get_loc().y; + PSD[SDF_SPEC_TARGET] = target; // ready to be passed to SELECT_TARGET node + if(PSD[SDF_SPEC_TARGET] < 6) PSD[SDF_SPEC_TARGET] += 11; run_special(eSpecCtx::ATTACKING_MELEE, 0, weap.abil_data[0],univ.party[who_att].combat_pos, &s1, &s2, &s3); } } @@ -823,21 +801,25 @@ void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cIt } -short calc_spec_dam(eItemAbil abil,short abil_str,short abil_dat,cCreature* monst,eDamageType& dmg_type) { +short calc_spec_dam(eItemAbil abil,short abil_str,short abil_dat,iLiving& monst,eDamageType& dmg_type) { short store = 0; - switch(abil) { - case eItemAbil::DAMAGING_WEAPON: + if(abil == eItemAbil::DAMAGING_WEAPON) { store += get_ran(abil_str,1,6); if(abil == eItemAbil::DAMAGING_WEAPON) dmg_type = eDamageType(abil_dat); else dmg_type = eDamageType::FIRE; - break; - case eItemAbil::SLAYER_WEAPON: + } else if(abil == eItemAbil::SLAYER_WEAPON) { + eRace race = eRace::UNKNOWN; + if(cCreature* who = dynamic_cast(&monst)) + race = who->m_type; + else if(cPlayer* who = dynamic_cast(&monst)) + race = who->race; + if(race == eRace::UNKNOWN) return 0; // Slith, nephilim, and vahnatai are affected by humanoid-bane weapons as well as their individual banes - if(abil_dat == int(eRace::HUMANOID) && (monst->m_type == eRace::SLITH || monst->m_type == eRace::NEPHIL || monst->m_type == eRace::VAHNATAI)); - else if(monst->m_type != eRace(abil_dat)) - break; + if(abil_dat == int(eRace::HUMANOID) && (race == eRace::SLITH || race == eRace::NEPHIL || race == eRace::VAHNATAI)); + else if(race != eRace(abil_dat)) + return 0; store += abil_str; switch(eRace(abil_dat)) { case eRace::DEMON: @@ -859,10 +841,8 @@ short calc_spec_dam(eItemAbil abil,short abil_str,short abil_dat,cCreature* mons store *= 7; break; } - break; - case eItemAbil::CAUSES_FEAR: - if(monst) scare_monst(monst,abil_str * 10); - break; + } else if(abil == eItemAbil::CAUSES_FEAR) { + monst.scare(abil_str * 10); } return store; } @@ -1236,12 +1216,12 @@ void do_combat_cast(location target) { switch(spell_being_cast) { case eSpell::ACID_SPRAY: store_m_type = 0; - acid_monst(cur_monst,level); + cur_monst->acid(level); store_sound = 24; break; case eSpell::PARALYZE_BEAM: store_m_type = 9; - charm_monst(cur_monst,0,eStatus::PARALYZED,500); + cur_monst->sleep(eStatus::PARALYZED,500,0); store_sound = 24; break; case eSpell::UNHOLY_RAVAGING: @@ -1250,8 +1230,8 @@ void do_combat_cast(location target) { r1 = get_ran(4,1,8); r2 = get_ran(1,0,2); damage_monst(targ_num, 7, r1, 0, eDamageType::MAGIC,0); - slow_monst(cur_monst, 4 + r2); - poison_monst(cur_monst, 5 + r2); + cur_monst->slow(4 + r2); + cur_monst->poison(5 + r2); break; case eSpell::SCRY_MONSTER: @@ -1288,14 +1268,14 @@ void do_combat_cast(location target) { case eSpell::CHARM_FOE: store_m_type = 14; - charm_monst(cur_monst,-1 * (bonus + univ.party[current_pc].level / 8),eStatus::CHARM,0); + cur_monst->sleep(eStatus::CHARM,0,-1 * (bonus + univ.party[current_pc].level / 8)); store_sound = 24; break; case eSpell::DISEASE: store_m_type = 0; r1 = get_ran(1,0,1); - disease_monst(cur_monst,2 + r1 + bonus); + cur_monst->disease(2 + r1 + bonus); store_sound = 24; break; @@ -1307,64 +1287,64 @@ void do_combat_cast(location target) { case eSpell::DUMBFOUND: store_m_type = 14; - dumbfound_monst(cur_monst,1 + bonus / 3); + cur_monst->dumbfound(1 + bonus / 3); store_sound = 53; break; case eSpell::SCARE: store_m_type = 11; - scare_monst(cur_monst,get_ran(2 + bonus,1,6)); + cur_monst->scare(get_ran(2 + bonus,1,6)); store_sound = 54; break; case eSpell::FEAR: store_m_type = 11; - scare_monst(cur_monst,get_ran(min(20,univ.party[current_pc].level / 2 + bonus),1,8)); + cur_monst->scare(get_ran(min(20,univ.party[current_pc].level / 2 + bonus),1,8)); store_sound = 54; break; case eSpell::SLOW: store_m_type = 11; r1 = get_ran(1,0,1); - slow_monst(cur_monst,2 + r1 + bonus); + cur_monst->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; - poison_monst(cur_monst,2 + bonus / 2); + cur_monst->poison(2 + bonus / 2); store_sound = 55; break; case eSpell::PARALYZE: store_m_type = 9; - charm_monst(cur_monst,-10,eStatus::PARALYZED,1000); + cur_monst->sleep(eStatus::PARALYZED,1000,-10); store_sound = 25; break; case eSpell::POISON: store_m_type = 11; - poison_monst(cur_monst,4 + bonus / 2); + cur_monst->poison(4 + bonus / 2); store_sound = 55; break; case eSpell::POISON_MAJOR: store_m_type = 11; - poison_monst(cur_monst,8 + bonus / 2); + cur_monst->poison(8 + bonus / 2); store_sound = 55; break; case eSpell::STUMBLE: store_m_type = 8; - curse_monst(cur_monst,4 + bonus); + cur_monst->curse(4 + bonus); store_sound = 24; break; case eSpell::CURSE: store_m_type = 8; - curse_monst(cur_monst,2 + bonus); + cur_monst->curse(2 + bonus); store_sound = 24; break; case eSpell::HOLY_SCOURGE: store_m_type = 8; - curse_monst(cur_monst,2 + univ.party[current_pc].level / 2); + cur_monst->curse(2 + univ.party[current_pc].level / 2); store_sound = 24; break; @@ -1644,7 +1624,7 @@ void fire_missile(location target) { eDamageType dmg_tp = eDamageType::UNBLOCKABLE; short bonus_dam = 0; cItem& missile = univ.party[missile_firer].items[ammo_inv_slot]; - spec_dam = calc_spec_dam(missile.ability,missile.abil_data[0],missile.abil_data[1],cur_monst,dmg_tp); + spec_dam = calc_spec_dam(missile.ability,missile.abil_data[0],missile.abil_data[1],*cur_monst,dmg_tp); if(dmg_tp != eDamageType::UNBLOCKABLE) std::swap(bonus_dam, spec_dam); if(univ.party[missile_firer].items[ammo_inv_slot].ability == eItemAbil::HEALING_WEAPON) { ASB(" There is a flash of light."); @@ -1657,24 +1637,20 @@ void fire_missile(location target) { poison_amt = univ.party[missile_firer].status[eStatus::POISONED_WEAPON]; if(univ.party[missile_firer].has_abil_equip(eItemAbil::POISON_AUGMENT) < 24) poison_amt++; - poison_monst(cur_monst,poison_amt); + cur_monst->poison(poison_amt); } if((missile.ability == eItemAbil::STATUS_WEAPON) && (get_ran(1,0,1) == 1)) { apply_weapon_status(eStatus(missile.abil_data[1]), missile.abil_data[0], r2 + spec_dam, targ_monst + 100, "Missile"); } else if(missile.ability == eItemAbil::SOULSUCKER && get_ran(1,0,1) == 1) { add_string_to_buf(" Missile drains life."); - heal_pc(missile_firer,missile.abil_data[0] / 2); - } else if(missile.ability == eItemAbil::ANTIMAGIC_WEAPON && cur_monst->mu + cur_monst->cl > 0 && get_ran(1,0,1) == 1) { - short drain = missile.abil_data[0]; - magic_adjust(cur_monst, &drain); - if(drain > 0) { + univ.party[missile_firer].heal(missile.abil_data[0] / 2); + } else if(missile.ability == eItemAbil::ANTIMAGIC_WEAPON) { + short before = cur_monst->get_magic(); + if(mu + cl > 0 && get_ran(1,0,1) == 1) + cur_monst->drain_sp(missile.abil_data[0]); + if(before > cur_monst->get_magic()) { add_string_to_buf(" Missile drains energy."); - if(cur_monst->mu > 0 && cur_monst->mp > 4) - drain = min(cur_monst->mp, drain / 3); - else if(cur_monst->cl > 0 && cur_monst->mp > 10) - drain = min(cur_monst->mp, drain / 2); - cur_monst->mp -= drain; - restore_sp_pc(missile_firer, drain / 3); + univ.party[missile_firer].restore_sp((before > cur_monst->get_magic()) / 3); } } if(cur_monst->abil[eMonstAbil::HIT_TRIGGER].active) { @@ -1690,11 +1666,11 @@ void fire_missile(location target) { } else if((targ_monst = pc_there(target)) < 6) { eDamageType dmg_tp = eDamageType::UNBLOCKABLE; cItem& missile = univ.party[missile_firer].items[ammo_inv_slot]; - spec_dam = calc_spec_dam(missile.ability,missile.abil_data[0],missile.abil_data[1],nullptr,dmg_tp); + spec_dam = calc_spec_dam(missile.ability,missile.abil_data[0],missile.abil_data[1],univ.party[targ_monst],dmg_tp); eRace race = univ.party[missile_firer].race; if(univ.party[current_pc].items[ammo_inv_slot].ability == eItemAbil::HEALING_WEAPON) { ASB(" There is a flash of light."); - heal_pc(targ_monst,r2); + univ.party[targ_monst].heal(r2); } else damage_pc(targ_monst, r2, eDamageType::WEAPON, race, 0); if(spec_dam > 0) damage_pc(targ_monst, spec_dam, dmg_tp, race, 0); @@ -1703,26 +1679,22 @@ void fire_missile(location target) { poison_amt = univ.party[missile_firer].status[eStatus::POISONED_WEAPON]; if(univ.party[missile_firer].has_abil_equip(eItemAbil::POISON_AUGMENT) < 24) poison_amt++; - poison_pc(targ_monst,poison_amt); + univ.party[targ_monst].poison(poison_amt); } if((missile.ability == eItemAbil::STATUS_WEAPON) && (get_ran(1,0,1) == 1)) { apply_weapon_status(eStatus(missile.abil_data[1]), missile.abil_data[0], r2 + spec_dam, targ_monst, "Missile"); } else if(missile.ability == eItemAbil::SOULSUCKER && get_ran(1,0,1) == 1) { add_string_to_buf(" Missile drains life."); - heal_pc(missile_firer,missile.abil_data[0] / 2); - } else if(missile.ability == eItemAbil::ANTIMAGIC_WEAPON && - univ.party[targ_monst].skill(eSkill::MAGE_SPELLS) + univ.party[targ_monst].skill(eSkill::PRIEST_SPELLS) > 0 && - get_ran(1,0,1) == 1) { - short drain = missile.abil_data[0]; - magic_adjust(cur_monst, &drain); - if(drain > 0) { + univ.party[missile_firer].heal(missile.abil_data[0] / 2); + } else if(missile.ability == eItemAbil::ANTIMAGIC_WEAPON) { + cPlayer& which_m = univ.party[targ_monst]; + short before = which_m.get_magic(); + if(which_m.skill(eSkill::MAGE_SPELLS) + which_m.skill(eSkill::PRIEST_SPELLS) > 0 && + get_ran(1,0,1) == 1) + which_m.drain_sp(missile.abil_data[0]); + if(before > which_m.get_magic()) { add_string_to_buf(" Missile drains energy."); - if(univ.party[targ_monst].skill(eSkill::MAGE_SPELLS) > 0 && univ.party[targ_monst].cur_sp > 4) - drain = min(univ.party[targ_monst].cur_sp, drain / 3); - else if(univ.party[targ_monst].skill(eSkill::PRIEST_SPELLS) > 0 && univ.party[targ_monst].cur_sp > 10) - drain = min(univ.party[targ_monst].cur_sp, drain / 2); - univ.party[targ_monst].cur_sp -= drain; - restore_sp_pc(missile_firer, drain / 3); + univ.party[missile_firer].restore_sp((before > which_m.get_magic()) / 3); } } else if(missile.ability == eItemAbil::WEAPON_CALL_SPECIAL) { short s1,s2,s3; @@ -1900,7 +1872,7 @@ void combat_run_monst() { move_to_zero(univ.party.status[ePartyStatus::STEALTH]); if((item = univ.party[i].has_abil_equip(eItemAbil::REGENERATE)) < 24) { update_stat = true; - heal_pc(i,get_ran(1,0,univ.party[i].items[item].item_level + 1)); + univ.party[i].heal(get_ran(1,0,univ.party[i].items[item].item_level + 1)); } } for(i = 0; i < 6; i++) @@ -2076,7 +2048,7 @@ void do_monster_turn() { if((cur_monst->summoned % 100) == 1) { cur_monst->active = 0; cur_monst->ap = 0; - monst_spell_note(cur_monst->number,17); + cur_monst->spell_note(17); } move_to_zero(cur_monst->summoned); } @@ -2348,7 +2320,7 @@ void do_monster_turn() { if(univ.party[k].parry > 99 && monst_adjacent(univ.party[k].combat_pos,i) && (cur_monst->active > 0)) { univ.party[k].parry = 0; - pc_attack(k,i); + pc_attack(k,100 + i); } } @@ -2359,7 +2331,7 @@ void do_monster_turn() { if(univ.party[k].parry > 99 && monst_adjacent(univ.party[k].combat_pos,i) && (cur_monst->active > 0) && (cur_monst->attitude % 2 == 1)) { univ.party[k].parry = 0; - pc_attack(k,i); + pc_attack(k,100 + i); } } @@ -2387,7 +2359,7 @@ void do_monster_turn() { && (pc_adj[k]) && (cur_monst->attitude % 2 == 1) && (cur_monst->active > 0) && univ.party[k].status[eStatus::INVISIBLE] == 0) { combat_posing_monster = current_working_monster = k; - pc_attack(k,i); + pc_attack(k,100 + i); combat_posing_monster = current_working_monster = 100 + i; pc_adj[k] = false; } @@ -2416,7 +2388,7 @@ void do_monster_turn() { if(what_summon) r1 = get_ran(1, abil.summon.min, abil.summon.max); else r1 = 0; if(r1 && summon_monster(what_summon, cur_monst->cur_loc,abil.summon.len,cur_monst->attitude)) { - monst_spell_note(cur_monst->number,33); + cur_monst->spell_note(33); play_sound(61); bool failed = false; while(--r1 && !failed) { @@ -2467,7 +2439,7 @@ void do_monster_turn() { } if(cur_monst->status[eStatus::ASLEEP] == 1) - monst_spell_note(cur_monst->number,29); + cur_monst->spell_note(29); move_to_zero(cur_monst->status[eStatus::ASLEEP]); move_to_zero(cur_monst->status[eStatus::PARALYZED]); @@ -2492,10 +2464,10 @@ void do_monster_turn() { } k = get_ran(1,1,5); switch(k) { - case 1: case 2: poison_monst(cur_monst, 2);break; - case 3: slow_monst(cur_monst,2); break; - case 4: curse_monst(cur_monst,2); break; - case 5: scare_monst(cur_monst,10); break; + case 1: case 2: cur_monst->poison(2); break; + case 3: cur_monst->slow(2); break; + case 4: cur_monst->curse(2); break; + case 5: cur_monst->scare(10); break; } if(get_ran(1,1,6) < 4) cur_monst->status[eStatus::DISEASE]--; @@ -2504,8 +2476,7 @@ void do_monster_turn() { } if(univ.party.age % 4 == 0) { - if(cur_monst->mp < cur_monst->max_mp) - cur_monst->mp += 2; + cur_monst->restore_sp(2); move_to_zero(cur_monst->status[eStatus::DUMB]); } } // end take care of monsters @@ -2598,11 +2569,8 @@ void monster_attack_pc(short who_att,short target) { damaged_message(store_hp - univ.party[target].cur_health, attacker->a[i].type); - int martyr1 = univ.party[target].status[eStatus::MARTYRS_SHIELD]; - int martyr2 = univ.party[target].get_prot_level(eItemAbil::MARTYRS_SHIELD); - if(martyr1 + martyr2 > 0) { - int dmg = store_hp - univ.party[target].cur_health; - if(get_ran(1,1,20) < martyr2) dmg += max(1, martyr2 / 5); + if(univ.party[target].is_shielded()) { + int dmg = univ.party[target].get_shared_dmg(store_hp - univ.party[target].get_health()); add_string_to_buf(" Shares damage! "); damage_monst(who_att, 6, dmg, 0, eDamageType::MAGIC,0); } @@ -2859,31 +2827,31 @@ void monst_fire_missile(short m_num,short bless,std::pair a case eMonstMissile::BOLT: snd = 12; if(target < 100) add_string_to_buf(" Shoots at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 12); + else m_target->spell_note(12); break; case eMonstMissile::SPEAR: if(target < 100) add_string_to_buf(" Throws spear at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 13); + else m_target->spell_note(13); break; case eMonstMissile::RAZORDISK: if(target < 100) add_string_to_buf(" Throws razordisk at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 15); + else m_target->spell_note(15); break; case eMonstMissile::SPINE: if(target < 100) add_string_to_buf(" Fires spines at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 32); + else m_target->spell_note(32); break; case eMonstMissile::DART: if(target < 100) add_string_to_buf(" Throws dart at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 53); + else m_target->spell_note(53); break; case eMonstMissile::ROCK: if(target < 100) add_string_to_buf(" Throws rock at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 14); + else m_target->spell_note(14); break; case eMonstMissile::KNIFE: if(target < 100) add_string_to_buf(" Throws knife at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 54); + else m_target->spell_note(54); break; } if(abil.second.missile.type == eMonstMissile::ARROW || abil.second.missile.type == eMonstMissile::BOLT) @@ -2910,12 +2878,12 @@ void monst_fire_missile(short m_num,short bless,std::pair a // TODO: Should we pass in the monster's actual race here? damage_pc(target,r2,eDamageType::WEAPON,eRace::UNKNOWN,13); } else { - monst_spell_note(m_target->number, 16); + m_target->spell_note(16); damage_monst(target - 100,7,r2,0,eDamageType::WEAPON,13); } } else { if(target < 100) add_string_to_buf(" Misses " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number,18); + else m_target->spell_note(18); } if(target < 100) { int spec_item = univ.party[target].has_abil_equip(eItemAbil::HIT_CALL_SPECIAL); @@ -2942,12 +2910,12 @@ void monst_fire_missile(short m_num,short bless,std::pair a } } else if(abil.first == eMonstAbil::MISSILE_WEB) { if(target < 100) add_string_to_buf(" Throws web at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 58); + else m_target->spell_note(58); run_a_missile(source, targ_space, 8, 0, 14, 0, 0, 100); web_space(targ_space.x, targ_space.y); } else if(abil.first == eMonstAbil::RAY_HEAT) { if(target < 100) add_string_to_buf(" Hits " + univ.party[target].name + " with heat ray!"); - else monst_spell_note(m_target->number, 55); + else m_target->spell_note(55); run_a_missile(source, targ_space, 13, 0, 51, 0, 0, 100); uAbility proxy = {true}; proxy.gen.strength = abil.second.special.extra3; @@ -2974,23 +2942,23 @@ void monst_fire_missile(short m_num,short bless,std::pair a case eMonstGen::RAY: snd = 51; if(target < 100) add_string_to_buf(" Fires ray at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 55); + else m_target->spell_note(55); break; case eMonstGen::GAZE: snd = 43; if(target < 100) add_string_to_buf(" Gazes at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 56); + else m_target->spell_note(56); break; case eMonstGen::BREATH: snd = 44; if(target < 100) add_string_to_buf(" Breathes on " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 57); + else m_target->spell_note(57); break; case eMonstGen::SPIT: path_type = 1; snd = 64; if(target < 100) add_string_to_buf(" Spits at " + univ.party[target].name + '.'); - else monst_spell_note(m_target->number, 59); + else m_target->spell_note(59); break; } if(abil.second.gen.pic < 0) play_sound(snd); @@ -3001,20 +2969,11 @@ void monst_fire_missile(short m_num,short bless,std::pair a void monst_basic_abil(short m_num, std::pair abil, short target) { int i, r1; - cCreature* m_target; - location targ_space; if(target == 6) return; - if(target >= 100) { - m_target = &univ.town.monst[m_num]; - targ_space = univ.town.monst[target - 100].cur_loc; - if(univ.town.monst[target - 100].active == 0) - return; - } else { - targ_space = (is_combat()) ? univ.party[target].combat_pos : univ.town.p_loc; - if(univ.party[target].main_status != eMainStatus::ALIVE) - return; - } + iLiving& m_target = univ.get_target(target); + location targ_space = m_target.get_loc(); + if(!m_target.is_alive()) return; switch(abil.first) { case eMonstAbil::DAMAGE: case eMonstAbil::DAMAGE2: // Determine die size @@ -3025,8 +2984,7 @@ void monst_basic_abil(short m_num, std::pair abil, short ta i = 10; r1 = get_ran(abil.second.gen.strength, 1, i); start_missile_anim(); - if(target < 100) damage_pc(target, r1, abil.second.gen.dmg, eRace::UNKNOWN, 0); - else damage_monst(target - 100, 7, r1, 0, abil.second.gen.dmg, 0); + damage_target(target, r1, abil.second.gen.dmg); do_explosion_anim(5, 0); end_missile_anim(); handle_marked_damage(); @@ -3041,49 +2999,39 @@ void monst_basic_abil(short m_num, std::pair abil, short ta if(abil.second.gen.type == eMonstGen::TOUCH) i = abil.second.gen.stat == eStatus::ASLEEP ? -15 : -5; else i = univ.town.monst[m_num].level / 2; - if(target < 100) sleep_pc(target, abil.second.gen.strength, abil.second.gen.stat, i); - else charm_monst(m_target, i, abil.second.gen.stat, abil.second.gen.strength); + m_target.sleep(abil.second.gen.stat, abil.second.gen.strength, i); break; case eStatus::ACID: - if(target < 100) acid_pc(target, abil.second.gen.strength); - else acid_monst(m_target, abil.second.gen.strength); + m_target.acid(abil.second.gen.strength); break; case eStatus::POISON: - if(target < 100) poison_pc(target, abil.second.gen.strength); - else poison_monst(m_target, abil.second.gen.strength); + m_target.poison(abil.second.gen.strength); break; case eStatus::BLESS_CURSE: - if(target < 100) curse_pc(target, abil.second.gen.strength); - else curse_monst(m_target, abil.second.gen.strength); + m_target.curse(abil.second.gen.strength); break; case eStatus::HASTE_SLOW: - if(target < 100) slow_pc(target, abil.second.gen.strength); - else slow_monst(m_target, abil.second.gen.strength); + m_target.slow(abil.second.gen.strength); break; case eStatus::WEBS: - if(target < 100) web_pc(target, abil.second.gen.strength); - else web_monst(m_target, abil.second.gen.strength); + m_target.web(abil.second.gen.strength); break; case eStatus::DISEASE: - if(target < 100) disease_pc(target, abil.second.gen.strength); - else disease_monst(m_target, abil.second.gen.strength); + m_target.disease(abil.second.gen.strength); break; case eStatus::DUMB: - if(target < 100) dumbfound_pc(target, abil.second.gen.strength); - else dumbfound_monst(m_target, abil.second.gen.strength); + m_target.dumbfound(abil.second.gen.strength); break; // These only work on PCs case eStatus::INVULNERABLE: case eStatus::MAGIC_RESISTANCE: case eStatus::INVISIBLE: case eStatus::MARTYRS_SHIELD: // TODO: Wait what? This one works for monsters! - if(target < 100) - univ.party[target].apply_status(abil.second.gen.stat, -abil.second.gen.strength); + m_target.apply_status(abil.second.gen.stat, -abil.second.gen.strength); break; // This only works on monsters case eStatus::CHARM: - if(target >= 100) - charm_monst(m_target, abil.second.gen.strength, eStatus::CHARM, univ.town.monst[m_num].attitude); + m_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 case eStatus::MAIN: @@ -3094,8 +3042,7 @@ void monst_basic_abil(short m_num, std::pair abil, short ta break; case eMonstAbil::PETRIFY: i = univ.town.monst[m_num].level * abil.second.gen.strength / 100; - if(target < 100) petrify_pc(target, i); - else petrify_monst(m_target, i); + m_target.petrify(i); break; case eMonstAbil::DRAIN_SP: if(target < 100) { @@ -3103,10 +3050,11 @@ void monst_basic_abil(short m_num, std::pair abil, short ta univ.party[target].cur_sp *= abil.second.gen.strength; univ.party[target].cur_sp /= 100; } else { - monst_spell_note(m_target->number,11); + cCreature* who = dynamic_cast(&m_target); + who->spell_note(11); // TODO: If mp < 4 it used to set monster's skill to 1. Should that be restored? - m_target->mp *= abil.second.gen.strength; - m_target->mp /= 100; + who->mp *= abil.second.gen.strength; + who->mp /= 100; } break; case eMonstAbil::DRAIN_XP: @@ -3175,7 +3123,7 @@ bool monst_breathe(cCreature *caster,location targ_space,uAbility abil) { bool monst_cast_mage(cCreature *caster,short targ) { short r1,j,i,level,target_levels,friend_levels_near,x; bool acted = false; - location target,vict_loc,ashes_loc,l; + location target,ashes_loc,l; cCreature *affected; const eSpell caster_array[7][18] = { { @@ -3277,11 +3225,8 @@ bool monst_cast_mage(cCreature *caster,short targ) { targ = 6; } - if(targ < 6) { - vict_loc = (is_combat()) ? univ.party[targ].combat_pos : univ.town.p_loc; - } - if(targ >= 100) - vict_loc = univ.town.monst[targ - 100].cur_loc; + iLiving& victim = univ.get_target(targ); + location vict_loc = victim.get_loc(); // check antimagic if(targ == 6 && univ.town.is_antimagic(target.x,target.y)) @@ -3327,11 +3272,11 @@ bool monst_cast_mage(cCreature *caster,short targ) { break; case eSpell::HASTE_MINOR: play_sound(25); - slow_monst(caster, -2); + caster->slow(-2); break; case eSpell::STRENGTH: play_sound(25); - curse_monst(caster, -3); + caster->curse(-3); break; case eSpell::CLOUD_FLAME: run_a_missile(l,vict_loc,2,1,11,0,0,80); @@ -3345,21 +3290,15 @@ bool monst_cast_mage(cCreature *caster,short targ) { break; case eSpell::POISON_MINOR: run_a_missile(l,vict_loc,11,0,25,0,0,80); - if(targ < 6) - poison_pc(targ,2 + get_ran(1,0,caster->level / 2)); - else poison_monst(&univ.town.monst[targ - 100],2 + get_ran(1,0,caster->level / 2)); + victim.poison(2 + get_ran(1,0,caster->level / 2)); break; case eSpell::SLOW: run_a_missile(l,vict_loc,15,0,25,0,0,80); - if(targ < 6) - slow_pc(targ,2 + caster->level / 2); - else slow_monst(&univ.town.monst[targ - 100],2 + caster->level / 2); + victim.slow(2 + caster->level / 2); break; case eSpell::DUMBFOUND: run_a_missile(l,vict_loc,14,0,25,0,0,80); - if(targ < 6) - dumbfound_pc(targ,2); - else dumbfound_monst(&univ.town.monst[targ - 100],2); + victim.dumbfound(2); break; case eSpell::CLOUD_STINK: run_a_missile(l,target,0,0,25,0,0,80); @@ -3423,9 +3362,7 @@ bool monst_cast_mage(cCreature *caster,short targ) { case eSpell::POISON: run_a_missile(l,vict_loc,11,0,25,0,0,80); x = get_ran(1,0,caster->level / 2); - if(targ < 6) - poison_pc(targ,4 + x); - else poison_monst(&univ.town.monst[targ - 100],4 + x); + victim.poison(4 + x); break; case eSpell::ICE_BOLT: run_a_missile(l,vict_loc,6,1,11,0,0,80); @@ -3438,14 +3375,14 @@ bool monst_cast_mage(cCreature *caster,short targ) { if(caster->attitude % 2 == 1) for(i = 0; i < 6; i++) if(pc_near(i,caster->cur_loc,8)) - slow_pc(i,2 + caster->level / 4); + univ.party[i].slow(2 + caster->level / 4); for(i = 0; i < univ.town.monst.size(); i++) { if((univ.town.monst[i].active != 0) && (((univ.town.monst[i].attitude % 2 == 1) && (caster->attitude % 2 != 1)) || ((univ.town.monst[i].attitude % 2 != 1) && (caster->attitude % 2 == 1)) || ((univ.town.monst[i].attitude % 2 == 1) && (caster->attitude != univ.town.monst[i].attitude))) && (dist(caster->cur_loc,univ.town.monst[i].cur_loc) <= 7)) - slow_monst(&univ.town.monst[i],2 + caster->level / 4); + univ.town.monst[i].slow(2 + caster->level / 4); } break; case eSpell::HASTE_MAJOR: @@ -3454,7 +3391,7 @@ bool monst_cast_mage(cCreature *caster,short targ) { if((monst_near(i,caster->cur_loc,8,0)) && (caster->attitude == univ.town.monst[i].attitude)) { affected = &univ.town.monst[i]; - slow_monst(affected, -3); + affected->slow(-3); } play_sound(4); break; @@ -3473,9 +3410,7 @@ bool monst_cast_mage(cCreature *caster,short targ) { case eSpell::POISON_MAJOR: run_a_missile(l,vict_loc,11,1,11,0,0,80); x = get_ran(1,1,2); - if(targ < 6) - poison_pc(targ,6 + x); - else poison_monst(&univ.town.monst[targ - 100],6 + x); + victim.poison(6 + x); break; case eSpell::KILL: run_a_missile(l,vict_loc,9,1,11,0,0,80); @@ -3499,7 +3434,7 @@ bool monst_cast_mage(cCreature *caster,short targ) { affected = &univ.town.monst[i]; affected->health += get_ran(2,1,10); r1 = get_ran(3,1,4); - curse_monst(affected, -r1); + affected->curse(-r1); affected->status[eStatus::WEBS] = 0; if(affected->status[eStatus::HASTE_SLOW] < 0) affected->status[eStatus::HASTE_SLOW] = 0; @@ -3526,7 +3461,7 @@ bool monst_cast_mage(cCreature *caster,short targ) { bool monst_cast_priest(cCreature *caster,short targ) { short r1,r2,i,x,level,target_levels,friend_levels_near; bool acted = false; - location target,vict_loc,l; + location target,l; cCreature *affected; eSpell caster_array[7][10] = { { @@ -3602,10 +3537,14 @@ bool monst_cast_priest(cCreature *caster,short targ) { } if(area_effects.count(spell) > 0) targ = 6; + + iLiving& victim = univ.get_target(targ); + location vict_loc = victim.get_loc(); if(targ < 6) vict_loc = (is_town()) ? univ.town.p_loc : univ.party[targ].combat_pos; if(targ >= 100) vict_loc = univ.town.monst[targ - 100].cur_loc; + if(targ == 6 && univ.town.is_antimagic(target.x,target.y)) return false; if(targ < 6 && univ.town.is_antimagic(univ.party[targ].combat_pos.x,univ.party[targ].combat_pos.y)) @@ -3653,15 +3592,13 @@ bool monst_cast_priest(cCreature *caster,short targ) { break; case eSpell::BLESS_MINOR: case eSpell::BLESS: play_sound(24); - curse_monst(caster, -(spell == eSpell::BLESS ? 5 : 3)); + caster->curse(-(spell == eSpell::BLESS ? 5 : 3)); play_sound(4); break; case eSpell::CURSE: run_a_missile(l,vict_loc,8,0,24,0,0,80); x = get_ran(1,0,1); - if(targ < 6) - curse_pc(targ,2 + x); - else curse_monst(&univ.town.monst[targ - 100],2 + x); + victim.curse(2 + x); break; case eSpell::WOUND: run_a_missile(l,vict_loc,8,0,24,0,0,80); @@ -3680,23 +3617,22 @@ bool monst_cast_priest(cCreature *caster,short targ) { case eSpell::DISEASE: run_a_missile(l,vict_loc,11,0,24,0,0,80); x = get_ran(1,0,2); - if(targ < 6) - disease_pc(targ,2 + x); - else disease_monst(&univ.town.monst[targ - 100],2 + x); + victim.disease(2 + x); break; case eSpell::HOLY_SCOURGE: run_a_missile(l,vict_loc,15,0,24,0,0,80); + // TODO: Why are PCs and monsters affected in different amounts? if(targ < 6) { r1 = get_ran(1,0,2); - slow_pc(targ,2 + r1); + victim.slow(2 + r1); r1 = get_ran(1,0,2); - curse_pc(targ,3 + r1); + victim.curse(3 + r1); } else { r1 = get_ran(1,0,2); - slow_monst(&univ.town.monst[targ - 100],r1); + victim.slow(r1); r1 = get_ran(1,0,2); - curse_monst(&univ.town.monst[targ - 100],r1); + victim.curse(r1); } break; case eSpell::SMITE: @@ -3741,9 +3677,9 @@ bool monst_cast_priest(cCreature *caster,short targ) { for(i = 0; i < 6; i++) if(pc_near(i,caster->cur_loc,8)) { if(spell == eSpell::CURSE_ALL) - curse_pc(i,2 + r1); + univ.party[i].curse(2 + r1); if(spell == eSpell::PESTILENCE) - disease_pc(i,2 + r2); + univ.party[i].disease(2 + r2); } for(i = 0; i < univ.town.monst.size(); i++) { if((univ.town.monst[i].active != 0) && @@ -3752,9 +3688,9 @@ bool monst_cast_priest(cCreature *caster,short targ) { ((univ.town.monst[i].attitude % 2 == 1) && (caster->attitude != univ.town.monst[i].attitude))) && (dist(caster->cur_loc,univ.town.monst[i].cur_loc) <= 7)) { if(spell == eSpell::CURSE_ALL) - curse_monst(&univ.town.monst[i],2 + r1); + univ.town.monst[i].curse(2 + r1); if(spell == eSpell::PESTILENCE) - disease_monst(&univ.town.monst[i],2 + r2); + univ.town.monst[i].disease(2 + r2); } } break; @@ -3767,7 +3703,7 @@ bool monst_cast_priest(cCreature *caster,short targ) { case eSpell::HEAL_MAJOR: r1 = get_ran(5,1,6) + 3; break; case eSpell::HEAL_ALL: r1 = 50; break; } - caster->health = min(caster->health + r1, caster->m_health); + caster->heal(r1); break; case eSpell::BLESS_PARTY: case eSpell::REVIVE_ALL: play_sound(24); @@ -3778,7 +3714,7 @@ bool monst_cast_priest(cCreature *caster,short targ) { (caster->attitude == univ.town.monst[i].attitude)) { affected = &univ.town.monst[i]; if(spell == eSpell::BLESS_PARTY) - curse_monst(affected, -r1); + affected->curse(-r1); if(spell == eSpell::REVIVE_ALL) affected->health += r1; } @@ -3796,26 +3732,13 @@ bool monst_cast_priest(cCreature *caster,short targ) { r1 = get_ran(4,1,8); r2 = get_ran(1,0,2); damage_target(targ,r1,eDamageType::MAGIC); - if(targ < 6) { - slow_pc(targ,6); - poison_pc(targ,5 + r2); - } - else { - slow_monst(&univ.town.monst[targ - 100],6); - poison_monst(&univ.town.monst[targ - 100],5 + r2); - } + victim.slow(6); + victim.poison(5 + r2); break; case eSpell::AVATAR: play_sound(24); - monst_spell_note(caster->number,26); - caster->health = caster->m_health; - caster->status[eStatus::BLESS_CURSE] = 8; - caster->status[eStatus::POISON] = 0; - caster->status[eStatus::HASTE_SLOW] = 8; - caster->status[eStatus::WEBS] = 0; - caster->status[eStatus::DISEASE] = 0; - caster->status[eStatus::DUMB] = 0; - caster->status[eStatus::MARTYRS_SHIELD] = 8; + caster->spell_note(26); + caster->avatar(); break; case eSpell::DIVINE_THUD: run_a_missile(l,target,9,0,11,0,0,80); @@ -4140,7 +4063,7 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho continue; switch(effect) { case FIELD_WEB: - web_monst(which_m,3); + which_m->web(3); break; case WALL_FORCE: r1 = get_ran(3,1,6); @@ -4151,7 +4074,7 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho damage_monst(k, who_hit, r1,0, eDamageType::FIRE,0); break; case CLOUD_STINK: - curse_monst(which_m,get_ran(1,1,2)); + which_m->curse(get_ran(1,1,2)); break; case WALL_ICE: r1 = get_ran(3,1,6); @@ -4162,7 +4085,7 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho damage_monst(k, who_hit, r1,0, eDamageType::WEAPON,0); break; case CLOUD_SLEEP: - charm_monst(which_m,0,eStatus::ASLEEP,3); + which_m->sleep(eStatus::ASLEEP,3,0); break; case OBJECT_BLOCK: r1 = get_ran(6,1,8); @@ -4402,19 +4325,19 @@ void handle_disease() { r1 = get_ran(1,1,10); switch(r1) { case 1: case 2: - poison_pc(i,2); + univ.party[i].poison(2); break; case 3: case 4: - slow_pc(i,2); + univ.party[i].slow(2); break; case 5: drain_pc(i,5); break; case 6: case 7: - curse_pc(i,3); + univ.party[i].curse(3); break; case 8: - dumbfound_pc(i,3); + univ.party[i].dumbfound(3); break; case 9: case 10: add_string_to_buf(" " + univ.party[i].name + "unaffected."); @@ -4504,6 +4427,7 @@ void end_combat() { univ.party[i].status[eStatus::POISONED_WEAPON] = 0; univ.party[i].status[eStatus::BLESS_CURSE] = 0; univ.party[i].status[eStatus::HASTE_SLOW] = 0; + univ.party[i].combat_pos = {-1,-1}; } if(which_combat_type == 0) { overall_mode = MODE_OUTDOORS; @@ -4621,7 +4545,7 @@ void combat_immed_mage_cast(short current_pc, eSpell spell_num, bool freebie) { case eSpell::STRENGTH: c_line += " stronger."; - curse_pc(target, -3); + univ.party[target].curse(-3); store_m_type = 8; break; case eSpell::RESIST_MAGIC: @@ -4632,7 +4556,7 @@ void combat_immed_mage_cast(short current_pc, eSpell spell_num, bool freebie) { default: i = (spell_num == eSpell::HASTE_MINOR) ? 2 : max(2,univ.party[current_pc].level / 2 + bonus); - slow_pc(target, -i); + univ.party[target].slow(-i); c_line += " hasted."; store_m_type = 8; break; @@ -4650,10 +4574,10 @@ void combat_immed_mage_cast(short current_pc, eSpell spell_num, bool freebie) { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) { - slow_pc(i, -(spell_num == eSpell::HASTE_MAJOR ? 1 + univ.party[current_pc].level / 8 + bonus : 3 + bonus)); + univ.party[i].slow(-(spell_num == eSpell::HASTE_MAJOR ? 1 + univ.party[current_pc].level / 8 + bonus : 3 + bonus)); if(spell_num == eSpell::BLESS_MAJOR) { poison_weapon(i,2,1); - curse_pc(i, -4); + univ.party[i].curse(-4); add_missile(univ.party[i].combat_pos,14,0,0,0); } else add_missile(univ.party[i].combat_pos,8,0,0,0); @@ -4688,17 +4612,17 @@ void combat_immed_mage_cast(short current_pc, eSpell spell_num, bool freebie) { switch(spell_num) { case eSpell::FEAR_GROUP: r1 = get_ran(univ.party[current_pc].level / 3,1,8); - scare_monst(which_m,r1); + which_m->scare(r1); store_m_type = 10; break; case eSpell::SLOW_GROUP: case eSpell::RAVAGE_ENEMIES: - slow_monst(which_m,5 + bonus); + which_m->slow(5 + bonus); if(spell_num == eSpell::RAVAGE_ENEMIES) - curse_monst(which_m,3 + bonus); + which_m->curse(3 + bonus); store_m_type = 8; break; case eSpell::PARALYSIS_MASS: - charm_monst(which_m,15,eStatus::PARALYZED,1000); + which_m->sleep(eStatus::PARALYZED,1000,15); store_m_type = 15; break; } @@ -4805,7 +4729,7 @@ void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie) store_sound = 4; if(!freebie) univ.party[current_pc].cur_sp -= (*spell_num).cost; - curse_pc(target,-(spell_num==eSpell::BLESS_MINOR ? 2 : max(2,(univ.party[current_pc].level * 3) / 4 + 1 + bonus))); + univ.party[target].curse(-(spell_num==eSpell::BLESS_MINOR ? 2 : max(2,(univ.party[current_pc].level * 3) / 4 + 1 + bonus))); add_missile(univ.party[target].combat_pos,8,0,0,0); } break; @@ -4815,7 +4739,7 @@ void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie) univ.party[current_pc].cur_sp -= (*spell_num).cost; for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) { - curse_pc(i, -(univ.party[current_pc].level / 3)); + univ.party[i].curse(-(univ.party[current_pc].level / 3)); add_missile(univ.party[i].combat_pos,8,0,0,0); } store_sound = 4; @@ -4825,9 +4749,6 @@ void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie) if(!freebie) univ.party[current_pc].cur_sp -= (*spell_num).cost; add_string_to_buf(" " + univ.party[current_pc].name + " is an avatar!"); - heal_pc(current_pc,200); - cure_pc(current_pc,8); - // TODO: Move the heal/cure over to this function as well univ.party[current_pc].avatar(); break; @@ -4844,18 +4765,18 @@ void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie) which_m = &univ.town.monst[i]; switch(spell_num) { case eSpell::CURSE_ALL: - curse_monst(which_m,3 + bonus); + which_m->curse(3 + bonus); store_m_type = 8; break; case eSpell::CHARM_MASS: // TODO: As an item spell, the penalty was 0, though perhaps it was intended to be 8 - // (since 8 was passed as the final argument). Now the penalty has increased to 27. + // (since 8 was passed as the amount argument). Now the penalty has increased to 27. // It should probably be put back somehow. - charm_monst(which_m,28 - bonus,eStatus::CHARM,0); + which_m->sleep(eStatus::CHARM,0,28 - bonus); store_m_type = 14; break; case eSpell::PESTILENCE: - disease_monst(which_m,3 + bonus); + which_m->disease(3 + bonus); store_m_type = 0; break; } @@ -5019,7 +4940,7 @@ static void process_force_cage(location loc, short i) { if(which_m.attitude % 2 == 1 && get_ran(1,1,100) < which_m.mu * 10 + which_m.cl * 4 + 5) { // TODO: This sound is not right play_sound(60); - monst_spell_note(m, 50); + which_m.spell_note(50); univ.town.set_force_cage(loc.x,loc.y,false); which_m.status[eStatus::FORCECAGE] = 0; } else which_m.status[eStatus::FORCECAGE] = 8; @@ -5176,13 +5097,13 @@ void scloud_space(short m,short n) { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) if(univ.party[i].combat_pos == target) { - curse_pc(i,get_ran(1,1,2)); + univ.party[i].curse(get_ran(1,1,2)); } if(overall_mode < MODE_COMBAT) if(target == univ.town.p_loc) { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) - curse_pc(i,get_ran(1,1,2)); + univ.party[i].curse(get_ran(1,1,2)); } } @@ -5199,12 +5120,12 @@ void web_space(short m,short n) { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) if(univ.party[i].combat_pos == target) { - web_pc(i,3); + univ.party[i].web(3); } if(overall_mode < MODE_COMBAT) if(target == univ.town.p_loc) { for(i = 0; i < 6; i++) - web_pc(i,3); + univ.party[i].web(3); } } void sleep_cloud_space(short m,short n) { @@ -5220,12 +5141,11 @@ void sleep_cloud_space(short m,short n) { for(i = 0; i < 6; i++) if(univ.party[i].main_status == eMainStatus::ALIVE) if(univ.party[i].combat_pos == target) { - sleep_pc(i,3,eStatus::ASLEEP,0); + univ.party[i].sleep(eStatus::ASLEEP,3,0); } if(overall_mode < MODE_COMBAT) if(target == univ.town.p_loc) { - for(i = 0; i < 6; i++) - sleep_pc(i,3,eStatus::ASLEEP,0); + univ.party.sleep(eStatus::ASLEEP,3,0); } } diff --git a/src/boe.combat.h b/src/boe.combat.h index 65d1366d..cad7de0a 100644 --- a/src/boe.combat.h +++ b/src/boe.combat.h @@ -14,7 +14,7 @@ void char_parry(); void char_stand_ready(); void pc_attack(short who_att,short target); void pc_attack_weapon(short who_att,short target,short hit_adj,short dam_adj,cItem& weap,short primary,bool do_poison); -short calc_spec_dam(eItemAbil abil,short abil_str,short abil_dat,cCreature* monst,eDamageType& dmg_type); +short calc_spec_dam(eItemAbil abil,short abil_str,short abil_dat,iLiving& monst,eDamageType& dmg_type); void place_target(location target); void do_combat_cast(location target); void handle_marked_damage(); diff --git a/src/boe.graphutil.cpp b/src/boe.graphutil.cpp index 069526b0..ca6910fb 100644 --- a/src/boe.graphutil.cpp +++ b/src/boe.graphutil.cpp @@ -260,14 +260,14 @@ void draw_pcs(location center,short mode) { if(univ.party[i].which_graphic >= 1000) { bool isParty = univ.party[i].which_graphic >= 10000; pic_num_t need_pic = univ.party[i].which_graphic % 1000; - if(univ.party[i].dir >= 4) + if(univ.party[i].direction >= 4) need_pic++; if(combat_posing_monster == i) need_pic += 2; graf_pos_ref(from_gw, source_rect) = spec_scen_g.find_graphic(need_pic, isParty); } else { source_rect = calc_rect(2 * (univ.party[i].which_graphic / 8), univ.party[i].which_graphic % 8); - if(univ.party[i].dir >= 4) + if(univ.party[i].direction >= 4) source_rect.offset(28,0); if(combat_posing_monster == i) source_rect.offset(0,288); @@ -294,7 +294,7 @@ void draw_pcs(location center,short mode) { where_draw.x = univ.party[current_pc].combat_pos.x - center.x + 4; where_draw.y = univ.party[current_pc].combat_pos.y - center.y + 4; source_rect = calc_rect(2 * (univ.party[current_pc].which_graphic / 8), univ.party[current_pc].which_graphic % 8); - if(univ.party[current_pc].dir >= 4) + if(univ.party[current_pc].direction >= 4) source_rect.offset(28,0); if(combat_posing_monster == current_pc) source_rect.offset(0,288); @@ -472,12 +472,12 @@ void draw_party_symbol(location center) { if(univ.party[i].which_graphic >= 1000) { bool isParty = univ.party[i].which_graphic >= 10000; pic_num_t need_pic = univ.party[i].which_graphic % 1000; - if(univ.party[i].dir >= 4) + if(univ.party[i].direction >= 4) need_pic++; graf_pos_ref(from_gw, source_rect) = spec_scen_g.find_graphic(need_pic, isParty); } else { source_rect = calc_rect(2 * (univ.party[current_pc].which_graphic / 8), univ.party[i].which_graphic % 8); - if(univ.party[current_pc].dir >= 4) + if(univ.party[current_pc].direction >= 4) source_rect.offset(28,0); from_gw = &pc_gworld; } diff --git a/src/boe.items.cpp b/src/boe.items.cpp index 32e25834..7287016c 100644 --- a/src/boe.items.cpp +++ b/src/boe.items.cpp @@ -753,15 +753,6 @@ void place_glands(location where,mon_num_t m_type) { } } -short party_total_level() { - short i,j = 0; - - for(i = 0; i < 6; i++) - if(univ.party[i].main_status == eMainStatus::ALIVE) - j += univ.party[i].level; - return j; -} - void reset_item_max() { while(univ.town.items.back().variety == eItemType::NO_ITEM) univ.town.items.pop_back(); @@ -820,9 +811,9 @@ void place_treasure(location where,short level,short loot,short mode) { amt = get_ran(2,1,7) + 1; else amt = loot * (get_ran(1,0,10 + (loot * 6) + (level * 2)) + 5); - if(party_total_level() <= 12) + if(univ.party.get_level() <= 12) amt += 1; - if((party_total_level() <= 60) && (amt > 2)) + if(univ.party.get_level() <= 60 && amt > 2) amt += 2; if(amt > 3) { @@ -830,7 +821,7 @@ void place_treasure(location where,short level,short loot,short mode) { new_item.item_level = amt; r1 = get_ran(1,1,9); if(((loot > 1) && (r1 < 7)) || ((loot == 1) && (r1 < 5)) || (mode == 1) - || ((r1 < 6) && (party_total_level() < 30)) || (loot > 2) ) + || ((r1 < 6) && (univ.party.get_level() < 30)) || (loot > 2) ) place_item(new_item,where,false); } for(j = 0; j < 5; j++) { diff --git a/src/boe.items.h b/src/boe.items.h index 694d060f..e55ffb9e 100644 --- a/src/boe.items.h +++ b/src/boe.items.h @@ -30,7 +30,6 @@ void draw_help_dialog_item_buttons(cDialog& dialog,short item); void draw_help_dialog_forcefields(cDialog& dialog,short item); void make_cursor_watch() ; void place_glands(location where,mon_num_t m_type); -short party_total_level() ; void reset_item_max(); short item_val(cItem item); void place_treasure(location where,short level,short loot,short mode); diff --git a/src/boe.main.cpp b/src/boe.main.cpp index 0dc914c8..257f9057 100644 --- a/src/boe.main.cpp +++ b/src/boe.main.cpp @@ -69,7 +69,7 @@ short fast_bang = false; // Note: This mostly behaves as a boolean variable, but short spec_item_array[60]; short current_spell_range; eGameMode overall_mode = MODE_STARTUP; -bool first_update = true,anim_onscreen = false,frills_on = true,changed_display_mode = false,suppress_stat_screen = false; +bool first_update = true,anim_onscreen = false,frills_on = true,changed_display_mode = false; short stat_window = 0,store_modifier; bool monsters_going = false,boom_anim_active = false; bool give_delays = false; @@ -112,7 +112,7 @@ int main(int /*argc*/, char* argv[]) { init_directories(argv[0]); init_menubar(); // Do this first of all because otherwise a default File and Window menu will be seen sync_prefs(); - cUniverse::print_result = cParty::print_result = cPlayer::print_result = add_string_to_buf; + cUniverse::print_result = iLiving::print_result = add_string_to_buf; init_graph_tool(); Initialize(); init_fileio(); diff --git a/src/boe.monster.cpp b/src/boe.monster.cpp index 0cd8382e..d2153792 100644 --- a/src/boe.monster.cpp +++ b/src/boe.monster.cpp @@ -26,9 +26,6 @@ extern short boom_gr[8],futzing; extern bool processing_fields,monsters_going; extern cUniverse univ; - -short charm_odds[20] = {90,90,85,80,78, 75,73,60,40,30, 20,10,4,1,0, 0,0,0,0,0}; - short out_enc_lev_tot(short which) { short count = 0,i; short num[7] = {22,8,4,4,3,2,1}; @@ -839,7 +836,7 @@ void monst_inflict_fields(short which_monst) { } if(univ.town.is_sleep_cloud(where_check.x,where_check.y)) { if(have_radiate && which_radiate != eFieldType::CLOUD_SLEEP) - charm_monst(which_m,0,eStatus::ASLEEP,3); + which_m->sleep(eStatus::ASLEEP,3,0); break; } if(univ.town.is_ice_wall(where_check.x,where_check.y)) { @@ -851,13 +848,13 @@ void monst_inflict_fields(short which_monst) { if(univ.town.is_scloud(where_check.x,where_check.y)) { r1 = get_ran(1,2,3); if(have_radiate && which_radiate != eFieldType::CLOUD_STINK) - curse_monst(which_m,r1); + which_m->curse(r1); break; } if(univ.town.is_web(where_check.x,where_check.y) && which_m->m_type != eRace::BUG) { - monst_spell_note(which_m->number,19); + which_m->spell_note(19); r1 = get_ran(1,2,3); - web_monst(which_m,r1); + which_m->web(r1); univ.town.set_web(where_check.x,where_check.y,false); break; } @@ -968,7 +965,7 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon if((which_m->attitude % 2 == 1) && (get_ran(1,1,100) < (which_m->mu * 10 + which_m->cl * 4))) { // TODO: Are these barrier sounds right? play_sound(60); - monst_spell_note(which_monst, 49); + which_m->spell_note(49); univ.town.set_fire_barr(where_check.x,where_check.y,false); } else { @@ -982,7 +979,7 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon if((which_m->attitude % 2 == 1) && (get_ran(1,1,100) < (which_m->mu * 10 + which_m->cl * 4)) && (!univ.town->strong_barriers)) { play_sound(60); - monst_spell_note(which_monst, 49); + which_m->spell_note(49); univ.town.set_force_barr(where_check.x,where_check.y,false); } else can_enter = false; @@ -1077,151 +1074,141 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon return can_enter; } -void magic_adjust(cCreature *which_m,short *how_much) { - if(*how_much <= 0) return; - if(which_m->abil[eMonstAbil::ABSORB_SPELLS].active && get_ran(1,1,1000) <= which_m->abil[eMonstAbil::ABSORB_SPELLS].special.extra1) { - int gain = which_m->abil[eMonstAbil::ABSORB_SPELLS].special.extra2; - *how_much = 0; - if(32767 - which_m->health > gain) - which_m->health = 32767; - else which_m->health += gain; - } - *how_much *= which_m->magic_res; - *how_much /= 100; -} - -void poison_monst(cCreature *which_m,short how_much) { +void cCreature::poison(int how_much) { if(how_much > 0) { - how_much *= which_m->poison_res; + how_much *= poison_res; how_much /= 100; } - which_m->status[eStatus::POISON] = min(8, which_m->status[eStatus::POISON] + how_much); + apply_status(eStatus::POISON, how_much); if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 4); + spell_note((how_much == 0) ? 10 : 4); else - monst_spell_note(which_m->number,34); + spell_note(34); } -void acid_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::ACID] = minmax(-8,8, which_m->status[eStatus::ACID] + how_much); - if(how_much >= 0) - monst_spell_note(which_m->number,31); - else - monst_spell_note(which_m->number,48); -} -void slow_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::HASTE_SLOW] = minmax(-8,8, which_m->status[eStatus::HASTE_SLOW] - how_much); +void cCreature::acid(int how_much) { + how_much = magic_adjust(how_much); + apply_status(eStatus::ACID, how_much); if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 2); + spell_note(31); else - monst_spell_note(which_m->number,35); + 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 curse_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::BLESS_CURSE] = minmax(-8,8, which_m->status[eStatus::BLESS_CURSE] - how_much); + +void cCreature::curse(int how_much) { + how_much = magic_adjust(how_much); + apply_status(eStatus::BLESS_CURSE, -how_much); if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 5); + spell_note((how_much == 0) ? 10 : 5); else - monst_spell_note(which_m->number,36); + spell_note(36); } -void web_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::WEBS] = minmax(-8,8, which_m->status[eStatus::WEBS] + how_much); + +void cCreature::web(int how_much) { + how_much = magic_adjust(how_much); + apply_status(eStatus::WEBS, how_much); if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 19); + spell_note((how_much == 0) ? 10 : 19); else - monst_spell_note(which_m->number,37); + spell_note(37); } -void scare_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->morale = which_m->morale - how_much; + +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) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 1); + spell_note((how_much == 0) ? 10 : 1); else - monst_spell_note(which_m->number,47); - -} -void disease_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::DISEASE] = minmax(-8,8, which_m->status[eStatus::DISEASE] + how_much); - if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 25); - else - monst_spell_note(which_m->number,38); + spell_note(47); } -void dumbfound_monst(cCreature *which_m,short how_much) { - magic_adjust(which_m,&how_much); - which_m->status[eStatus::DUMB] = minmax(-8,8, which_m->status[eStatus::DUMB] + how_much); +void cCreature::disease(int how_much) { + how_much = magic_adjust(how_much); + apply_status(eStatus::DISEASE, how_much); if(how_much >= 0) - monst_spell_note(which_m->number,(how_much == 0) ? 10 : 22); + spell_note((how_much == 0) ? 10 : 25); else - monst_spell_note(which_m->number,39); + 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); } -// Also used for sleep and paralyze. // For charm, amount is the resulting attitude of the charmed monster; if 0, attitude is 2. -void charm_monst(cCreature *which_m,short penalty,eStatus which_status,short amount) { - short r1; - +void cCreature::sleep(eStatus which_status,int amount,int penalty) { if(which_status != eStatus::CHARM && which_status != eStatus::FORCECAGE && amount < 0) { - which_m->status[which_status] -= amount; + status[which_status] -= amount; if(which_status == eStatus::PARALYZED) - which_m->status[which_status] = max(0, which_m->status[which_status]); + status[which_status] = max(0, status[which_status]); return; } if((which_status == eStatus::ASLEEP) && - (which_m->m_type == eRace::UNDEAD || which_m->m_type == eRace::SLIME || - which_m->m_type == eRace::STONE || which_m->m_type == eRace::PLANT)) + (m_type == eRace::UNDEAD || m_type == eRace::SLIME || + m_type == eRace::STONE || m_type == eRace::PLANT)) return; - r1 = get_ran(1,1,100); - if(which_m->magic_res > 0) { + short r1 = get_ran(1,1,100); + if(magic_res > 0) { r1 *= 100; - r1 /= which_m->magic_res; + 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 && which_m->abil[eMonstAbil::FIELD].active && which_m->abil[eMonstAbil::FIELD].gen.fld == eFieldType::CLOUD_SLEEP) + if(which_status == eStatus::ASLEEP && abil[eMonstAbil::FIELD].active && abil[eMonstAbil::FIELD].gen.fld == eFieldType::CLOUD_SLEEP) return; - if(r1 > charm_odds[which_m->level / 2]) { + if(r1 > charm_odds[level / 2]) { //one_sound(68); - monst_spell_note(which_m->number,10); + spell_note(10); } else { if(which_status == eStatus::CHARM) { if(amount == 0 || amount > 3) amount = 2; - which_m->attitude = amount; - monst_spell_note(which_m->number,23); + attitude = amount; + spell_note(23); } else if(which_status == eStatus::FORCECAGE) { - which_m->status[eStatus::FORCECAGE] = 8; - univ.town.set_force_cage(which_m->cur_loc.x, which_m->cur_loc.y, true); - monst_spell_note(which_m->number,52); + status[eStatus::FORCECAGE] = 8; + univ.town.set_force_cage(cur_loc.x, cur_loc.y, true); + spell_note(52); } else { - which_m->status[which_status] = amount; + status[which_status] = amount; if(which_status == eStatus::ASLEEP && (amount >= 0)) - monst_spell_note(which_m->number,28); + spell_note(28); if(which_status == eStatus::PARALYZED && (amount >= 0)) - monst_spell_note(which_m->number,30); + spell_note(30); if(amount < 0) - monst_spell_note(which_m->number,40); + spell_note(40); } //one_sound(53); } } + void record_monst(cCreature *which_m) { short r1; @@ -1232,13 +1219,13 @@ void record_monst(cCreature *which_m) { ASB("Capture Soul: Monster is too big."); } // TODO: Are these two sounds right? - else if(r1 > charm_odds[which_m->level / 2] || which_m->abil[eMonstAbil::SPLITS].active + else if(r1 > cCreature::charm_odds[which_m->level / 2] || which_m->abil[eMonstAbil::SPLITS].active || which_m->m_type == eRace::IMPORTANT) { - monst_spell_note(which_m->number,10); + which_m->spell_note(10); play_sound(68); } else { - monst_spell_note(which_m->number,24); + which_m->spell_note(24); r1 = get_ran(1,0,3); if(univ.party.imprisoned_monst[r1] == 0) univ.party.imprisoned_monst[r1] = which_m->number; @@ -1319,7 +1306,7 @@ bool summon_monster(mon_num_t which,location where,short duration,short given_at univ.town.monst[spot].attitude = given_attitude; univ.town.monst[spot].summoned = duration; - monst_spell_note(which,21); + univ.town.monst[spot].spell_note(21); return true; } diff --git a/src/boe.monster.h b/src/boe.monster.h index 4be10d2f..31f5f144 100644 --- a/src/boe.monster.h +++ b/src/boe.monster.h @@ -31,16 +31,6 @@ bool town_move_monster(short num,location dest); bool monster_placid(short m_num); void monst_inflict_fields(short which_monst); bool monst_check_special_terrain(location where_check,short mode,short which_monst); -void magic_adjust(cCreature *which_m,short *how_much); -void poison_monst(cCreature *which_m,short how_much); -void acid_monst(cCreature *which_m,short how_much); -void slow_monst(cCreature *which_m,short how_much); -void curse_monst(cCreature *which_m,short how_much); -void web_monst(cCreature *which_m,short how_much); -void scare_monst(cCreature *which_m,short how_much); -void disease_monst(cCreature *which_m,short how_much); -void dumbfound_monst(cCreature *which_m,short how_much); -void charm_monst(cCreature *which_m,short penalty,eStatus which_status,short amount); void record_monst(cCreature *which_m); short place_monster(mon_num_t which,location where); bool summon_monster(mon_num_t which,location where,short duration,short given_attitude); diff --git a/src/boe.party.cpp b/src/boe.party.cpp index 854465a6..2201bb62 100644 --- a/src/boe.party.cpp +++ b/src/boe.party.cpp @@ -57,7 +57,7 @@ extern eGameMode overall_mode; extern fs::path progDir; extern location center; extern sf::RenderWindow mainPtr; -extern bool spell_forced,save_maps,suppress_stat_screen,boom_anim_active; +extern bool spell_forced,save_maps,boom_anim_active; extern eSpell store_mage, store_priest; extern short store_mage_lev, store_priest_lev; extern short store_spell_target,pc_casting; @@ -338,60 +338,33 @@ bool take_sp(short pc_num,short amt) { return true; } - - - -void heal_pc(short pc_num,short amt) { - if(univ.party[pc_num].cur_health > univ.party[pc_num].max_health) - return; - if(univ.party[pc_num].main_status != eMainStatus::ALIVE) - return; - univ.party[pc_num].cur_health += amt; - if(univ.party[pc_num].cur_health > univ.party[pc_num].max_health) - univ.party[pc_num].cur_health = univ.party[pc_num].max_health; +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; } -void heal_party(short amt) { - short i; - - for(i = 0; i < 6; i++) - if(univ.party[i].main_status == eMainStatus::ALIVE) - heal_pc(i,amt); -} - -void cure_pc(short pc_num,short amt) { - if(univ.party[pc_num].main_status != eMainStatus::ALIVE) - return; - if(univ.party[pc_num].status[eStatus::POISON] <= amt) - univ.party[pc_num].status[eStatus::POISON] = 0; - else univ.party[pc_num].status[eStatus::POISON] -= amt; +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); } -void cure_party(short amt) { - short i; - - for(i = 0; i < 6; i++) - if(univ.party[i].main_status == eMainStatus::ALIVE) - cure_pc(i,amt); - -} - // if how_much < 0, bless -void curse_pc(short which_pc,short how_much) { - int level; - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - if(how_much > 0) - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::BLESS_CURSE)) / 2; - univ.party[which_pc].status[eStatus::BLESS_CURSE] = minmax(-8,8,univ.party[which_pc].status[eStatus::BLESS_CURSE] - how_much); - if(how_much < 0) - add_string_to_buf(" " + univ.party[which_pc].name + " blessed."); - else if(how_much > 0) - add_string_to_buf(" " + univ.party[which_pc].name + " cursed."); - } +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); @@ -399,145 +372,124 @@ void curse_pc(short which_pc,short how_much) { give_help(34,0); } -void dumbfound_pc(short which_pc,short how_much) { - short r1,level; - - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - r1 = get_ran(1,0,90); - if(univ.party[which_pc].has_abil_equip(eItemAbil::WILL) < 24) { +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 -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DUMB)) / 4; - if(r1 < univ.party[which_pc].level) + 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(" " + univ.party[which_pc].name + " saved."); + add_string_to_buf(" " + name + " saved."); return; } - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - univ.party[which_pc].status[eStatus::DUMB] = min(univ.party[which_pc].status[eStatus::DUMB] + how_much,8); - add_string_to_buf(" " + univ.party[which_pc].name + " dumbfounded."); - } + 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 disease_pc(short which_pc,short how_much) { - short r1,level; - - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - r1 = get_ran(1,1,100); - if(r1 < univ.party[which_pc].level * 2) +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(" " + univ.party[which_pc].name + " saved."); + add_string_to_buf(" " + name + " saved."); return; } - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DISEASE)) / 2; - if(univ.party[which_pc].traits[eTrait::FRAIL] && how_much > 1) + how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::DISEASE)) / 2; + if(traits[eTrait::FRAIL] && how_much > 1) how_much++; - if(univ.party[which_pc].traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0) + if(traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0) how_much++; - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - univ.party[which_pc].status[eStatus::DISEASE] = min(univ.party[which_pc].status[eStatus::DISEASE] + how_much,8); - add_string_to_buf(" " + univ.party[which_pc].name + " diseased."); - } + apply_status(eStatus::DISEASE, how_much); + add_string_to_buf(" " + name + " diseased."); one_sound(66); put_pc_screen(); give_help(29,0); } -// higher adjust, less chance of saving -void sleep_pc(short which_pc,short how_much,eStatus what_type,short adjust) { - short r1,level; - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - if(how_much == 0) - return; - // TODO: Uh, what if an invalid status is passed in? - // --> Currently, you'd get that status effect, but with a "paralyzed" message, sound, and quick-help - if(what_type == eStatus::ASLEEP || what_type == eStatus::PARALYZED) { //// - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::WILL) / 2; - level = univ.party[which_pc].get_prot_level(eItemAbil::FREE_ACTION); +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 || 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 -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(what_type)) / 4; + how_much -= get_prot_level(eItemAbil::STATUS_PROTECTION,int(what_type)) / 4; } - r1 = get_ran(1,1,100) + adjust; - if(r1 < 30 + univ.party[which_pc].level * 2) + short r1 = get_ran(1,1,100) + adjust; + if(r1 < 30 + level * 2) how_much = -1; - if(what_type == eStatus::ASLEEP && (univ.party[which_pc].traits[eTrait::HIGHLY_ALERT] || univ.party[which_pc].status[eStatus::ASLEEP] < 0)) + if(what_type == eStatus::ASLEEP && (traits[eTrait::HIGHLY_ALERT] || status[eStatus::ASLEEP] < 0)) how_much = -1; if(how_much <= 0) { - add_string_to_buf(" " + univ.party[which_pc].name + " resisted."); + add_string_to_buf(" " + name + " resisted."); return; } - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - univ.party[which_pc].status[what_type] = how_much; - if(what_type == eStatus::ASLEEP) - add_string_to_buf(" " + univ.party[which_pc].name + " falls asleep."); - else add_string_to_buf(" " + univ.party[which_pc].name + " paralyzed."); - if(what_type == eStatus::ASLEEP) - play_sound(96); - else play_sound(90); - univ.party[which_pc].ap = 0; - } + 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 give_help(32,0); - + else if(what_type == eStatus::PARALYZED) + give_help(32,0); } // if how_much < 0, haste -void slow_pc(short which_pc,short how_much) { - int level; - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - if(how_much > 0) - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::HASTE_SLOW)) / 2; - univ.party[which_pc].status[eStatus::HASTE_SLOW] = minmax(-8,8,univ.party[which_pc].status[eStatus::HASTE_SLOW] - how_much); - if(how_much < 0) - add_string_to_buf(" " + univ.party[which_pc].name + " hasted."); - else if(how_much > 0) - add_string_to_buf(" " + univ.party[which_pc].name + " slowed."); - } +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 web_pc(short which_pc,short how_much) { - int level; - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::WEBS)) / 2; - univ.party[which_pc].status[eStatus::WEBS] = min(univ.party[which_pc].status[eStatus::WEBS] + how_much,8); - add_string_to_buf(" " + univ.party[which_pc].name + " webbed."); - one_sound(17); - } +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 acid_pc(short which_pc,short how_much) { - if(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - if(univ.party[which_pc].has_abil_equip(eItemAbil::STATUS_PROTECTION,int(eStatus::ACID)) < 24) { - add_string_to_buf(" " + univ.party[which_pc].name + " resists acid."); +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; } - if(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - univ.party[which_pc].status[eStatus::ACID] += how_much; - add_string_to_buf(" " + univ.party[which_pc].name + " covered with acid!"); - one_sound(42); - } + status[eStatus::ACID] += how_much; + add_string_to_buf(" " + name + " covered with acid!"); + one_sound(42); put_pc_screen(); } @@ -561,20 +513,11 @@ void increase_light(short amt) { put_pc_screen(); } -void restore_sp_pc(short pc_num,short amt) { - if(univ.party[pc_num].cur_sp > univ.party[pc_num].max_sp) - return; - univ.party[pc_num].cur_sp += amt; - if(univ.party[pc_num].cur_sp > univ.party[pc_num].max_sp) - univ.party[pc_num].cur_sp = univ.party[pc_num].max_sp; -} - -void restore_sp_party(short amt) { - short i; - - for(i = 0; i < 6; i++) - if(univ.party[i].main_status == eMainStatus::ALIVE) - restore_sp_pc(i,amt); +void cPlayer::restore_sp(int amt) { + if(!is_alive()) return; + cur_sp += amt; + if(cur_sp > max_sp) + cur_sp = max_sp; } void award_party_xp(short amt) { @@ -1218,14 +1161,14 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) { r1 = get_ran(2, 1, 4); else r1 = get_ran(2 + (spell_num == eSpell::HEAL ? 6 : 12), 1, 4); sout << " healed " << r1 << '.'; - heal_pc(target,r1); + univ.party[target].heal(r1); one_sound(52); break; case eSpell::POISON_WEAKEN: case eSpell::POISON_CURE: sout << " cured."; r1 = ((spell_num == eSpell::POISON_WEAKEN) ? 1 : 3) + get_ran(1,0,2) + stat_adj(pc_num,eSkill::INTELLIGENCE) / 2; - cure_pc(target,r1); + univ.party[target].cure(r1); break; case eSpell::AWAKEN: @@ -1310,7 +1253,7 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) { sout << " takes " << store_caster_health - univ.party[pc_num].cur_health << '.'; } else if(spell_num == eSpell::REVIVE) { sout << " healed."; - heal_pc(target,250); + univ.party[target].heal(250); univ.party[target].status[eStatus::POISON] = 0; one_sound(-53); one_sound(52); } else if(spell_num == eSpell::DESTONE) { @@ -1386,16 +1329,16 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) { if(spell_num != eSpell::REVIVE_ALL) { r1 = get_ran((spell_num == eSpell::HEAL_ALL ? 6 : 3) + adj, 1, 4); add_string_to_buf(" Party healed " + std::to_string(r1) + "."); - heal_party(r1); + univ.party.heal(r1); play_sound(52); } else { r1 = get_ran(7 + adj, 1, 4); add_string_to_buf(" Party revived."); r1 = r1 * 2; - heal_party(r1); + univ.party.heal(r1); play_sound(-53); play_sound(-52); - cure_party(3 + adj); + univ.party.cure(3 + adj); } break; @@ -1403,7 +1346,7 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) { if(!freebie) univ.party[pc_num].cur_sp -= (*spell_num).cost; add_string_to_buf(" Party cured."); - cure_party(3 + stat_adj(pc_num,eSkill::INTELLIGENCE)); + univ.party.cure(3 + stat_adj(pc_num,eSkill::INTELLIGENCE)); break; case eSpell::SANCTUARY_MASS: case eSpell::CLEANSE_MAJOR: case eSpell::HYPERACTIVITY: @@ -1436,9 +1379,6 @@ void do_priest_spell(short pc_num,eSpell spell_num,bool freebie) { break; case eSpell::AVATAR: - heal_pc(pc_num,200); - cure_pc(pc_num,8); - // TODO: Move the heal/cure over to this function as well univ.party[pc_num].avatar(); break; @@ -1670,7 +1610,7 @@ void do_mindduel(short pc_num,cCreature *monst) { balance--; if(monst->mp == 0) { monst->status[eStatus::DUMB] += 2; - monst_spell_note(monst->number,22); + monst->spell_note(22); if(monst->status[eStatus::DUMB] > 7) { kill_monst(monst,pc_num); } @@ -2521,35 +2461,25 @@ bool flying() { else return true; } -void poison_pc(short which_pc,short how_much) { - short level; +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(univ.party[which_pc].main_status == eMainStatus::ALIVE) { - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::STATUS_PROTECTION,int(eStatus::POISON)) / 2; - how_much -= univ.party[which_pc].get_prot_level(eItemAbil::FULL_PROTECTION) / 3; - - if(univ.party[which_pc].traits[eTrait::FRAIL] && how_much > 1) - how_much++; - if(univ.party[which_pc].traits[eTrait::FRAIL] && how_much == 1 && get_ran(1,0,1) == 0) - how_much++; - - if(how_much > 0) { - univ.party[which_pc].status[eStatus::POISON] = min(univ.party[which_pc].status[eStatus::POISON] + how_much,8); - add_string_to_buf(" " + univ.party[which_pc].name + " poisoned."); - one_sound(17); - give_help(33,0); - } + 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 poison_party(short how_much) { - short i; - - for(i = 0; i < 6; i++) - poison_pc(i,how_much); -} - void void_sanctuary(short pc_num) { if(univ.party[pc_num].status[eStatus::INVISIBLE] > 0) { add_string_to_buf("You become visible!"); @@ -2739,21 +2669,26 @@ bool damage_pc(short which_pc,short how_much,eDamageType damage_type,eRace type_ return true; } -void petrify_pc(short which_pc, short strength) { +void cPlayer::petrify(int strength) { std::ostringstream create_line; short r1 = get_ran(1,0,20); - r1 += univ.party[which_pc].level / 4; - r1 += univ.party[which_pc].status[eStatus::BLESS_CURSE]; + r1 += level / 4; + r1 += status[eStatus::BLESS_CURSE]; r1 -= strength; - if(univ.party[which_pc].has_abil_equip(eItemAbil::PROTECT_FROM_PETRIFY) < 24) + if(has_abil_equip(eItemAbil::PROTECT_FROM_PETRIFY) < 24) r1 = 20; if(r1 > 14) { - create_line << " " << univ.party[which_pc].name << "resists."; + create_line << " " << name << "resists."; } else { - create_line << " " << univ.party[which_pc].name << "is turned to stone."; - kill_pc(which_pc,eMainStatus::STONE); + size_t i = 0; + for(int j = 0; j < 6; j++) { + if(this == &party[j]) + i = j; + } + create_line << " " << name << "is turned to stone."; + kill_pc(i,eMainStatus::STONE); } add_string_to_buf(create_line.str()); } @@ -2805,7 +2740,7 @@ void kill_pc(short which_pc,eMainStatus type) { else { add_string_to_buf(" Life saved! "); univ.party[which_pc].take_item(i); - heal_pc(which_pc,200); + univ.party[which_pc].heal(200); } if(univ.party[current_pc].main_status != eMainStatus::ALIVE) current_pc = first_active_pc(); diff --git a/src/boe.party.h b/src/boe.party.h index 0ed352c4..2b056ee3 100644 --- a/src/boe.party.h +++ b/src/boe.party.h @@ -8,19 +8,7 @@ class cDialog; void make_boats(); bool create_pc(short spot,cDialog* parent_num); bool take_sp(short pc_num,short amt); -void heal_pc(short pc_num,short amt); -void heal_party(short amt); -void cure_pc(short pc_num,short amt); -void cure_party(short amt); -void curse_pc(short which_pc,short how_much); -void dumbfound_pc(short which_pc,short how_much); -void disease_pc(short which_pc,short how_much); -void sleep_pc(short which_pc,short how_much,eStatus what_type,short adjust); -void slow_pc(short which_pc,short how_much); -void web_pc(short which_pc,short how_much); void increase_light(short amt); -void restore_sp_pc(short pc_num,short amt); -void restore_sp_party(short amt); void award_party_xp(short amt); void award_xp(short pc_num,short amt); void drain_pc(short which_pc,short how_much); @@ -48,15 +36,11 @@ bool pick_pc_graphic(short pc_num,short mode,cDialog* parent_num); bool pick_pc_name(short pc_num,cDialog* parent) ; mon_num_t pick_trapped_monst(); bool flying() ; -void acid_pc(short which_pc,short how_much); -void poison_pc(short which_pc,short how_much); -void poison_party(short how_much); void void_sanctuary(short pc_num); void hit_party(short how_much,eDamageType damage_type,short snd_type = 0); void slay_party(eMainStatus mode); bool damage_pc(short which_pc,short how_much,eDamageType damage_type,eRace type_of_attacker, short sound_type,bool do_print = true); void kill_pc(short which_pc,eMainStatus type); -void petrify_pc(short which_pc, short strength); void set_pc_moves(); void take_ap(short num); short trait_present(eTrait which_trait); diff --git a/src/boe.specials.cpp b/src/boe.specials.cpp index ddf2be70..48c4ae36 100644 --- a/src/boe.specials.cpp +++ b/src/boe.specials.cpp @@ -35,7 +35,7 @@ extern sf::RenderWindow mainPtr; extern eGameMode overall_mode; extern short which_combat_type,current_pc,stat_window; extern location center; -extern bool in_scen_debug,belt_present,processing_fields,monsters_going,suppress_stat_screen,boom_anim_active; +extern bool in_scen_debug,belt_present,processing_fields,monsters_going,boom_anim_active; extern effect_pat_type single,t,square,radius2,radius3,small_square,open_square,field[8]; extern effect_pat_type current_pat; extern cOutdoors::cWandering store_wandering_special; @@ -249,15 +249,13 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho if(univ.town.is_web(where_check.x,where_check.y)) { add_string_to_buf(" Webs! "); if(mode != eSpecCtx::COMBAT_MOVE) { - suppress_stat_screen = true; for(i = 0; i < 6; i++) { r1 = get_ran(1,2,3); - web_pc(i,r1); + univ.party[i].web(r1); } - suppress_stat_screen = true; put_pc_screen(); } - else web_pc(current_pc,get_ran(1,2,3)); + else univ.party[current_pc].web(get_ran(1,2,3)); univ.town.set_web(where_check.x,where_check.y,false); } if(univ.town.is_force_barr(where_check.x,where_check.y)) { @@ -384,13 +382,13 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho if(get_ran(1,1,100) > 60) add_string_to_buf("It's eerie here..."); break; case eStatus::BLESS_CURSE: // Should say "You feel awkward." / "You feel blessed."? - curse_pc(i,ter_flag1.s); + univ.party[i].curse(ter_flag1.s); break; case eStatus::POISON: - poison_pc(i,ter_flag1.u); + univ.party[i].poison(ter_flag1.u); break; case eStatus::HASTE_SLOW: // Should say "You feel sluggish." / "You feel speedy."? - slow_pc(i,ter_flag1.s); + univ.party[i].slow(ter_flag1.s); break; case eStatus::INVULNERABLE: // Should say "You feel odd." / "You feel protected."? univ.party[i].apply_status(eStatus::INVULNERABLE,ter_flag1.u); @@ -399,10 +397,10 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho univ.party[i].apply_status(eStatus::MAGIC_RESISTANCE,ter_flag1.u); break; case eStatus::WEBS: // Should say "You feel sticky." / "Your skin tingles."? - web_pc(i,ter_flag1.u); + univ.party[i].web(ter_flag1.u); break; case eStatus::DISEASE: // Should say "You feel healthy." / "You feel sick."? - disease_pc(i,ter_flag1.u); + univ.party[i].disease(ter_flag1.u); break; case eStatus::INVISIBLE: if(ter_flag1.s < 0) add_string_to_buf("You feel obscure."); @@ -410,19 +408,19 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho univ.party[i].apply_status(eStatus::INVISIBLE,ter_flag1.s); break; case eStatus::DUMB: // Should say "You feel clearheaded." / "You feel confused."? - dumbfound_pc(i,ter_flag1.u); + univ.party[i].dumbfound(ter_flag1.u); break; case eStatus::MARTYRS_SHIELD: // Should say "You feel dull." / "You start to glow slightly."? univ.party[i].apply_status(eStatus::MARTYRS_SHIELD,ter_flag1.u); break; case eStatus::ASLEEP: // Should say "You feel alert." / "You feel very tired."? - sleep_pc(i,ter_flag1.u,eStatus::ASLEEP,ter_flag1.u / 2); + univ.party[i].sleep(eStatus::ASLEEP,ter_flag1.u,ter_flag1.u / 2); break; case eStatus::PARALYZED: // Should say "You find it easier to move." / "You feel very stiff."? - sleep_pc(i,ter_flag1.u,eStatus::PARALYZED,ter_flag1.u / 2); + univ.party[i].sleep(eStatus::PARALYZED,ter_flag1.u,ter_flag1.u / 2); break; case eStatus::ACID: // Should say "Your skin tingles pleasantly." / "Your skin burns!"? - acid_pc(i,ter_flag1.u); + univ.party[i].acid(ter_flag1.u); break; case eStatus::MAIN: case eStatus::CHARM: // These magic values are illegal in this context break; @@ -544,27 +542,21 @@ void check_fields(location where_check,eSpecCtx mode,short which_pc) { if(univ.town.is_scloud(where_check.x,where_check.y)) { add_string_to_buf(" Stinking cloud! "); if(mode != eSpecCtx::COMBAT_MOVE) { - suppress_stat_screen = true; for(i = 0; i < 6; i++) { r1 = get_ran(1,2,3); - curse_pc(i,r1); + univ.party[i].curse(r1); } - suppress_stat_screen = false; put_pc_screen(); } - else curse_pc(current_pc,get_ran(1,2,3)); + else univ.party[current_pc].curse(get_ran(1,2,3)); } if(univ.town.is_sleep_cloud(where_check.x,where_check.y)) { add_string_to_buf(" Sleep cloud! "); if(mode != eSpecCtx::COMBAT_MOVE) { - suppress_stat_screen = true; - for(i = 0; i < 6; i++) { - sleep_pc(i,3,eStatus::ASLEEP,0); - } - suppress_stat_screen = false; - put_pc_screen(); + univ.party.sleep(eStatus::ASLEEP,3,0); } - else sleep_pc(current_pc,3,eStatus::ASLEEP,0); + else 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! "); @@ -771,19 +763,19 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel better."); - cure_pc(pc,str); + univ.party[pc].cure(str); break; case 1: ASB(" You feel ill."); - poison_pc(pc,str); + univ.party[pc].poison(str); break; case 2: ASB(" You all feel better."); - cure_party(str); + univ.party.cure(str); break; case 3: ASB(" You all feel ill."); - poison_party(str); + univ.party.poison(str); break; } break; @@ -795,7 +787,7 @@ void use_item(short pc,short item) { break; case 1: ASB(" You feel sick."); - disease_pc(pc,str); + univ.party[pc].disease(str); break; case 2: ASB(" You all feel healthy."); @@ -803,8 +795,7 @@ void use_item(short pc,short item) { break; case 3: ASB(" You all feel sick."); - for(i = 0; i < 6; i++) - disease_pc(i,str); + univ.party.disease(str); break; } break; @@ -816,7 +807,7 @@ void use_item(short pc,short item) { break; case 1: ASB(" You feel confused."); - dumbfound_pc(pc,str); + univ.party[pc].dumbfound(str); break; case 2: ASB(" You all feel clear headed."); @@ -824,8 +815,7 @@ void use_item(short pc,short item) { break; case 3: ASB(" You all feel confused."); - for(i = 0; i < 6; i++) - dumbfound_pc(i,str); + univ.party.dumbfound(str); break; } break; @@ -837,7 +827,7 @@ void use_item(short pc,short item) { break; case 1: ASB(" You feel very tired."); - sleep_pc(pc,str + 1,eStatus::ASLEEP,200); + univ.party[pc].sleep(eStatus::ASLEEP,str + 1,200); break; case 2: ASB(" You all feel alert."); @@ -845,8 +835,7 @@ void use_item(short pc,short item) { break; case 3: ASB(" You all feel very tired."); - for(i = 0; i < 6; i++) - sleep_pc(i,str + 1,eStatus::ASLEEP,200); + univ.party.sleep(eStatus::ASLEEP,str + 1,200); break; } break; @@ -858,7 +847,7 @@ void use_item(short pc,short item) { break; case 1: ASB(" You feel very stiff."); - sleep_pc(pc,str * 20 + 10,eStatus::PARALYZED,200); + univ.party[pc].sleep(eStatus::PARALYZED,str * 20 + 10,200); break; case 2: ASB(" You all find it easier to move."); @@ -866,8 +855,7 @@ void use_item(short pc,short item) { break; case 3: ASB(" You all feel very stiff."); - for(i = 0; i < 6; i++) - sleep_pc(i,str * 20 + 10,eStatus::PARALYZED,200); + univ.party.sleep(eStatus::PARALYZED,str * 20 + 10,200); break; } break; @@ -879,7 +867,7 @@ void use_item(short pc,short item) { break; case 1: ASB(" Your skin burns!"); - acid_pc(pc,str); + univ.party[pc].acid(str); break; case 2: ASB(" You all tingle pleasantly."); @@ -887,8 +875,7 @@ void use_item(short pc,short item) { break; case 3: ASB(" Everyone's skin burns!"); - for(i = 0; i < 6; i++) - acid_pc(i,str); + univ.party.acid(str); break; } break; @@ -897,19 +884,19 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel wonderful!"); - heal_pc(pc,str * 20); + univ.party[pc].heal(str * 20); univ.party[pc].apply_status(eStatus::BLESS_CURSE,str); break; case 1: ASB(" You feel terrible."); drain_pc(pc,str * 5); damage_pc(pc,20 * str,eDamageType::UNBLOCKABLE,eRace::HUMAN,0); - disease_pc(pc,2 * str); - dumbfound_pc(pc,2 * str); + univ.party[pc].disease(2 * str); + univ.party[pc].dumbfound(2 * str); break; case 2: ASB(" Everyone feels wonderful!"); - heal_party(str*20); + univ.party.heal(str*20); univ.party.apply_status(eStatus::BLESS_CURSE,str); break; case 3: @@ -917,8 +904,8 @@ void use_item(short pc,short item) { for(i = 0; i < 6; i++) { drain_pc(i,str * 5); damage_pc(i,20 * str,eDamageType::UNBLOCKABLE,eRace::HUMAN,0); - disease_pc(i,2 * str); - dumbfound_pc(i,2 * str); + univ.party[i].disease(2 * str); + univ.party[i].dumbfound(2 * str); } break; } @@ -972,7 +959,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel better."); - heal_pc(pc,str * 20); + univ.party[pc].heal(str * 20); break; case 1: ASB(" You feel sick."); @@ -980,7 +967,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all feel better."); - heal_party(str * 20); + univ.party.heal(str * 20); break; case 3: ASB(" You all feel sick."); @@ -992,7 +979,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel energized."); - restore_sp_pc(pc,str * 5); + univ.party[pc].restore_sp(str * 5); break; case 1: ASB(" You feel drained."); @@ -1000,7 +987,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all feel energized."); - restore_sp_party(str * 5); + univ.party.restore_sp(str * 5); break; case 3: ASB(" You all feel drained."); @@ -1042,23 +1029,23 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel wonderful."); - heal_pc(pc,str*25); - cure_pc(pc,str); + univ.party[pc].heal(str*25); + univ.party[pc].cure(str); break; case 1: ASB(" You feel terrible."); damage_pc(pc, str*25, eDamageType::UNBLOCKABLE, eRace::UNKNOWN, 0); - poison_pc(pc,str); + univ.party[pc].poison(str); break; case 2: ASB(" You all feel wonderful."); - heal_party(str*25); - cure_party(str); + univ.party.heal(str*25); + univ.party.cure(str); break; case 3: ASB(" You all feel terrible."); hit_party(str*25, eDamageType::UNBLOCKABLE); - poison_party(str); + univ.party.poison(str); break; } break; @@ -1482,7 +1469,7 @@ bool damage_monst(short which_m, short who_hit, short how_much, short how_much_s if(how_much <= 0) { if(is_combat()) - monst_spell_note(victim->number,7); + victim->spell_note(7); if(how_much <= 0 && (dam_type == eDamageType::WEAPON || dam_type == eDamageType::UNDEAD || dam_type == eDamageType::DEMON)) { draw_terrain(2); play_sound(2); @@ -1506,7 +1493,7 @@ bool damage_monst(short which_m, short who_hit, short how_much, short how_much_s if((which_spot = place_monster(victim->number,where_put)) < 90) { static_cast(univ.town.monst[which_spot]) = *victim; univ.town.monst[which_spot].health = victim->health; - monst_spell_note(victim->number,27); + victim->spell_note(27); } } if(who_hit < 7) @@ -1555,19 +1542,19 @@ bool damage_monst(short which_m, short who_hit, short how_much, short how_much_s return true; } -void petrify_monst(cCreature* m_target, short strength) { - monst_spell_note(m_target->number,9); +void cCreature::petrify(int strength) { + spell_note(9); short r1 = get_ran(1,0,20); - r1 += m_target->level / 4; - r1 += m_target->status[eStatus::BLESS_CURSE]; + r1 += level / 4; + r1 += status[eStatus::BLESS_CURSE]; r1 -= strength; // TODO: This should probably do something similar to charm_monst with the magic resistance - if(r1 > 14 || m_target->magic_res == 0) - monst_spell_note(m_target->number,10); + if(r1 > 14 || magic_res == 0) + spell_note(10); else { - monst_spell_note(m_target->number,8); - kill_monst(m_target,7); + spell_note(8); + kill_monst(this,7); } } @@ -2693,8 +2680,8 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, cCreature& who = univ.town.monst[pc - 100]; who.health = minmax(0, who.m_health, who.health + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); if(spec.ex1b == 0) - monst_spell_note(who.number,41); - else monst_spell_note(who.number,42); + who.spell_note(41); + else who.spell_note(42); } break; case eSpecType::AFFECT_SP: @@ -2708,8 +2695,8 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, cCreature& who = univ.town.monst[pc - 100]; who.mp = minmax(0, who.max_mp, who.mp + spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); if(spec.ex1b == 0) - monst_spell_note(who.number,43); - else monst_spell_note(who.number,44); + who.spell_note(43); + else who.spell_note(44); } break; case eSpecType::AFFECT_XP: @@ -2751,7 +2738,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, break; case 2: if(spec.ex1c > 0) - petrify_pc(i,spec.ex1c); + univ.party[i].petrify(spec.ex1c); else kill_pc(i,eMainStatus::SPLIT_STONE); break; case 3: @@ -2776,18 +2763,18 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, if(who.active > 0 && spec.ex1b > 0) { switch(spec.ex1a) { case 0: - monst_spell_note(who.number,46); + who.spell_note(46); kill_monst(&who,7,eMainStatus::DEAD); break; case 1: - monst_spell_note(who.number,51); + who.spell_note(51); kill_monst(&who,7,eMainStatus::DUST); break; case 2: if(spec.ex1c > 0) - petrify_monst(&who, spec.ex1c); + who.petrify(spec.ex1c); else { - monst_spell_note(who.number,8); + who.spell_note(8); kill_monst(&who,7,eMainStatus::STONE); } break; @@ -2799,7 +2786,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, // Bring back to life else if(who.active == 0 && spec.ex1b == 0) { who.active = 1; - monst_spell_note(who.number,45); + who.spell_note(45); } } break; @@ -2810,13 +2797,13 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, switch(eStatus(spec.ex2a)) { case eStatus::POISON: if(spec.ex1b == 0) - cure_pc(i, spec.ex1a); - else poison_pc(i, spec.ex1a); + univ.party[i].cure(spec.ex1a); + else univ.party[i].poison(spec.ex1a); break; case eStatus::HASTE_SLOW: if(spec.ex1b == 0) - slow_pc(i, -spec.ex1a); - else slow_pc(i, spec.ex1a); + univ.party[i].slow(-spec.ex1a); + else univ.party[i].slow(spec.ex1a); break; case eStatus::INVULNERABLE: if(spec.ex1b == 0) @@ -2831,12 +2818,12 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, case eStatus::WEBS: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::WEBS, -spec.ex1a); - else web_pc(i, spec.ex1a); + else univ.party[i].web(spec.ex1a); break; case eStatus::DISEASE: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::DISEASE, -spec.ex1a); - else disease_pc(i, spec.ex1a); + else univ.party[i].disease(spec.ex1a); break; case eStatus::INVISIBLE: if(spec.ex1b == 0) @@ -2845,23 +2832,23 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, break; case eStatus::BLESS_CURSE: if(spec.ex1b == 0) - curse_pc(i, -spec.ex1a); - else curse_pc(i, spec.ex1a); + univ.party[i].curse(-spec.ex1a); + else univ.party[i].curse(spec.ex1a); break; case eStatus::DUMB: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::DUMB, -spec.ex1a); - else dumbfound_pc(i, spec.ex1a); + else univ.party[i].dumbfound(spec.ex1a); break; case eStatus::ASLEEP: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::ASLEEP, -spec.ex1a); - else sleep_pc(i, spec.ex1a, eStatus::ASLEEP, 10); + else univ.party[i].sleep(eStatus::ASLEEP, spec.ex1a, 10); break; case eStatus::PARALYZED: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::PARALYZED, -spec.ex1a); - else sleep_pc(i, spec.ex1a, eStatus::PARALYZED, 10); + else univ.party[i].sleep(eStatus::PARALYZED, spec.ex1a, 10); break; case eStatus::POISONED_WEAPON: if(spec.ex1b == 0) @@ -2876,7 +2863,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, case eStatus::ACID: if(spec.ex1b == 0) univ.party[i].apply_status(eStatus::ACID, -spec.ex1a); - else acid_pc(i, spec.ex1a); + else univ.party[i].acid(spec.ex1a); break; // Invalid values case eStatus::MAIN: @@ -2892,43 +2879,43 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, switch(eStatus(spec.ex2a)) { case eStatus::POISON: if(spec.ex1b == 0) - poison_monst(&who, -spec.ex1a); - else poison_monst(&who, spec.ex1a); + who.poison(-spec.ex1a); + else who.poison(spec.ex1a); break; case eStatus::HASTE_SLOW: if(spec.ex1b == 0) - slow_monst(&who, -spec.ex1a); - else slow_monst(&who, spec.ex1a); + who.slow(-spec.ex1a); + else who.slow(spec.ex1a); break; case eStatus::WEBS: if(spec.ex1b == 0) - web_monst(&who, -spec.ex1a); - else web_monst(&who, spec.ex1a); + who.web(-spec.ex1a); + else who.web(spec.ex1a); break; case eStatus::DISEASE: if(spec.ex1b == 0) - disease_monst(&who, -spec.ex1a); - else disease_monst(&who, spec.ex1a); + who.disease(-spec.ex1a); + else who.disease(spec.ex1a); break; case eStatus::BLESS_CURSE: if(spec.ex1b == 0) - curse_monst(&who, -spec.ex1a); - else curse_monst(&who, spec.ex1a); + who.curse(-spec.ex1a); + else who.curse(spec.ex1a); break; case eStatus::DUMB: if(spec.ex1b == 0) - dumbfound_monst(&who, -spec.ex1a); - else dumbfound_monst(&who, spec.ex1a); + who.dumbfound(-spec.ex1a); + else who.dumbfound(spec.ex1a); break; case eStatus::ASLEEP: if(spec.ex1b == 0) - charm_monst(&who, 0, eStatus::ASLEEP, -spec.ex1a); - else charm_monst(&who, 0, eStatus::ASLEEP, spec.ex1a); + who.sleep(eStatus::ASLEEP, -spec.ex1a, 0); + else who.sleep(eStatus::ASLEEP, spec.ex1a, 0); break; case eStatus::PARALYZED: if(spec.ex1b == 0) - charm_monst(&who, 0, eStatus::PARALYZED, -spec.ex1a); - else charm_monst(&who, 0, eStatus::PARALYZED, spec.ex1a); + who.sleep(eStatus::PARALYZED, -spec.ex1a, 0); + else who.sleep(eStatus::PARALYZED, spec.ex1a, 0); break; case eStatus::MARTYRS_SHIELD: if(spec.ex1b == 0) @@ -2937,8 +2924,8 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, break; case eStatus::ACID: if(spec.ex1b == 0) - acid_monst(&who, -spec.ex1a); - else acid_monst(&who, spec.ex1a); + who.acid(-spec.ex1a); + else who.acid(spec.ex1a); break; // Invalid values case eStatus::MAIN: diff --git a/src/boe.specials.h b/src/boe.specials.h index d54ea478..68f5171a 100644 --- a/src/boe.specials.h +++ b/src/boe.specials.h @@ -10,7 +10,6 @@ bool adj_town_look(location where); void PSOE(short which_special,unsigned char *stuff_done_val,short where_put); bool damage_monst(short which_m, short who_hit, short how_much, short how_much_spec, eDamageType dam_type, short sound_type, bool do_print = true); void kill_monst(cCreature *which_m,short who_killed,eMainStatus type = eMainStatus::DEAD); -void petrify_monst(cCreature* m_target, short strength); void special_increase_age(long length = 1, bool queue = false); void do_rest(long length, int hp_restore, int mp_restore); void out_move_party(short x,short y) ; diff --git a/src/boe.text.cpp b/src/boe.text.cpp index 6382d784..72525cf1 100644 --- a/src/boe.text.cpp +++ b/src/boe.text.cpp @@ -60,7 +60,7 @@ extern short terrain_there[9][9]; // game globals extern location ul; -extern bool play_sounds,suppress_stat_screen; +extern bool play_sounds; extern rectangle item_buttons[8][6]; // name, use, give, drip, info, sell/id extern rectangle pc_buttons[6][5]; @@ -874,8 +874,8 @@ std::string print_monster_going(mon_num_t m_num,short ap) { return sout.str(); } -void monst_spell_note(mon_num_t number,short which_mess) { - std::string msg = get_m_name(number); +void cCreature::spell_note(int which_mess) { + std::string msg = m_name; switch(which_mess) { case 1: msg = " " + msg + " scared. "; diff --git a/src/boe.text.h b/src/boe.text.h index 46270b14..b5b6d24a 100644 --- a/src/boe.text.h +++ b/src/boe.text.h @@ -23,7 +23,6 @@ void print_monst_name(mon_num_t m_type); void print_monst_attacks(mon_num_t m_type,short target); void damaged_message(short damage,eMonstMelee type); std::string print_monster_going(mon_num_t m_num,short ap); -void monst_spell_note(mon_num_t number,short which_mess); void monst_cast_spell_note(mon_num_t number,eSpell spell); void monst_breathe_note(mon_num_t number); void monst_damaged_mes(mon_num_t which_m,short how_much,short how_much_spec); diff --git a/src/boe.town.cpp b/src/boe.town.cpp index c088d13c..13b1fe15 100644 --- a/src/boe.town.cpp +++ b/src/boe.town.cpp @@ -690,7 +690,7 @@ void start_town_combat(eDirection direction) { for(i = 0; i < 6; i++) { univ.party[i].last_attacked = univ.town.monst.size() + 10; univ.party[i].parry = 0; - univ.party[i].dir = direction; + univ.party[i].direction = direction; univ.party[current_pc].direction = direction; if(univ.party[i].main_status == eMainStatus::ALIVE) update_explored(univ.party[i].combat_pos); @@ -722,7 +722,7 @@ eDirection end_town_combat() { for(i = 0; i < 6; i++) { univ.party[i].parry = 0; } - return univ.party[r1].dir; + return univ.party[r1].direction; } void place_party(short direction) { diff --git a/src/boe.townspec.cpp b/src/boe.townspec.cpp index 526b698a..bcc865ab 100644 --- a/src/boe.townspec.cpp +++ b/src/boe.townspec.cpp @@ -81,14 +81,14 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) { add_string_to_buf(" A dart flies out. "); r1 = 3 + univ.town.difficulty / 14; r1 = r1 + trap_level * 2; - poison_pc(pc_num,r1); + univ.party[pc_num].poison(r1); break; case TRAP_GAS: add_string_to_buf(" Poison gas pours out. "); r1 = 2 + univ.town.difficulty / 14; r1 = r1 + trap_level * 2; - poison_party(r1); + univ.party.poison(r1); break; case TRAP_EXPLOSION: @@ -103,7 +103,8 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) { add_string_to_buf(" A purple ray flies out. "); r1 = 200 + univ.town.difficulty * 100; r1 = r1 + trap_level * 400; - sleep_pc(pc_num,r1,eStatus::PARALYZED,50); + // TODO: It says sleep ray but is actually paralysis ray? + univ.party[pc_num].sleep(eStatus::PARALYZED, r1, 50); break; case TRAP_DRAIN_XP: add_string_to_buf(" You feel weak. "); @@ -124,23 +125,21 @@ bool run_trap(short pc_num,eTrapType trap_type,short trap_level,short diff) { break; case TRAP_DUMBFOUND: add_string_to_buf(" You feel disoriented. "); - for(i = 0; i < 6; i++) - dumbfound_pc(i,2 + trap_level * 2); + univ.party.dumbfound(2 + trap_level * 2); break; case TRAP_DISEASE: add_string_to_buf(" You prick your finger. "); r1 = 3 + univ.town.difficulty / 14; r1 = r1 + trap_level * 2; - disease_pc(pc_num,r1); + univ.party[pc_num].disease(r1); break; case TRAP_DISEASE_ALL: add_string_to_buf(" A foul substance sprays out."); r1 = 2 + univ.town.difficulty / 14; r1 = r1 + trap_level * 2; - for(i = 0; i < 6; i++) - disease_pc(i,r1); + univ.party.disease(r1); break; case TRAP_CUSTOM: diff --git a/src/classes/living.cpp b/src/classes/living.cpp new file mode 100644 index 00000000..bd8fe001 --- /dev/null +++ b/src/classes/living.cpp @@ -0,0 +1,51 @@ +// +// living.cpp +// BoE +// +// Created by Celtic Minstrel on 15-01-24. +// +// + +#include "living.hpp" + +#include +#include "mathutil.hpp" + +void iLiving::apply_status(eStatus which, int how_much) { + static const std::set allow_negative = { + // The obvious ones: + eStatus::BLESS_CURSE, eStatus::HASTE_SLOW, + // The ones that BoE previously allowed: + eStatus::POISONED_WEAPON, eStatus::POISON, eStatus::ASLEEP, + // (Note: Negative levels of sleep can be obtained from the Hyperactivity spell. The other two never go negative.) + // The additional ones that make sense in the negative: + eStatus::MAGIC_RESISTANCE, eStatus::DUMB, + }; + + // TODO: Martyr's Shield range seems to be 0..10; Paralyzed seems to range something like 0..1000 + + if(!is_alive()) return; + status[which] = minmax(-8,8,status[which] + how_much); + if(!allow_negative.count(which)) + status[which] = max(status[which],0); +} + +void iLiving::clear_bad_status() { + status[eStatus::POISON] = 0; + if(status[eStatus::BLESS_CURSE] < 0) + status[eStatus::BLESS_CURSE] = 0; + if(status[eStatus::HASTE_SLOW] < 0) + status[eStatus::HASTE_SLOW] = 0; + status[eStatus::WEBS] = 0; + status[eStatus::DISEASE] = 0; + if(status[eStatus::DUMB] > 0) + status[eStatus::DUMB] = 0; + if(status[eStatus::ASLEEP] > 0) + status[eStatus::ASLEEP] = 0; + status[eStatus::PARALYZED] = 0; + status[eStatus::ACID] = 0; + if(status[eStatus::MAGIC_RESISTANCE] < 0) + status[eStatus::MAGIC_RESISTANCE] = 0; +} + +void(* iLiving::print_result)(std::string) = nullptr; diff --git a/src/classes/living.hpp b/src/classes/living.hpp new file mode 100644 index 00000000..ccf602ad --- /dev/null +++ b/src/classes/living.hpp @@ -0,0 +1,59 @@ +// +// living.hpp +// BoE +// +// Created by Celtic Minstrel on 15-01-24. +// +// + +#ifndef BoE_living_hpp +#define BoE_living_hpp + +#include +#include + +#include "location.h" +#include "simpletypes.h" + +class iLiving { +public: + // HACK: This is only really marked mutable so that I can use operator[] from const methods + mutable std::map status; + short ap; + eDirection direction; + short marked_damage = 0; // for use during animations + + virtual bool is_alive() const = 0; + virtual bool is_shielded() const = 0; // Checks for martyr's shield in any form - status, monster abil, item abil + virtual int get_shared_dmg(int base_dmg) const = 0; // And this goes with the above. + + virtual void apply_status(eStatus which, int how_much); + virtual void clear_bad_status(); + + virtual void heal(int how_much) = 0; + virtual void poison(int how_much) = 0; + virtual void cure(int how_much) = 0; + virtual void acid(int how_much) = 0; + virtual void curse(int how_much) = 0; + virtual void slow(int how_much) = 0; + virtual void web(int how_much) = 0; + virtual void disease(int how_much) = 0; + virtual void dumbfound(int how_much) = 0; + virtual void scare(int how_much) = 0; + virtual void sleep(eStatus type, int how_much, int adj) = 0; // Also handles paralysis, charm, and forcecage + virtual void avatar() = 0; + virtual void drain_sp(int how_much) = 0; + virtual void restore_sp(int how_much) = 0; + virtual void petrify(int adj) = 0; + + virtual int get_health() const = 0; + virtual int get_magic() const = 0; + virtual int get_level() const = 0; + virtual location get_loc() const = 0; + + virtual ~iLiving() = default; + + static void(* print_result)(std::string); +}; + +#endif diff --git a/src/classes/monster.cpp b/src/classes/monster.cpp index b2a36b6d..b2c0eb08 100644 --- a/src/classes/monster.cpp +++ b/src/classes/monster.cpp @@ -17,9 +17,11 @@ #include "oldstructs.h" #include "fileio.hpp" #include "spell.hpp" +#include "mathutil.hpp" static uAbility test; static_assert(&test.active == &test.missile.active, "uAbility union has incorrect layout"); +const short cCreature::charm_odds[20] = {90,90,85,80,78, 75,73,60,40,30, 20,10,4,1,0, 0,0,0,0,0}; void cMonster::append(legacy::monster_record_type& old){ level = old.level; @@ -492,6 +494,103 @@ void cCreature::append(legacy::creature_data_type old){ direction = eDirection(old.m_d.direction); } +void cCreature::avatar() { + health = m_health; + status[eStatus::POISON] = 0; + status[eStatus::BLESS_CURSE] = 8; + status[eStatus::HASTE_SLOW] = 8; + status[eStatus::WEBS] = 0; + status[eStatus::DISEASE] = 0; + if(status[eStatus::DUMB] > 0) + status[eStatus::DUMB] = 0; + status[eStatus::MARTYRS_SHIELD] = 8; +} + +void cCreature::heal(int amt) { + if(!is_alive()) return; + if(health >= m_health) return; + health += amt; + if(health > m_health) + health = m_health; +} + +void cCreature::cure(int amt) { + if(!is_alive()) return; + if(status[eStatus::POISON] <= amt) + status[eStatus::POISON] = 0; + else status[eStatus::POISON] -= amt; +} + +void cCreature::restore_sp(int amt) { + if(!is_alive()) return; + mp += amt; + if(mp > max_mp) + mp = max_mp; +} + +void cCreature::drain_sp(int drain) { + drain = magic_adjust(drain); + if(drain > 0) { + if(mu > 0 && mp > 4) + drain = min(mp, drain / 3); + else if(cl > 0 && mp > 10) + drain = min(mp, drain / 2); + mp -= drain; + if(mp < 0) mp = 0; + } +} + +bool cCreature::is_alive() const { + return active > 0; +} + +location cCreature::get_loc() const { + return cur_loc; +} + +bool cCreature::is_shielded() const { + if(status[eStatus::MARTYRS_SHIELD] > 0) + return true; + if(abil[eMonstAbil::MARTYRS_SHIELD].active && get_ran(1,1,1000) <= abil[eMonstAbil::MARTYRS_SHIELD].special.extra1) + return true; + return false; +} + +int cCreature::get_shared_dmg(int base_dmg) const { + if(abil[eMonstAbil::MARTYRS_SHIELD].active) { + base_dmg *= abil[eMonstAbil::MARTYRS_SHIELD].special.extra2; + base_dmg /= 100; + } + return base_dmg; +} + +int cCreature::magic_adjust(int how_much) { + if(how_much <= 0) return how_much; + if(abil[eMonstAbil::ABSORB_SPELLS].active && get_ran(1,1,1000) <= abil[eMonstAbil::ABSORB_SPELLS].special.extra1) { + int gain = abil[eMonstAbil::ABSORB_SPELLS].special.extra2; + if(32767 - health > gain) + health = 32767; + else health += gain; + return 0; + } + // TODO: Magic resistance status effect? + how_much *= magic_res; + how_much /= 100; + return how_much; +} + +int cCreature::get_health() const { + return health; +} + +int cCreature::get_magic() const { + return mp; +} + +int cCreature::get_level() const { + return level; +} + std::ostream& operator<<(std::ostream& out, const cMonster::cAttack& att) { out << int(att.dice) << 'd' << int(att.sides); return out; @@ -1119,7 +1218,7 @@ void cCreature::writeTo(std::ostream& file) const { file << "CURHP " << health << '\n'; file << "CURSP " << mp << '\n'; file << "MORALE " << morale << '\n'; - file << "DIRECTION " << unsigned(direction) << '\n'; + file << "DIRECTION " << direction << '\n'; // TODO: Should we be saving "max_mp" and/or "m_morale"? } diff --git a/src/classes/monster.h b/src/classes/monster.h index d49e68ba..67555c12 100644 --- a/src/classes/monster.h +++ b/src/classes/monster.h @@ -16,6 +16,7 @@ #include "soundtool.hpp" #include "simpletypes.h" #include "graphtool.hpp" +#include "living.hpp" namespace legacy { struct monster_record_type; @@ -114,7 +115,8 @@ public: unsigned int mu; unsigned int cl; unsigned int treasure; - std::map abil; + // HACK: This is only really marked mutable so that I can use operator[] from const methods + mutable std::map abil; item_num_t corpse_item; short corpse_item_chance; unsigned int magic_res; @@ -133,9 +135,9 @@ public: pic_num_t picture_num; snd_num_t ambient_sound; // has a chance of being played every move spec_num_t see_spec; -public: std::map::iterator addAbil(eMonstAbilTemplate what, int param = 0); + void append(legacy::monster_record_type& old); cMonster(); void writeTo(std::ostream& file) const; @@ -168,8 +170,9 @@ public: cTownperson(location loc, mon_num_t num, const cMonster& monst); }; -class cCreature : public cMonster, public cTownperson { +class cCreature : public cMonster, public cTownperson, public iLiving { public: + static const short charm_odds[20]; short active, attitude; location cur_loc; short summoned; @@ -178,15 +181,41 @@ public: short health; short mp; short max_mp; - short ap; short morale,m_morale; // these are calculated in-game based on the level - std::map status; - eDirection direction; - short marked_damage = 0; // for use during animations cCreature(); cCreature(int num); + void heal(int how_much); + void poison(int how_much); + void cure(int how_much); + void acid(int how_much); + void curse(int how_much); + void slow(int how_much); + void web(int how_much); + void disease(int how_much); + void dumbfound(int how_much); + void scare(int how_much); + void sleep(eStatus type, int how_much, int adj); + void avatar(); + void drain_sp(int how_much); + void restore_sp(int how_much); + void petrify(int adj); + void kill(eMainStatus type = eMainStatus::DEAD); + + int get_health() const; + int get_magic() const; + int get_level() const; + + bool is_alive() const; + bool is_shielded() const; + int get_shared_dmg(int base_dmg) const; + location get_loc() const; + + int magic_adjust(int base); + + void spell_note(int which); + void append(legacy::creature_data_type old); void writeTo(std::ostream& file) const; void readFrom(std::istream& file); diff --git a/src/classes/party.cpp b/src/classes/party.cpp index ef60c778..aaab99fe 100644 --- a/src/classes/party.cpp +++ b/src/classes/party.cpp @@ -260,6 +260,131 @@ void cParty::apply_status(eStatus which, int how_much) { adven[i]->apply_status(which, how_much); } +void cParty::clear_bad_status() { + for(int i = 0; i < 6; i++) + adven[i]->clear_bad_status(); +} + +bool cParty::is_alive() const { + for(int i = 0; i < 6; i++) + if(adven[i]->is_alive()) + return true; + return false; +} + +bool cParty::is_shielded() const { + return false; +} + +int cParty::get_shared_dmg(int) const { + return 0; +} + +int cParty::get_health() const { + int health = 0; + for(int i = 0; i < 6; i++) + if(adven[i]->is_alive()) + health += adven[i]->cur_health; + return health; +} + +int cParty::get_magic() const { + int magic = 0; + for(int i = 0; i < 6; i++) + if(adven[i]->is_alive()) + magic += adven[i]->cur_sp; + return magic; +} + +int cParty::get_level() const { + short j = 0; + for(int i = 0; i < 6; i++) + if(univ.party[i].main_status == eMainStatus::ALIVE) + j += univ.party[i].level; + return j; +} + +void cParty::heal(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->heal(how_much); +} + +void cParty::poison(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->poison(how_much); +} + +void cParty::cure(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->cure(how_much); +} + +void cParty::acid(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->acid(how_much); +} + +void cParty::curse(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->curse(how_much); +} + +void cParty::slow(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->slow(how_much); +} + +void cParty::web(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->web(how_much); +} + +void cParty::disease(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->disease(how_much); +} + +void cParty::dumbfound(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->dumbfound(how_much); +} + +void cParty::sleep(eStatus type, int how_much, int adj) { + for(int i = 0; i < 6; i++) + adven[i]->sleep(type, how_much, adj); +} + +void cParty::scare(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->scare(how_much); +} + +void cParty::avatar() { + for(int i = 0; i < 6; i++) + adven[i]->avatar(); +} + +void cParty::drain_sp(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->drain_sp(how_much); +} + +void cParty::restore_sp(int how_much) { + for(int i = 0; i < 6; i++) + adven[i]->restore_sp(how_much); +} + +void cParty::petrify(int adj) { + for(int i = 0; i < 6; i++) + adven[i]->petrify(adj); +} + +location cParty::get_loc() const { + if(univ.town.num == 200) + return p_loc; + return univ.town.p_loc; +} + bool cParty::give_item(cItem item,bool do_print) { for(int i = 0; i < 6; i++) { if(adven[i]->give_item(item,do_print)) @@ -927,5 +1052,3 @@ std::ostream& operator<<(std::ostream& out, ePartyStatus type) { return out; } -void(* cParty::print_result)(std::string) = nullptr; - diff --git a/src/classes/party.h b/src/classes/party.h index 40e978b5..ca8c0759 100644 --- a/src/classes/party.h +++ b/src/classes/party.h @@ -20,6 +20,7 @@ #include "pc.h" #include "outdoors.h" #include "monster.h" +#include "living.hpp" namespace legacy { struct party_record_type; @@ -37,7 +38,7 @@ struct campaign_flag_type{ class cUniverse; -class cParty { +class cParty : public iLiving { public: class cConvers { // conversation; formerly talk_save_type public: @@ -131,7 +132,33 @@ public: void append(legacy::setup_save_type& old); void append(legacy::pc_record_type(& old)[6]); + bool is_alive() const; + bool is_shielded() const; + int get_shared_dmg(int base_dmg) const; + location get_loc() const; + void apply_status(eStatus which, int how_much); + void heal(int how_much); + void poison(int how_much); + void cure(int how_much); + void acid(int how_much); + void curse(int how_much); + void slow(int how_much); + void web(int how_much); + void disease(int how_much); + void dumbfound(int how_much); + void scare(int how_much); + void sleep(eStatus type, int how_much, int adj); + void clear_bad_status(); + void avatar(); + void drain_sp(int how_much); + void restore_sp(int how_much); + void petrify(int adj); + void kill(eMainStatus type = eMainStatus::DEAD); + + int get_health() const; + int get_magic() const; + int get_level() const; void new_pc(size_t spot); size_t free_space(); @@ -164,7 +191,6 @@ public: typedef std::vector::iterator timerIter; cParty(cUniverse& univ, long party_preset = 'dflt'); ~cParty(); - static void(* print_result)(std::string); }; bool operator==(const cParty::cConvers& one, const cParty::cConvers& two); diff --git a/src/classes/pc.cpp b/src/classes/pc.cpp index c8ba5611..630f2abb 100644 --- a/src/classes/pc.cpp +++ b/src/classes/pc.cpp @@ -49,7 +49,7 @@ void cPlayer::append(legacy::pc_record_type old){ which_graphic = old.which_graphic; weap_poisoned = old.weap_poisoned; race = (eRace) old.race; - direction = old.direction; + direction = eDirection(old.direction); } short cPlayer::get_tnl(){ @@ -76,38 +76,75 @@ short cPlayer::get_tnl(){ return tnl; } -void cPlayer::apply_status(eStatus which, int how_much) { - static const std::set allow_negative = { - // The obvious ones: - eStatus::BLESS_CURSE, eStatus::HASTE_SLOW, - // The ones that BoE previously allowed: - eStatus::POISONED_WEAPON, eStatus::POISON, eStatus::ASLEEP, - // (Note: Negative levels of sleep can be obtained from the Hyperactivity spell. The other two never go negative.) - // The additional ones that make sense in the negative: - eStatus::MAGIC_RESISTANCE, eStatus::DUMB, - }; - - // TODO: Apply STATUS_PROTECTION item abilities; the challenge is to determine whether to apply to positive or negative how_much - // TODO: I'd like to merge poison_pc, web_pc, acid_pc etc into this function. - - if(main_status != eMainStatus::ALIVE) - return; - status[which] = minmax(-8,8,status[which] + how_much); - if(!allow_negative.count(which)) - status[which] = max(status[which],0); -} - void cPlayer::avatar() { + heal(300); + cure(8); status[eStatus::BLESS_CURSE] = 8; status[eStatus::HASTE_SLOW] = 8; status[eStatus::INVULNERABLE] = 3; status[eStatus::MAGIC_RESISTANCE] = 8; status[eStatus::WEBS] = 0; status[eStatus::DISEASE] = 0; - status[eStatus::DUMB] = 0; + if(status[eStatus::DUMB] > 0) + status[eStatus::DUMB] = 0; status[eStatus::MARTYRS_SHIELD] = 8; } +void cPlayer::drain_sp(int drain) { + int mu = skills[eSkill::MAGE_SPELLS]; + int cl = skills[eSkill::PRIEST_SPELLS]; + if(drain > 0) { + if(mu > 0 && cur_sp > 4) + drain = min(cur_sp, drain / 3); + else if(cl > 0 && cur_sp > 10) + drain = min(cur_sp, drain / 2); + cur_sp -= drain; + if(cur_sp < 0) cur_sp = 0; + } +} + +void cPlayer::scare(int) { + // TODO: Not implemented +} + +bool cPlayer::is_alive() const { + return main_status == eMainStatus::ALIVE; +} + +bool cPlayer::is_shielded() const { + if(status[eStatus::MARTYRS_SHIELD] > 0) + return true; + if(get_prot_level(eItemAbil::MARTYRS_SHIELD) > 0) + return true; + return false; +} + +int cPlayer::get_shared_dmg(int base) const { + int martyr1 = status[eStatus::MARTYRS_SHIELD]; + int martyr2 = get_prot_level(eItemAbil::MARTYRS_SHIELD); + if(martyr1 + martyr2 <= 0) return 0; + if(get_ran(1,1,20) < martyr2) return base + max(1, martyr2 / 5); + return base; +} + +location cPlayer::get_loc() const { + if(combat_pos.x < 0 || combat_pos.y < 0) + return party.get_loc(); + return combat_pos; +} + +int cPlayer::get_health() const { + return cur_health; +} + +int cPlayer::get_magic() const { + return cur_sp; +} + +int cPlayer::get_level() const { + return level; +} + void cPlayer::sort_items() { using it = eItemType; static std::map item_priority = { @@ -191,12 +228,12 @@ bool cPlayer::give_item(cItem item, bool do_print, bool allow_overload) { return false; } -short cPlayer::max_weight() { +short cPlayer::max_weight() const { return 100 + (15 * min(skill(eSkill::STRENGTH),20)) + (traits[eTrait::STRENGTH] * 30) + (traits[eTrait::BAD_BACK] * -50); } -short cPlayer::cur_weight() { +short cPlayer::cur_weight() const { short weight = 0; bool airy = false,heavy = false; @@ -217,11 +254,11 @@ short cPlayer::cur_weight() { return weight; } -short cPlayer::free_weight() { +short cPlayer::free_weight() const { return max_weight() - cur_weight(); } -short cPlayer::has_space() { +short cPlayer::has_space() const { for(int i = 0; i < 24; i++) { if(items[i].variety == eItemType::NO_ITEM) return i; @@ -253,7 +290,7 @@ void cPlayer::combine_things() { } } -short cPlayer::get_prot_level(eItemAbil abil, short dat) { +short cPlayer::get_prot_level(eItemAbil abil, short dat) const { int sum = 0; for(int i = 0; i < 24; i++) { if(items[i].variety == eItemType::NO_ITEM) continue; @@ -266,7 +303,7 @@ short cPlayer::get_prot_level(eItemAbil abil, short dat) { } -short cPlayer::has_abil_equip(eItemAbil abil,short dat) { +short cPlayer::has_abil_equip(eItemAbil abil,short dat) const { for(short i = 0; i < 24; i++) { if(items[i].variety == eItemType::NO_ITEM) continue; if(items[i].ability != abil) continue; @@ -277,7 +314,7 @@ short cPlayer::has_abil_equip(eItemAbil abil,short dat) { return 24; } -short cPlayer::has_abil(eItemAbil abil,short dat) { +short cPlayer::has_abil(eItemAbil abil,short dat) const { for(short i = 0; i < 24; i++) { if(items[i].variety == eItemType::NO_ITEM) continue; if(items[i].ability != abil) continue; @@ -287,7 +324,7 @@ short cPlayer::has_abil(eItemAbil abil,short dat) { return 24; } -short cPlayer::skill(eSkill skill) { +short cPlayer::skill(eSkill skill) const { int bulk_bonus = 0; if(skill >= eSkill::EDGED_WEAPONS && skill <= eSkill::DEFENSE) bulk_bonus = get_prot_level(eItemAbil::BOOST_WAR); @@ -296,7 +333,7 @@ short cPlayer::skill(eSkill skill) { return min(20, skills[skill] + get_prot_level(eItemAbil::BOOST_STAT, int(skill))) + bulk_bonus; } -eBuyStatus cPlayer::ok_to_buy(short cost,cItem item) { +eBuyStatus cPlayer::ok_to_buy(short cost,cItem item) const { if(item.variety == eItemType::SPECIAL) { if(party.spec_items[item.item_level]) return eBuyStatus::HAVE_LOTS; @@ -404,7 +441,7 @@ cPlayer::cPlayer(cParty& party) : party(party) { weap_poisoned = 24; race = eRace::HUMAN; - direction = 0; + direction = DIR_N; } cPlayer::cPlayer(cParty& party,long key,short slot) : party(party) { @@ -464,7 +501,7 @@ cPlayer::cPlayer(cParty& party,long key,short slot) : party(party) { } race = eRace::HUMAN; - direction = 0; + direction = DIR_N; }else if(key == 'dflt'){ // TODO: The duplication of std::map shouldn't be needed here static std::map pc_stats[6] = { @@ -557,7 +594,7 @@ cPlayer::cPlayer(cParty& party,long key,short slot) : party(party) { } race = (eRace) pc_race[slot]; - direction = 0; + direction = DIR_N; which_graphic = pc_graphics[slot]; } @@ -730,5 +767,3 @@ std::istream& operator >> (std::istream& in, eMainStatus& e){ else e = eMainStatus::ABSENT; return in; } - -void(* cPlayer::print_result)(std::string) = nullptr; diff --git a/src/classes/pc.h b/src/classes/pc.h index 78c05551..4d9728c7 100644 --- a/src/classes/pc.h +++ b/src/classes/pc.h @@ -17,6 +17,7 @@ #include "simpletypes.h" #include "item.h" #include "pictypes.hpp" +#include "living.hpp" namespace legacy { struct pc_record_type; }; @@ -24,12 +25,13 @@ enum class eBuyStatus {OK, NO_SPACE, NEED_GOLD, TOO_HEAVY, HAVE_LOTS}; class cParty; -class cPlayer { +class cPlayer : public iLiving { cParty& party; public: eMainStatus main_status; std::string name; - std::map skills; + // HACK: This is only really marked mutable so that I can use operator[] from const methods + mutable std::map skills; unsigned short max_health; short cur_health; unsigned short max_sp; @@ -37,49 +39,69 @@ public: unsigned short experience; short skill_pts; short level; - std::map status; std::array items; std::array equip; bool priest_spells[62]; bool mage_spells[62]; pic_num_t which_graphic; short weap_poisoned; - std::map traits; + // HACK: This is only really marked mutable so that I can use operator[] from const methods + mutable std::map traits; eRace race; - short direction; - short ap; // transient stuff std::map last_cast; location combat_pos; - short marked_damage = 0, parry, last_attacked; - eDirection dir; + short parry, last_attacked; + + bool is_alive() const; + bool is_shielded() const; + int get_shared_dmg(int base_dmg) const; + + int get_health() const; + int get_magic() const; + int get_level() const; + location get_loc() const; void finish_create(); - void apply_status(eStatus which, int how_much); + void heal(int how_much); + void poison(int how_much); + void cure(int how_much); + void acid(int how_much); + void curse(int how_much); + void slow(int how_much); + void web(int how_much); + void disease(int how_much); + void dumbfound(int how_much); + void scare(int how_much); + void sleep(eStatus type, int how_much, int adj); void avatar(); + void drain_sp(int how_much); + void restore_sp(int how_much); + void petrify(int adj); + void kill(eMainStatus type = eMainStatus::DEAD); void combine_things(); void sort_items(); bool give_item(cItem item, bool do_print, bool allow_overload = false); void take_item(int which_item); void remove_charge(int which_item); - short has_space(); - short max_weight(); - short cur_weight(); - short free_weight(); - 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); + short has_space() const; + short max_weight() const; + short cur_weight() const; + short free_weight() const; + short get_prot_level(eItemAbil abil, short dat = -1) const; + short has_abil_equip(eItemAbil abil, short dat = -1) const; + short has_abil(eItemAbil abil, short dat = -1) const; + short skill(eSkill skill) const; + eBuyStatus ok_to_buy(short cost,cItem item) const; void append(legacy::pc_record_type old); cPlayer(cParty& party); cPlayer(cParty& party,long key,short slot); - static void(* print_result)(std::string); short get_tnl(); void writeTo(std::ostream& file) const; void readFrom(std::istream& file); + virtual ~cPlayer() = default; }; void operator += (eMainStatus& stat, eMainStatus othr); diff --git a/src/classes/universe.cpp b/src/classes/universe.cpp index 81ab6867..d70f2a23 100644 --- a/src/classes/universe.cpp +++ b/src/classes/universe.cpp @@ -925,6 +925,17 @@ void cUniverse::check_item(cItem& item) { } } +iLiving& cUniverse::get_target(size_t which) { + size_t maxint = -1; + if(which == maxint || which == 6) + return party; + else if(which < 6) + return party[which]; + else if(which >= 100 && which < 100 + town.monst.size()) + return town.monst[which - 100]; + else throw std::string("Tried to get nonexistent target!"); +} + extern cCustomGraphics spec_scen_g; pic_num_t cUniverse::addGraphic(pic_num_t pic, ePicType type) { diff --git a/src/classes/universe.h b/src/classes/universe.h index 24393b7e..1165c9b2 100644 --- a/src/classes/universe.h +++ b/src/classes/universe.h @@ -158,6 +158,8 @@ class cUniverse{ public: void exportSummons(); void exportGraphics(); + + iLiving& get_target(size_t which); cScenario scenario; cParty party; diff --git a/src/pcedit/pc.main.cpp b/src/pcedit/pc.main.cpp index 59742093..246eeba0 100644 --- a/src/pcedit/pc.main.cpp +++ b/src/pcedit/pc.main.cpp @@ -245,17 +245,7 @@ void handle_menu_choice(eMenu item_hit) { break; case eMenu::CURE_CONDITIONS: display_strings(4,15); - for(i = 0; i < 6; i++) { - univ.party[i].status[eStatus::POISON] = 0; - if(univ.party[i].status[eStatus::HASTE_SLOW] < 0) - univ.party[i].status[eStatus::HASTE_SLOW] = 0; - univ.party[i].status[eStatus::WEBS] = 0; - univ.party[i].status[eStatus::DISEASE] = 0; - univ.party[i].status[eStatus::DUMB] = 0; - univ.party[i].status[eStatus::ASLEEP] = 0; - univ.party[i].status[eStatus::PARALYZED] = 0; - univ.party[i].status[eStatus::ACID] = 0; - } + univ.party.clear_bad_status(); break; case eMenu::LEAVE_SCENARIO: