Add an info structure for eItemType enum

This commit is contained in:
2017-04-15 02:03:42 -04:00
parent c2ce2a2cd1
commit 1f9615d185
7 changed files with 78 additions and 70 deletions

View File

@@ -2278,7 +2278,7 @@ bool damage_pc(cPlayer& which_pc,short how_much,eDamageType damage_type,eRace ty
how_much -= minmax(-5,5,which_pc.status[eStatus::BLESS_CURSE]);
for(short i = 0; i < which_pc.items.size(); i++) {
if((which_pc.items[i].variety != eItemType::NO_ITEM) && (which_pc.equip[i])) {
if(isArmourType(which_pc.items[i].variety)) {
if((*which_pc.items[i].variety).is_armour) {
r1 = get_ran(1,1,which_pc.items[i].item_level);
how_much -= r1;

View File

@@ -314,7 +314,7 @@ void put_item_screen(short screen_num) {
style.italic = true;
if(univ.party[pc].items[i_num].variety == eItemType::ONE_HANDED || univ.party[pc].items[i_num].variety == eItemType::TWO_HANDED)
style.colour = sf::Color::Magenta;
else if(isArmourType(univ.party[pc].items[i_num].variety))
else if((*univ.party[pc].items[i_num].variety).is_armour)
style.colour = sf::Color::Green;
else style.colour = sf::Color::Blue;
} else style.colour = sf::Color::Black;
@@ -394,7 +394,7 @@ void place_buy_button(short position,short pc_num,short item_num) {
}
break;
case MODE_SELL_WEAP:
if(isWeaponType(univ.party[pc_num].items[item_num].variety) &&
if((*univ.party[pc_num].items[item_num].variety).is_weapon &&
(!univ.party[pc_num].equip[item_num]) &&
(univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) &&
(!univ.party[pc_num].items[item_num].unsellable)) {
@@ -403,7 +403,7 @@ void place_buy_button(short position,short pc_num,short item_num) {
}
break;
case MODE_SELL_ARMOR:
if(isArmourType(univ.party[pc_num].items[item_num].variety) &&
if((*univ.party[pc_num].items[item_num].variety).is_armour &&
(!univ.party[pc_num].equip[item_num]) &&
(univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) &&
(!univ.party[pc_num].items[item_num].unsellable)) {

View File

@@ -24,25 +24,50 @@
#include "spell.hpp"
#include "race.hpp"
extern const std::multiset<eItemType> equippable = {
eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::BOW, eItemType::ARROW, eItemType::THROWN_MISSILE,
eItemType::TOOL, eItemType::SHIELD, eItemType::ARMOR, eItemType::HELM, eItemType::GLOVES,
eItemType::SHIELD_2, eItemType::BOOTS, eItemType::RING, eItemType::NECKLACE, eItemType::PANTS,
eItemType::CROSSBOW, eItemType::BOLTS, eItemType::MISSILE_NO_AMMO,
// And these are the ones that you can equip two of
eItemType::ONE_HANDED, eItemType::RING,
};
static std::array<item_variety_t, 28> load_item_type_info() {
std::multiset<eItemType> equippable = {
eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::BOW, eItemType::ARROW, eItemType::THROWN_MISSILE,
eItemType::TOOL, eItemType::SHIELD, eItemType::ARMOR, eItemType::HELM, eItemType::GLOVES,
eItemType::SHIELD_2, eItemType::BOOTS, eItemType::RING, eItemType::NECKLACE, eItemType::PANTS,
eItemType::CROSSBOW, eItemType::BOLTS, eItemType::MISSILE_NO_AMMO,
// And these are the ones that you can equip two of
eItemType::ONE_HANDED, eItemType::RING,
};
std::multiset<eItemType> num_hands_to_use = {
eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::TWO_HANDED, eItemType::SHIELD, eItemType::SHIELD_2,
};
// For following, if an item of type n is equipped, no other items of type n can be equipped,
std::map<const eItemType, const eItemCat> excluding_types = {
{eItemType::BOW, eItemCat::MISSILE_WEAPON},
{eItemType::CROSSBOW, eItemCat::MISSILE_WEAPON},
{eItemType::MISSILE_NO_AMMO, eItemCat::MISSILE_WEAPON},
{eItemType::ARROW, eItemCat::MISSILE_AMMO},
{eItemType::THROWN_MISSILE, eItemCat::MISSILE_AMMO},
{eItemType::BOLTS, eItemCat::MISSILE_AMMO},
};
std::array<item_variety_t, 28> all_info;
int i = -1;
for(auto& info : all_info) {
eItemType type = eItemType(++i);
info.self = type;
// TODO: Maybe don't base these on i?
info.is_armour = i >= 12 && i <= 17;
info.is_weapon = (i >= 1 && i <= 6 && i != 3) || (i >= 23 && i <= 25);
info.is_missile = i == 5 || i == 6 || i == 24 || i == 25;
info.equip_count = equippable.count(type);
info.num_hands = num_hands_to_use.count(type);
info.exclusion = info.num_hands ? eItemCat::HANDS : excluding_types[type];
}
return all_info;
}
extern const std::multiset<eItemType> num_hands_to_use = {
eItemType::ONE_HANDED, eItemType::TWO_HANDED, eItemType::TWO_HANDED, eItemType::SHIELD, eItemType::SHIELD_2,
};
// For following, if an item of type n is equipped, no other items of type n can be equipped,
// TODO: Should SHIELD and SHIELD_2 have an entry here?
std::map<const eItemType, const short> excluding_types = {
{eItemType::BOW, 2}, {eItemType::ARROW, 1}, {eItemType::THROWN_MISSILE, 1},
{eItemType::CROSSBOW, 2}, {eItemType::BOLTS, 1}, {eItemType::MISSILE_NO_AMMO, 2}
};
const item_variety_t& operator*(eItemType type) {
static std::array<item_variety_t, 28> item_type_info = load_item_type_info();
return item_type_info[int(type)];
}
unsigned char cItem::rec_treas_class() const {
short tmp = value;

View File

@@ -44,19 +44,18 @@ enum class eItemType {
QUEST = 27,
};
inline bool isArmourType(eItemType type) {
int code = (int) type;
return code >= 12 && code <= 17;
}
enum class eItemCat {
MISC, MISSILE_WEAPON, MISSILE_AMMO, HANDS,
};
inline bool isWeaponType(eItemType type) {
int code = (int) type;
return (code >= 1 && code <= 6 && code != 3) || (code >= 23 && code <= 25);
}
struct item_variety_t {
eItemType self;
bool is_armour, is_weapon, is_missile;
int equip_count, num_hands;
eItemCat exclusion;
};
inline bool isMissileType(eItemType type) {
return type == eItemType::ARROW || type == eItemType::BOLTS || type == eItemType::THROWN_MISSILE || type == eItemType::MISSILE_NO_AMMO;
}
const item_variety_t& operator*(eItemType type);
enum class eItemUse {HELP_ONE, HARM_ONE, HELP_ALL, HARM_ALL};

View File

@@ -47,7 +47,6 @@ extern ter_num_t template_terrain[64][64];
extern cScenario scenario;
extern cCustomGraphics spec_scen_g;
extern location cur_out;
extern const std::multiset<eItemType> equippable;
const std::set<eItemAbil> items_no_strength = {
eItemAbil::NONE, eItemAbil::HEALING_WEAPON, eItemAbil::RETURNING_MISSILE, eItemAbil::SEEKING_MISSILE, eItemAbil::DRAIN_MISSILES,
@@ -1918,7 +1917,7 @@ static bool edit_item_abil_event_filter(cDialog& me, std::string hit, cItem& ite
put_item_abils_in_dlog(me, item, which);
} else if(hit == "weapon") {
save_item_abils(me, item);
if(!isWeaponType(item.variety)) {
if(!(*item.variety).is_weapon) {
showError("You can only give an ability of this sort to a weapon.","",&me);
return true;
}
@@ -1936,7 +1935,7 @@ static bool edit_item_abil_event_filter(cDialog& me, std::string hit, cItem& ite
put_item_abils_in_dlog(me, item, which);
} else if(hit == "general") {
save_item_abils(me, item);
if(equippable.count(item.variety) == 0 || item.variety == eItemType::ARROW || item.variety == eItemType::THROWN_MISSILE || item.variety == eItemType::BOLTS){
if((*item.variety).equip_count == 0 || item.variety == eItemType::ARROW || item.variety == eItemType::THROWN_MISSILE || item.variety == eItemType::BOLTS){
showError("You can only give an ability of this sort to an non-missile item which can be equipped (like armor, or a ring).",&me);
return true;
}

View File

@@ -439,9 +439,9 @@ void writeItemsToXml(ticpp::Printer&& data, cScenario& scenario) {
data.PushElement("protection", item.protection);
if(item.charges > 0)
data.PushElement("charges", item.charges);
if(isWeaponType(item.variety) && item.variety != eItemType::ARROW && item.variety != eItemType::BOLTS)
if((*item.variety).is_weapon && item.variety != eItemType::ARROW && item.variety != eItemType::BOLTS)
data.PushElement("weapon-type", item.weap_type);
if(item.missile > 0 || isMissileType(item.variety))
if(item.missile > 0 || (*item.variety).is_missile)
data.PushElement("missile-type", item.missile);
data.PushElement("pic", item.graphic_num);
if(item.type_flag > 0)

View File

@@ -18,10 +18,6 @@
#include "mathutil.hpp"
#include "fileio.hpp"
extern const std::multiset<eItemType> equippable;
extern const std::multiset<eItemType> num_hands_to_use;
extern std::map<const eItemType, const short> excluding_types;
extern short skill_bonus[21];
// A nice convenient bitset with just the low 30 bits set, for initializing spells
const uint32_t cPlayer::basic_spells = std::numeric_limits<uint32_t>::max() >> 2;
@@ -496,24 +492,18 @@ bool cPlayer::give_item(cItem item, int flags) {
print_result(announce.str());
}
if(equip_type != 0 && equippable.count(item.variety)) {
if(equip_type != 0 && (*item.variety).equip_count) {
if(!equip_item(free_space.slot, false) && equip_type != GIVE_EQUIP_SOFT) {
int exclude = 0;
if(num_hands_to_use.count(item.variety))
exclude = 100;
else exclude = excluding_types[item.variety];
eItemCat exclude = (*item.variety).exclusion;
int rem1 = items.size(), rem2 = items.size();
for(int i = 0; i < items.size(); i++) {
if(i == free_space.slot) continue;
if(!equip[i]) continue;
int check_exclude = 0;
if(num_hands_to_use.count(items[i].variety))
check_exclude = 100;
else check_exclude = excluding_types[items[i].variety];
eItemCat check_exclude = (*items[i].variety).exclusion;
if(exclude != check_exclude) continue;
if(exclude == 0 && item.variety != items[i].variety)
if(exclude == eItemCat::MISC && item.variety != items[i].variety)
continue;
if(exclude == 100) {
if(exclude == eItemCat::HANDS) {
if(rem1 == items.size()) {
if(item.variety == eItemType::ONE_HANDED || item.variety == eItemType::TWO_HANDED || rem2 < items.size())
rem1 = i;
@@ -528,18 +518,13 @@ bool cPlayer::give_item(cItem item, int flags) {
}
bool can_rem1 = rem1 < items.size() && (!items[rem1].cursed || equip_type == GIVE_EQUIP_FORCE);
bool can_rem2 = rem2 < items.size() && (!items[rem2].cursed || equip_type == GIVE_EQUIP_FORCE);
if(exclude == 100) {
if(item.variety == eItemType::TWO_HANDED) {
if(can_rem1) equip[rem1] = false;
if(can_rem2) equip[rem2] = false;
} else if(item.variety == eItemType::ONE_HANDED) {
if(exclude == eItemCat::HANDS) {
if((*item.variety).num_hands == 2 && can_rem1 && can_rem2) {
equip[rem1] = false;
equip[rem2] = false;
} else if((*item.variety).num_hands == 1) {
if(can_rem1) equip[rem1] = false;
else if(can_rem2) equip[rem2] = false;
} else { // It's a shield
if(can_rem2 && items[rem2].variety != item.variety)
equip[rem2] = false;
else if(can_rem1 && items[rem1].variety != item.variety)
equip[rem1] = false;
}
if((rem1 == weap_poisoned.slot && !equip[rem1]) || (rem2 == weap_poisoned.slot && !equip[rem2])) {
status[eStatus::POISONED_WEAPON] = 0;
@@ -559,7 +544,7 @@ bool cPlayer::give_item(cItem item, int flags) {
}
bool cPlayer::equip_item(int which_item, bool do_print) {
if(!equippable.count(items[which_item].variety)) {
if((*items[which_item].variety).equip_count == 0) {
if(do_print && print_result)
print_result("Equip: Can't equip this item.");
return false;
@@ -569,15 +554,15 @@ bool cPlayer::equip_item(int which_item, bool do_print) {
if(equip[i]) {
if(items[i].variety == items[which_item].variety)
num_this_type++;
hands_occupied += num_hands_to_use.count(items[i].variety);
hands_occupied += (*items[i].variety).num_hands;
}
short equip_item_type = excluding_types[items[which_item].variety];
eItemCat equip_item_type = (*items[which_item].variety).exclusion;
// Now if missile is already equipped, no more missiles
if(equip_item_type > 0) {
if(equip_item_type != eItemCat::MISC) {
for(int i = 0; i < items.size(); i++)
if(equip[i] && excluding_types[items[i].variety] == equip_item_type) {
if(equip[i] && (*items[i].variety).exclusion == equip_item_type) {
if(do_print && print_result) {
print_result("Equip: You have something of this type");
print_result(" equipped.");
@@ -587,11 +572,11 @@ bool cPlayer::equip_item(int which_item, bool do_print) {
}
size_t hands_free = 2 - hands_occupied;
if(hands_free < num_hands_to_use.count(items[which_item].variety)) {
if(hands_free < (*items[which_item].variety).num_hands) {
if(do_print && print_result)
print_result("Equip: Not enough free hands");
return false;
} else if(equippable.count(items[which_item].variety) <= num_this_type) {
} else if((*items[which_item].variety).equip_count <= num_this_type) {
if(do_print && print_result)
print_result("Equip: Can't equip another");
return false;