From 12c87a85af8d6ca2979d9dd8c735b66112dd0891 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Tue, 13 Jan 2015 11:45:45 -0500 Subject: [PATCH] Merge more item abilities - The strength, dexterity, and intelligence abilities have been merged; it's now possible to make items that boost some other skill, though the handling for this is not yet implemented. - The occasional haste/bless/disease abilities have been merged. - Move affect_pc and affect_party functions into cPlayer and cParty respectively --- src/boe.actions.cpp | 42 +++++++++++++------- src/boe.combat.cpp | 58 ++++++++++++++++++++------- src/boe.party.cpp | 42 ++------------------ src/boe.party.h | 2 - src/boe.specials.cpp | 82 +++++++++++++++++++-------------------- src/classes/item.cpp | 30 +++++++++----- src/classes/party.cpp | 5 +++ src/classes/party.h | 2 + src/classes/pc.cpp | 22 +++++++++++ src/classes/pc.h | 1 + src/classes/simpletypes.h | 35 ++++++++++++----- 11 files changed, 193 insertions(+), 128 deletions(-) diff --git a/src/boe.actions.cpp b/src/boe.actions.cpp index 808c989a1..8cce94610 100644 --- a/src/boe.actions.cpp +++ b/src/boe.actions.cpp @@ -2191,13 +2191,20 @@ void do_rest(long length, int hp_restore, int mp_restore) { for(int i = 0; i < 6; i++) univ.party[i].status.clear(); // Specials countdowns - if((length > 500 || age_before / 500 < univ.party.age / 500) && party_has_abil(eItemAbil::DISEASE_PARTY) && get_ran(1,0,5) == 3) { - // TODO: This seems to be the "radioactivity" handler, and the string appears to not exist. - cStrDlog display_enc_string("Missing String: Radioactivity", "", "", 8, PIC_DLOG); - display_enc_string.setSound(3); - display_enc_string.show(); + if((length > 500 || age_before / 500 < univ.party.age / 500) && party_has_abil(eItemAbil::OCCASIONAL_STATUS)) { + // TODO: There used to be a "display strings" here; should we hook in a special node call? for(int i = 0; i < 6; i++) - disease_pc(i,5); + for(int j = 0; j < 24; j++) { + cItem& item = univ.party[i].items[j]; + if(item.ability != eItemAbil::OCCASIONAL_STATUS) continue; + if(item.magic_use_type < 2) continue; + if(get_ran(1,0,5) != 3) continue; + int how_much = item.abil_data[0]; + if(item.magic_use_type % 2 == 1) how_much *= -1; + if(isStatusNegative(eStatus(item.abil_data[1]))) + how_much *= -1; + univ.party.apply_status(eStatus(item.abil_data[1]), how_much); + } } // Plants and magic shops if(length > 4000 || age_before / 4000 < univ.party.age / 4000) @@ -2293,14 +2300,21 @@ void increase_age() { } // Specials countdowns - if((univ.party.age % 500 == 0 && get_ran(1,0,5) == 3 && party_has_abil(eItemAbil::DISEASE_PARTY))) { - update_stat = true; - // TODO: This seems to be the "radioactivity" handler, and the string appears to not exist. - cStrDlog display_enc_string("Missing String: Radioactivity", "", "", 8, PIC_DLOG); - display_enc_string.setSound(3); - display_enc_string.show(); - for(i = 0; i < 6; i++) - disease_pc(i,2); + if(univ.party.age % 500 == 0 && party_has_abil(eItemAbil::OCCASIONAL_STATUS)) { + // TODO: There used to be a "display strings" here; should we hook in a special node call? + for(int i = 0; i < 6; i++) + for(int j = 0; j < 24; j++) { + cItem& item = univ.party[i].items[j]; + if(item.ability != eItemAbil::OCCASIONAL_STATUS) continue; + if(item.magic_use_type < 2) continue; + if(get_ran(1,0,5) != 3) continue; + int how_much = item.abil_data[0]; + if(item.magic_use_type % 2 == 1) how_much *= -1; + eStatus status = eStatus(item.abil_data[1]); + if(isStatusNegative(status)) + how_much *= -1; + univ.party.apply_status(status, how_much); + } } diff --git a/src/boe.combat.cpp b/src/boe.combat.cpp index 53c5d38ca..cd57f442b 100644 --- a/src/boe.combat.cpp +++ b/src/boe.combat.cpp @@ -1735,21 +1735,53 @@ void combat_run_monst() { move_to_zero(univ.party[i].status[eStatus::PARALYZED]); // Do special items - if(((item_level = get_prot_level(i,eItemAbil::OCCASIONAL_HASTE)) > 0) - && (get_ran(1,0,10) == 5)) { - update_stat = true; - univ.party[i].status[eStatus::HASTE_SLOW] += item_level / 2; - add_string_to_buf("An item hastes you!"); - } - if((item_level = get_prot_level(i,eItemAbil::OCCASIONAL_BLESS)) > 0) { - if(get_ran(1,0,10) == 5) { - update_stat = true; - univ.party[i].status[eStatus::BLESS_CURSE] += item_level / 2; - add_string_to_buf("An item blesses you!"); + for(int j = 0; j < 24; j++) { + cItem& item = univ.party[i].items[j]; + if(item.ability != eItemAbil::OCCASIONAL_STATUS) continue; + if(item.magic_use_type > 1) continue; // Affects whole party, which is handled elsewhere + if(get_ran(1,0,10) != 5) continue; + int how_much = item.abil_data[0]; + if(item.magic_use_type % 2 == 1) how_much *= -1; + eStatus status = eStatus(item.abil_data[1]); + if(isStatusNegative(status)) + how_much *= -1; + switch(status) { + case eStatus::MAIN: break; + case eStatus::HASTE_SLOW: + if(how_much > 0) add_string_to_buf("An item hastes you!"); + else add_string_to_buf("An item slows you!"); + break; + case eStatus::BLESS_CURSE: + if(how_much > 0) add_string_to_buf("An item blesses you!"); + else add_string_to_buf("An item curses you!"); + break; + case eStatus::POISON: + if(how_much > 0) add_string_to_buf("An item poisons you!"); + else if(univ.party[i].status[eStatus::POISON] > 0) + add_string_to_buf("An item cures you!"); + break; + case eStatus::INVULNERABLE: + case eStatus::MAGIC_RESISTANCE: + case eStatus::INVISIBLE: + case eStatus::MARTYRS_SHIELD: + if(how_much > 0) add_string_to_buf("An item protects you!"); + // TODO: Message for negative amounts: + break; + case eStatus::DISEASE: + if(how_much > 0) add_string_to_buf("An item diseases you!"); + else if(univ.party[i].status[eStatus::DISEASE] > 0) + add_string_to_buf("An item cures you!"); + break; + case eStatus::DUMB: + if(how_much > 0) add_string_to_buf("An item clouds your mind!"); + else if(univ.party[i].status[eStatus::DUMB] > 0) + add_string_to_buf("An item clears your mind!"); + break; + // TODO: Messages for other statuses? } + univ.party[i].apply_status(status, how_much); + update_stat = true; } - - } special_increase_age(); diff --git a/src/boe.party.cpp b/src/boe.party.cpp index f3cee957d..06f7e8e61 100644 --- a/src/boe.party.cpp +++ b/src/boe.party.cpp @@ -2283,19 +2283,14 @@ short stat_adj(short pc_num,eSkill which) { if(which == eSkill::INTELLIGENCE) { if(univ.party[pc_num].traits[eTrait::MAGICALLY_APT]) tr++; - if(pc_has_abil_equip(pc_num,eItemAbil::INTELLIGENCE) < 24) - tr++; } if(which == eSkill::STRENGTH) { if(univ.party[pc_num].traits[eTrait::STRENGTH]) tr++; - if(pc_has_abil_equip(pc_num,eItemAbil::STRENGTH) < 24) - tr++; - } - if(which == eSkill::DEXTERITY) { - if(pc_has_abil_equip(pc_num,eItemAbil::DEXTERITY) < 24) - tr++; } + // TODO: Use ability strength? + if(pc_has_abil_equip(pc_num,eItemAbil::BOOST_STAT,int(which)) < 24) + tr++; return tr; } @@ -2573,37 +2568,6 @@ void poison_party(short how_much) { for(i = 0; i < 6; i++) poison_pc(i,how_much); } -//type; // which status to affect -void affect_pc(short which_pc,eStatus type,short 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(univ.party[which_pc].main_status != eMainStatus::ALIVE) - return; - univ.party[which_pc].status[type] = minmax (-8,8,univ.party[which_pc].status[type] + how_much); - if(!allow_negative.count(type)) - univ.party[which_pc].status[type] = max(univ.party[which_pc].status[type],0); - put_pc_screen(); -} -//type; // which status to affect -void affect_party(eStatus type,short how_much) { - short i; - - for(i = 0; i < 6; i++) - if(univ.party[i].main_status == eMainStatus::ALIVE) - univ.party[i].status[type] = minmax (-8,8,univ.party[i].status[type] + how_much); - put_pc_screen(); -} void void_sanctuary(short pc_num) { if(univ.party[pc_num].status[eStatus::INVISIBLE] > 0) { diff --git a/src/boe.party.h b/src/boe.party.h index ed4f450bf..1a0df9c24 100644 --- a/src/boe.party.h +++ b/src/boe.party.h @@ -49,8 +49,6 @@ 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 affect_pc(short which_pc,eStatus type,short how_much); -void affect_party(eStatus type,short how_much); void void_sanctuary(short pc_num); void hit_party(short how_much,eDamageType damage_type); void slay_party(eMainStatus mode); diff --git a/src/boe.specials.cpp b/src/boe.specials.cpp index 1ab61c3e8..1c92bb868 100644 --- a/src/boe.specials.cpp +++ b/src/boe.specials.cpp @@ -391,10 +391,10 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho slow_pc(i,ter_flag1.s); break; case eStatus::INVULNERABLE: // Should say "You feel odd." / "You feel protected."? - affect_pc(i,eStatus::INVULNERABLE,ter_flag1.u); + univ.party[i].apply_status(eStatus::INVULNERABLE,ter_flag1.u); break; case eStatus::MAGIC_RESISTANCE: // Should say "You feel odd." / "You feel protected."? - affect_pc(i,eStatus::MAGIC_RESISTANCE,ter_flag1.u); + 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); @@ -405,13 +405,13 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho case eStatus::INVISIBLE: if(ter_flag1.s < 0) add_string_to_buf("You feel obscure."); else add_string_to_buf("You feel exposed."); - affect_pc(i,eStatus::INVISIBLE,ter_flag1.s); + 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); break; case eStatus::MARTYRS_SHIELD: // Should say "You feel dull." / "You start to glow slightly."? - affect_pc(i,eStatus::MARTYRS_SHIELD,ter_flag1.u); + 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); @@ -695,8 +695,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You feel blessed."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::HASTE_SLOW: // TODO: Is this the right sound? @@ -706,8 +706,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You feel speedy."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::INVULNERABLE: // TODO: Is this the right sound? @@ -717,8 +717,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You feel protected."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::MAGIC_RESISTANCE: // TODO: Is this the right sound? @@ -728,8 +728,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You feel protected."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::WEBS: if(type % 2 == 1) @@ -739,8 +739,8 @@ void use_item(short pc,short item) { str = str * -1; } if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::INVISIBLE: // TODO: Is this the right sound? @@ -750,8 +750,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You feel obscure."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::MARTYRS_SHIELD: // TODO: Is this the right sound? @@ -761,8 +761,8 @@ void use_item(short pc,short item) { str = str * -1; }else ASB(" You start to glow slightly."); if(type > 1) - affect_party(status,str); - else affect_pc(pc,status,str); + univ.party.apply_status(status,str); + else univ.party[pc].apply_status(status,str); break; case eStatus::POISON: switch(type) { @@ -788,7 +788,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel healthy."); - affect_pc(pc,eStatus::DISEASE,-1 * str); + univ.party[pc].apply_status(eStatus::DISEASE,-1 * str); break; case 1: ASB(" You feel sick."); @@ -796,7 +796,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all feel healthy."); - affect_party(eStatus::DISEASE,-1 * str); + univ.party.apply_status(eStatus::DISEASE,-1 * str); break; case 3: ASB(" You all feel sick."); @@ -809,7 +809,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel clear headed."); - affect_pc(pc,eStatus::DUMB,-1 * str); + univ.party[pc].apply_status(eStatus::DUMB,-1 * str); break; case 1: ASB(" You feel confused."); @@ -817,7 +817,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all feel clear headed."); - affect_party(eStatus::DUMB,-1 * str); + univ.party.apply_status(eStatus::DUMB,-1 * str); break; case 3: ASB(" You all feel confused."); @@ -830,7 +830,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You feel alert."); - affect_pc(pc,eStatus::ASLEEP,-1 * str); + univ.party[pc].apply_status(eStatus::ASLEEP,-1 * str); break; case 1: ASB(" You feel very tired."); @@ -838,7 +838,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all feel alert."); - affect_party(eStatus::ASLEEP,-1 * str); + univ.party.apply_status(eStatus::ASLEEP,-1 * str); break; case 3: ASB(" You all feel very tired."); @@ -851,7 +851,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" You find it easier to move."); - affect_pc(pc,eStatus::PARALYZED,-1 * str * 100); + univ.party[pc].apply_status(eStatus::PARALYZED,-1 * str * 100); break; case 1: ASB(" You feel very stiff."); @@ -859,7 +859,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all find it easier to move."); - affect_party(eStatus::PARALYZED,-1 * str * 100); + univ.party.apply_status(eStatus::PARALYZED,-1 * str * 100); break; case 3: ASB(" You all feel very stiff."); @@ -872,7 +872,7 @@ void use_item(short pc,short item) { switch(type) { case 0: ASB(" Your skin tingles pleasantly."); - affect_pc(pc,eStatus::ACID,-1 * str); + univ.party[pc].apply_status(eStatus::ACID,-1 * str); break; case 1: ASB(" Your skin burns!"); @@ -880,7 +880,7 @@ void use_item(short pc,short item) { break; case 2: ASB(" You all tingle pleasantly."); - affect_party(eStatus::ACID,-1 * str); + univ.party.apply_status(eStatus::ACID,-1 * str); break; case 3: ASB(" Everyone's skin burns!"); @@ -895,14 +895,12 @@ void use_item(short pc,short item) { case 0: case 1: ASB(" You feel wonderful!"); heal_pc(pc,str * 20); - affect_pc(pc,eStatus::BLESS_CURSE,str); + univ.party[pc].apply_status(eStatus::BLESS_CURSE,str); break; case 2: case 3: ASB(" Everyone feels wonderful!"); - for(i = 0; i < 6; i++) { - heal_pc(i,str * 20); - affect_pc(i,eStatus::BLESS_CURSE,str); - } + heal_party(str*20); + univ.party.apply_status(eStatus::BLESS_CURSE,str); break; } break; @@ -2664,18 +2662,18 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, case eSpecType::AFFECT_INVULN: for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::INVULNERABLE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::INVULNERABLE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); break; case eSpecType::AFFECT_MAGIC_RES: for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::MAGIC_RESISTANCE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::MAGIC_RESISTANCE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); break; case eSpecType::AFFECT_WEBS: if(spec.ex2a < 0) { for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::WEBS,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::WEBS,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); } else { if(univ.town.monst[spec.ex2a].active > 0) { @@ -2690,7 +2688,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, if(spec.ex2a < 0) { for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::DISEASE,spec.ex1a * ((spec.ex1b != 0) ? 1: -1)); + univ.party[i].apply_status(eStatus::DISEASE,spec.ex1a * ((spec.ex1b != 0) ? 1: -1)); } else { if(univ.town.monst[spec.ex2a].active > 0) { @@ -2704,13 +2702,13 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, case eSpecType::AFFECT_SANCTUARY: for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::INVISIBLE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::INVISIBLE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); break; case eSpecType::AFFECT_CURSE_BLESS: if(spec.ex2a < 0) { for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::BLESS_CURSE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::BLESS_CURSE,spec.ex1a * ((spec.ex1b != 0) ? -1: 1)); } else { if(univ.town.monst[spec.ex2a].active > 0) { @@ -2725,7 +2723,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, if(spec.ex2a < 0) { for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) - affect_pc(i,eStatus::DUMB,spec.ex1a * ((spec.ex1b == 0) ? -1: 1)); + univ.party[i].apply_status(eStatus::DUMB,spec.ex1a * ((spec.ex1b == 0) ? -1: 1)); } else { if(univ.town.monst[spec.ex2a].active > 0) { @@ -2741,7 +2739,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) { if(spec.ex1b == 0) { - affect_pc(i,eStatus::ASLEEP,-1 * spec.ex1a); + univ.party[i].apply_status(eStatus::ASLEEP,-1 * spec.ex1a); } else sleep_pc(i,spec.ex1a,eStatus::ASLEEP,10); } @@ -2760,7 +2758,7 @@ void affect_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type, for(i = 0; i < 6; i++) if((pc < 0) || (pc == i)) { if(spec.ex1b == 0) { - affect_pc(i,eStatus::PARALYZED,-1 * spec.ex1a); + univ.party[i].apply_status(eStatus::PARALYZED,-1 * spec.ex1a); } else sleep_pc(i,spec.ex1a,eStatus::PARALYZED,10); } diff --git a/src/classes/item.cpp b/src/classes/item.cpp index c34d7b5a0..60245bb63 100644 --- a/src/classes/item.cpp +++ b/src/classes/item.cpp @@ -349,14 +349,20 @@ void cItem::append(legacy::item_record_type& old){ case 37: ability = eItemAbil::SKILL; break; - case 38: - ability = eItemAbil::STRENGTH; + case 38: // Strength + ability = eItemAbil::BOOST_STAT; + abil_data[0] = 1; + abil_data[1] = int(eSkill::STRENGTH); break; - case 39: - ability = eItemAbil::DEXTERITY; + case 39: // Dexterity + ability = eItemAbil::BOOST_STAT; + abil_data[0] = 1; + abil_data[1] = int(eSkill::DEXTERITY); break; - case 40: - ability = eItemAbil::INTELLIGENCE; + case 40: // Intelligence + ability = eItemAbil::BOOST_STAT; + abil_data[0] = 1; + abil_data[1] = int(eSkill::INTELLIGENCE); break; case 41: ability = eItemAbil::ACCURACY; @@ -374,10 +380,14 @@ void cItem::append(legacy::item_record_type& old){ ability = eItemAbil::HEAVIER_OBJECT; break; case 46: - ability = eItemAbil::OCCASIONAL_BLESS; + ability = eItemAbil::OCCASIONAL_STATUS; + abil_data[1] = int(eStatus::BLESS_CURSE); + magic_use_type = 0; break; case 47: - ability = eItemAbil::OCCASIONAL_HASTE; + ability = eItemAbil::OCCASIONAL_STATUS; + abil_data[1] = int(eStatus::HASTE_SLOW); + magic_use_type = 0; break; case 48: ability = eItemAbil::LIFE_SAVING; @@ -392,7 +402,9 @@ void cItem::append(legacy::item_record_type& old){ ability = eItemAbil::POISON_AUGMENT; break; case 52: - ability = eItemAbil::DISEASE_PARTY; + ability = eItemAbil::OCCASIONAL_STATUS; + abil_data[1] = int(eStatus::DISEASE); + magic_use_type = 3; break; case 53: ability = eItemAbil::WILL; diff --git a/src/classes/party.cpp b/src/classes/party.cpp index 1ee3e6bd2..ce3ec06a2 100644 --- a/src/classes/party.cpp +++ b/src/classes/party.cpp @@ -231,6 +231,11 @@ bool cParty::record(eEncNoteType type, const std::string& what, const std::strin return false; } +void cParty::apply_status(eStatus which, int how_much) { + for(int i = 0; i < 6; i++) + adven[i].apply_status(which, how_much); +} + bool cParty::start_timer(short time, short node, short type){ if(party_event_timers.size() == party_event_timers.max_size()) return false; // Shouldn't be reached cTimer t; diff --git a/src/classes/party.h b/src/classes/party.h index cb88bd10a..6fc4b256d 100644 --- a/src/classes/party.h +++ b/src/classes/party.h @@ -127,6 +127,8 @@ public: void append(legacy::stored_items_list_type& old,short which_list); void append(legacy::setup_save_type& old); + void apply_status(eStatus which, int how_much); + void add_pc(legacy::pc_record_type old); void add_pc(cPlayer new_pc); void void_pcs(); diff --git a/src/classes/pc.cpp b/src/classes/pc.cpp index 0e0bba922..4cd9ae7d4 100644 --- a/src/classes/pc.cpp +++ b/src/classes/pc.cpp @@ -15,6 +15,7 @@ #include "classes.h" #include "oldstructs.h" +#include "mathutil.hpp" void cPlayer::append(legacy::pc_record_type old){ int i; @@ -75,6 +76,27 @@ 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::finish_create() { // Start items switch(race) { diff --git a/src/classes/pc.h b/src/classes/pc.h index 89641bba9..2eee28f9e 100644 --- a/src/classes/pc.h +++ b/src/classes/pc.h @@ -49,6 +49,7 @@ public: short marked_damage, dir, parry, last_attacked; void finish_create(); + void apply_status(eStatus which, int how_much); void append(legacy::pc_record_type old); cPlayer(); diff --git a/src/classes/simpletypes.h b/src/classes/simpletypes.h index 95d718f5e..26280ea2b 100644 --- a/src/classes/simpletypes.h +++ b/src/classes/simpletypes.h @@ -103,13 +103,34 @@ enum class eStatus { ASLEEP = 11, PARALYZED = 12, ACID = 13, - FORCECAGE = 14, // This is new and currently unused, since forcecages aren't even really implemented yet. + FORCECAGE = 14, // This one is new // It's not quite a real status effect since it doesn't expire - // We use 15 because 14 was technically a "reserved/unused" status, though it was never used for anything CHARM = 15, }; +inline bool isStatusNegative(eStatus stat) { + switch(stat) { + case eStatus::POISONED_WEAPON: return false; + case eStatus::BLESS_CURSE: return false; + case eStatus::POISON: return true; + case eStatus::HASTE_SLOW: return false; + case eStatus::INVULNERABLE: return false; + case eStatus::MAGIC_RESISTANCE: return false; + case eStatus::WEBS: return true; + case eStatus::DISEASE: return true; + case eStatus::INVISIBLE: return false; + case eStatus::DUMB: return true; + case eStatus::MARTYRS_SHIELD: return false; + case eStatus::ASLEEP: return true; + case eStatus::PARALYZED: return true; + case eStatus::ACID: return true; + case eStatus::FORCECAGE: return true; + case eStatus::CHARM: return true; + } + return false; +} + /* Special Ability a.k.a spec_skill */ enum eMonstAbil { @@ -304,21 +325,17 @@ enum class eItemAbil { FULL_PROTECTION = 31, STATUS_PROTECTION = 36, SKILL = 37, - STRENGTH = 38, - DEXTERITY = 39, - INTELLIGENCE = 40, + BOOST_STAT = 38, ACCURACY = 41, THIEVING = 42, GIANT_STRENGTH = 43, LIGHTER_OBJECT = 44, HEAVIER_OBJECT = 45, - OCCASIONAL_BLESS = 46, - OCCASIONAL_HASTE = 47, + OCCASIONAL_STATUS = 46, LIFE_SAVING = 48, PROTECT_FROM_PETRIFY = 49, REGENERATE = 50, POISON_AUGMENT = 51, - DISEASE_PARTY = 52, WILL = 53, FREE_ACTION = 54, SPEED = 55, @@ -345,7 +362,7 @@ enum class eItemAbil { QUICKFIRE = 129, // Reagents HOLLY = 150, // Holly/Toadstool - COMFREY = 151, // Comfreey Root + COMFREY = 151, // Comfrey Root NETTLE = 152, // Glowing Nettle WORMGRASS = 153, // Crypt Shroom/Wormgrass ASPTONGUE = 154, // Asptongue Mold