Create an info struct for the eStatus and ePartyStatus enums

This reintroduces the normal speed icon and opens #230
This commit is contained in:
2024-08-27 23:37:01 -04:00
parent 54050a7cbb
commit e7d5b4ff81
12 changed files with 94 additions and 60 deletions

46
src/damage.cpp Normal file
View File

@@ -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)];
}

View File

@@ -9,6 +9,9 @@
#ifndef BoE_DATA_DAMAGE_HPP
#define BoE_DATA_DAMAGE_HPP
#include <limits>
#include <boost/optional.hpp>
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<int>::max()) : icon(p), lo(m), hi(M) {}
};
boost::optional<special_icon_t> 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,

View File

@@ -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);
}

View File

@@ -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:

View File

@@ -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);
}
}
}

View File

@@ -83,16 +83,6 @@ extern cUniverse univ;
extern sf::Texture pc_gworld;
extern std::queue<pending_special_type> 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<eStatus, std::pair<short, short>> 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);

View File

@@ -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<eStatus, std::pair<short, short>> 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);

View File

@@ -7,6 +7,7 @@ tools = Split("""
drawable_manager.cpp
keymods.cpp
replay.cpp
../damage.cpp
../location.cpp
../mathutil.cpp
../porting.cpp

View File

@@ -50,7 +50,7 @@ void iLiving::clear_bad_status() {
std::map<eStatus, short> old;
status.swap(old);
std::remove_copy_if(old.begin(), old.end(), std::inserter(status, status.begin()), [](std::pair<const eStatus, short> kv) {
return isStatusNegative(kv.first) ? kv.second > 0 : kv.second < 0;
return (*kv.first).isNegative ? kv.second > 0 : kv.second < 0;
});
}