diff --git a/proj/vs2017/Common/Common.vcxproj b/proj/vs2017/Common/Common.vcxproj index 2d87ee8e..f172b3d7 100644 --- a/proj/vs2017/Common/Common.vcxproj +++ b/proj/vs2017/Common/Common.vcxproj @@ -387,6 +387,7 @@ + diff --git a/proj/vs2017/Common/Common.vcxproj.filters b/proj/vs2017/Common/Common.vcxproj.filters index 50afff6a..2f45390d 100644 --- a/proj/vs2017/Common/Common.vcxproj.filters +++ b/proj/vs2017/Common/Common.vcxproj.filters @@ -716,6 +716,7 @@ Universe + diff --git a/proj/xc12/BoE.xcodeproj/project.pbxproj b/proj/xc12/BoE.xcodeproj/project.pbxproj index 821a2243..8ad5013f 100755 --- a/proj/xc12/BoE.xcodeproj/project.pbxproj +++ b/proj/xc12/BoE.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ 9153C79E1A994A0D00D7F8A7 /* SFML.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; 9153C79F1A994A1300D7F8A7 /* SFML.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; 9153C7A01A994A1700D7F8A7 /* SFML.framework in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; + 915473BF2C7E11B900EB1C94 /* damage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 915473BE2C7E11B900EB1C94 /* damage.cpp */; }; 915AF9E81BBF8B5C008AEF49 /* scrollpane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A81BBE2B54009905A4 /* scrollpane.cpp */; }; 9176FEC71D550EFE006EF694 /* out_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC01D550EFC006EF694 /* out_legacy.cpp */; }; 9176FEC81D550EFE006EF694 /* scen_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC11D550EFC006EF694 /* scen_legacy.cpp */; }; @@ -690,6 +691,7 @@ 914F412E23EBD27500DB53BD /* town.xsd */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = town.xsd; sourceTree = ""; }; 915325161A2E1DA8000A9A1C /* oldstructs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oldstructs.cpp; sourceTree = ""; }; 915325181A2E37EE000A9A1C /* special_parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = special_parse.cpp; sourceTree = ""; }; + 915473BE2C7E11B900EB1C94 /* damage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = damage.cpp; sourceTree = ""; }; 91574CC323CB97C5004766F8 /* enum_map.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = enum_map.hpp; sourceTree = ""; }; 91597A6C1A3BED2D00BE7BF9 /* spell.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = spell.hpp; sourceTree = ""; }; 91597A6E1A3BEDC700BE7BF9 /* spell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spell.cpp; sourceTree = ""; }; @@ -1329,6 +1331,7 @@ 9185BDA41EA053E00027C346 /* misc */ = { isa = PBXGroup; children = ( + 915473BE2C7E11B900EB1C94 /* damage.cpp */, 91279BE10F9D0F73007B0D52 /* location.cpp */, 91B3F11E0F97801F00BF5B67 /* mathutil.cpp */, 915325161A2E1DA8000A9A1C /* oldstructs.cpp */, @@ -2095,6 +2098,7 @@ 9149924B25913E3F00B5BE97 /* container.cpp in Sources */, 9149924D25913E3F00B5BE97 /* led.cpp in Sources */, 9149924F25913E3F00B5BE97 /* ledgroup.cpp in Sources */, + 915473BF2C7E11B900EB1C94 /* damage.cpp in Sources */, 91499253259140FF00B5BE97 /* keycodes.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/src/damage.cpp b/src/damage.cpp new file mode 100644 index 00000000..3331ade1 --- /dev/null +++ b/src/damage.cpp @@ -0,0 +1,46 @@ +// +// damage.cpp +// BoE +// +// Created by Celtic Minstrel on 2023-08-27. +// +// + +#include "damage.hpp" + +static status_info_t status_info[int(eStatus::CHARM) + 1] = { + {false, 4}, // POISONED_WEAPON + {false, 2, 3}, // BLESS_CURSE + {true, 0, -1, {1, 4}}, // POISON + {false, 6, 8, {7, 0, 0}}, // HASTE_SLOW + {false, 5}, // INVULNERABLE + {false, 9, 19}, // MAGIC_RESISTANCE + {true, 10}, // WEBS + {true, 11}, // DISEASE + {false, 12}, // INVISIBLE + {true, 13, 18}, // DUMB + {false, 14}, // MARTYRS_SHIELD + {true, 15, 21}, // ASLEEP + {true, 16}, // PARALYZED + {true, 17}, // ACIDS + {true, 20}, // FORCECAGE + {true, 22}, // CHARM +}; + +static status_info_t party_status_info[int(ePartyStatus::FIREWALK) + 1] = { + {false, 26}, // STEALTH + {false, 23}, // FLIGHT + {false, 24}, // DETECT_LIFE + {false, 25}, // FIREWALK +}; + +status_info_t dummy_main_info{}; + +const status_info_t& operator* (eStatus status) { + if(status == eStatus::MAIN) return dummy_main_info; + return status_info[int(status)]; +} + +const status_info_t& operator* (ePartyStatus status) { + return party_status_info[int(status)]; +} diff --git a/src/damage.hpp b/src/damage.hpp index efaf94a5..71f4a010 100644 --- a/src/damage.hpp +++ b/src/damage.hpp @@ -9,6 +9,9 @@ #ifndef BoE_DATA_DAMAGE_HPP #define BoE_DATA_DAMAGE_HPP +#include +#include + enum class eDamageType { WEAPON = 0, FIRE = 1, @@ -45,29 +48,6 @@ enum class eStatus { CHARM = 15, }; -inline bool isStatusNegative(eStatus stat) { - switch(stat) { - case eStatus::MAIN: return false; - 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; -} - enum class ePartyStatus { STEALTH, FLIGHT, @@ -75,6 +55,22 @@ enum class ePartyStatus { FIREWALK, }; +struct status_info_t { + bool isNegative = false; + int icon = -1, negIcon = -1; + struct special_icon_t { + int icon, lo, hi; + special_icon_t(int p, int m, int M = std::numeric_limits::max()) : icon(p), lo(m), hi(M) {} + }; + boost::optional special; + status_info_t() = default; + status_info_t(bool neg, int p1, int p2 = -1) : isNegative(neg), icon(p1), negIcon(p2) {} + status_info_t(bool neg, int p1, int p2, special_icon_t spec) : isNegative(neg), icon(p1), negIcon(p2), special(spec) {} +}; + +const status_info_t& operator* (eStatus status); +const status_info_t& operator* (ePartyStatus status); + enum class eMainStatus { ABSENT = 0, // absent, empty slot ALIVE = 1, diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index abb6a990..91b0ef67 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -2310,7 +2310,7 @@ void do_rest(long length, int hp_restore, int mp_restore) { if(get_ran(1,0,5) != 3) continue; int how_much = item.abil_strength; if(item.abil_harms()) how_much *= -1; - if(isStatusNegative(item.abil_data.status)) + if((*item.abil_data.status).isNegative) how_much *= -1; univ.party.apply_status(item.abil_data.status, how_much); } @@ -2429,7 +2429,7 @@ void increase_age() { int how_much = item.abil_strength; if(item.abil_harms()) how_much *= -1; eStatus status = item.abil_data.status; - if(isStatusNegative(status)) + if((*status).isNegative) how_much *= -1; univ.party.apply_status(status, how_much); } diff --git a/src/game/boe.combat.cpp b/src/game/boe.combat.cpp index 0dd913e1..ec1a4470 100644 --- a/src/game/boe.combat.cpp +++ b/src/game/boe.combat.cpp @@ -2097,7 +2097,7 @@ void combat_run_monst() { int how_much = item.abil_strength; if(item.abil_harms()) how_much *= -1; eStatus status = item.abil_data.status; - if(isStatusNegative(status)) + if((*status).isNegative) how_much *= -1; switch(status) { case eStatus::MAIN: case eStatus::CHARM: diff --git a/src/game/boe.graphics.cpp b/src/game/boe.graphics.cpp index 36429023..c862fadb 100644 --- a/src/game/boe.graphics.cpp +++ b/src/game/boe.graphics.cpp @@ -643,21 +643,12 @@ void put_text_bar(std::string str) { to_rect.left = to_rect.right - 15; to_rect.width() = 12; to_rect.height() = 12; - if(univ.party.status[ePartyStatus::STEALTH] > 0) { - rect_draw_some_item(status_gworld, get_stat_effect_rect(26), text_bar_gworld, to_rect, sf::BlendAlpha); - to_rect.offset(-15, 0); - } - if(univ.party.status[ePartyStatus::FLIGHT] > 0) { - rect_draw_some_item(status_gworld, get_stat_effect_rect(23), text_bar_gworld, to_rect, sf::BlendAlpha); - to_rect.offset(-15, 0); - } - if(univ.party.status[ePartyStatus::DETECT_LIFE] > 0) { - rect_draw_some_item(status_gworld, get_stat_effect_rect(24), text_bar_gworld, to_rect, sf::BlendAlpha); - to_rect.offset(-15, 0); - } - if(univ.party.status[ePartyStatus::FIREWALK] > 0) { - rect_draw_some_item(status_gworld, get_stat_effect_rect(25), text_bar_gworld, to_rect, sf::BlendAlpha); - to_rect.offset(-15, 0); + for(auto next : univ.party.status) { + const auto& statInfo = *next.first; + if(next.second > 0) { + rect_draw_some_item(status_gworld, get_stat_effect_rect(statInfo.icon), text_bar_gworld, to_rect, sf::BlendAlpha); + to_rect.offset(-15, 0); + } } } diff --git a/src/game/boe.party.cpp b/src/game/boe.party.cpp index 4d879b56..d15e27c6 100644 --- a/src/game/boe.party.cpp +++ b/src/game/boe.party.cpp @@ -83,16 +83,6 @@ extern cUniverse univ; extern sf::Texture pc_gworld; extern std::queue special_queue; -// First icon is displayed for positive values, second for negative, if -1 no negative icon. -// This omits two special cases - major poison, and normal speed; they are hard-coded. -std::map> statIcons = { - {eStatus::POISONED_WEAPON, {4,-1}}, {eStatus::BLESS_CURSE, {2,3}}, {eStatus::POISON, {0,-1}}, - {eStatus::HASTE_SLOW, {6,8}}, {eStatus::INVULNERABLE, {5,-1}}, {eStatus::MAGIC_RESISTANCE, {9,19}}, - {eStatus::WEBS, {10,-1}}, {eStatus::DISEASE, {11,-1}}, {eStatus::INVISIBLE, {12,-1}}, - {eStatus::DUMB, {13,18}}, {eStatus::MARTYRS_SHIELD, {14,-1}}, {eStatus::ASLEEP, {15,21}}, - {eStatus::PARALYZED, {16,-1}}, {eStatus::ACID, {17,-1}}, {eStatus::FORCECAGE, {20,-1}}, -}; - // Variables for spell selection short on_which_spell_page = 0; short store_last_cast_mage = 6,store_last_cast_priest = 6; @@ -1635,10 +1625,12 @@ static void put_target_status_graphics(cDialog& me, short for_pc) { pic.setFormat(TXT_FRAME, FRM_NONE); if(isAlive) { short placedIcon = -1; - if(next.first == eStatus::POISON && next.second > 4) placedIcon = 1; - else if(next.second > 0) placedIcon = statIcons[next.first].first; - else if(next.second < 0) placedIcon = statIcons[next.first].second; - else if(next.first == eStatus::HASTE_SLOW) placedIcon = 7; + const auto& statInfo = *next.first; + if(statInfo.special && next.second >= statInfo.special->lo && next.second <= statInfo.special->hi) { + placedIcon = statInfo.special->icon; + } + else if(next.second > 0) placedIcon = statInfo.icon; + else if(next.second < 0) placedIcon = statInfo.negIcon; if(placedIcon >= 0) { pic.show(); pic.setPict(placedIcon); diff --git a/src/game/boe.text.cpp b/src/game/boe.text.cpp index b3ad55fc..5c449fad 100644 --- a/src/game/boe.text.cpp +++ b/src/game/boe.text.cpp @@ -82,7 +82,6 @@ extern short store_selling_values[8]; extern short combat_posing_monster, current_working_monster; // 0-5 PC 100 + x - monster x extern bool supressing_some_spaces; extern location ok_space[4]; -extern std::map> statIcons; // Draws the pc area in upper right void put_pc_screen() { @@ -642,9 +641,12 @@ void draw_pc_effects(short pc) { sf::Texture& status_gworld = *ResMgr::graphics.get("staticons"); for(auto next : univ.party[pc].status) { short placedIcon = -1; - if(next.first == eStatus::POISON && next.second > 4) placedIcon = 1; - else if(next.second > 0) placedIcon = statIcons[next.first].first; - else if(next.second < 0) placedIcon = statIcons[next.first].second; + const auto& statInfo = *next.first; + if(statInfo.special && next.second >= statInfo.special->lo && next.second <= statInfo.special->hi) { + placedIcon = statInfo.special->icon; + } + else if(next.second > 0) placedIcon = statInfo.icon; + else if(next.second < 0) placedIcon = statInfo.negIcon; if(placedIcon >= 0) { rect_draw_some_item(status_gworld, get_stat_effect_rect(placedIcon), pc_stats_gworld, dest_rect, sf::BlendAlpha); dest_rect.offset(13, 0); diff --git a/src/tools/SConscript b/src/tools/SConscript index 7ec445aa..d0a174cb 100644 --- a/src/tools/SConscript +++ b/src/tools/SConscript @@ -7,6 +7,7 @@ tools = Split(""" drawable_manager.cpp keymods.cpp replay.cpp + ../damage.cpp ../location.cpp ../mathutil.cpp ../porting.cpp diff --git a/src/universe/living.cpp b/src/universe/living.cpp index 2f3f13a9..e8ab1401 100644 --- a/src/universe/living.cpp +++ b/src/universe/living.cpp @@ -50,7 +50,7 @@ void iLiving::clear_bad_status() { std::map old; status.swap(old); std::remove_copy_if(old.begin(), old.end(), std::inserter(status, status.begin()), [](std::pair kv) { - return isStatusNegative(kv.first) ? kv.second > 0 : kv.second < 0; + return (*kv.first).isNegative ? kv.second > 0 : kv.second < 0; }); }