1361 lines
43 KiB
C++
1361 lines
43 KiB
C++
/*
|
|
* item.cpp
|
|
* BoE
|
|
*
|
|
* Created by Celtic Minstrel on 20/04/09.
|
|
*
|
|
*/
|
|
|
|
#include "item.hpp"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include "oldstructs.hpp"
|
|
#include "utility.hpp"
|
|
#include "fileio.hpp"
|
|
|
|
#include "damage.hpp"
|
|
#include "spell.hpp"
|
|
#include "race.hpp"
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
if(charges > 0) tmp *= charges;
|
|
if(tmp >= 15) return 1;
|
|
if(tmp >= 100) return 2;
|
|
if(tmp >= 900) return 3;
|
|
if(tmp >= 2400) return 4;
|
|
return 0;
|
|
}
|
|
|
|
short cItem::item_weight() const {
|
|
short n = charges, w = weight;
|
|
if(variety == eItemType::NO_ITEM)
|
|
return 0;
|
|
if(charges > 0){
|
|
if((variety == eItemType::ARROW) || (variety == eItemType::THROWN_MISSILE) || (variety == eItemType::POTION) || (variety == eItemType::BOLTS))
|
|
return n * w;
|
|
}
|
|
return w;
|
|
}
|
|
|
|
bool cItem::abil_harms() const {
|
|
if(magic_use_type == eItemUse::HARM_ONE || magic_use_type == eItemUse::HARM_ALL)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool cItem::abil_group() const {
|
|
if(magic_use_type == eItemUse::HELP_ALL || magic_use_type == eItemUse::HARM_ALL)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
cItem::cItem(){
|
|
variety = eItemType::NO_ITEM;
|
|
item_level = 0;
|
|
awkward = 0;
|
|
bonus = 0;
|
|
protection = 0;
|
|
charges = 0;
|
|
weap_type = eSkill::INVALID;
|
|
magic_use_type = eItemUse::HELP_ONE;
|
|
graphic_num = 0;
|
|
ability = eItemAbil::NONE;
|
|
abil_data[0] = 0;
|
|
abil_data[1] = 0;
|
|
missile = 0;
|
|
type_flag = 0;
|
|
is_special = 0;
|
|
value = 0;
|
|
weight = 0;
|
|
special_class = 0;
|
|
item_loc.x = 0;
|
|
item_loc.y = 0;
|
|
treas_class = 0;
|
|
ident = property = magic = contained = held = false;
|
|
cursed = concealed = enchanted = unsellable = false;
|
|
}
|
|
|
|
cItem::cItem(long preset) : cItem() {
|
|
switch(preset){
|
|
case 'nife':
|
|
variety = eItemType::ONE_HANDED;
|
|
item_level = 4;
|
|
bonus = 1;
|
|
weap_type = eSkill::EDGED_WEAPONS;
|
|
graphic_num = 55;
|
|
value = 2;
|
|
weight = 7;
|
|
full_name = "Bronze Knife";
|
|
name = "Knife";
|
|
ident = true;
|
|
break;
|
|
case 'buck':
|
|
variety = eItemType::SHIELD;
|
|
item_level = 1;
|
|
awkward = 1;
|
|
graphic_num = 75;
|
|
value = 2;
|
|
weight = 20;
|
|
full_name = "Crude Buckler";
|
|
name = "Buckler";
|
|
ident = true;
|
|
break;
|
|
case 'bow ':
|
|
variety = eItemType::BOW;
|
|
weap_type = eSkill::ARCHERY;
|
|
graphic_num = 10;
|
|
value = 15;
|
|
weight = 20;
|
|
full_name = "Cavewood Bow";
|
|
name = "Bow";
|
|
ident = true;
|
|
break;
|
|
case 'arrw':
|
|
variety = eItemType::ARROW;
|
|
item_level = 12;
|
|
charges = 12;
|
|
graphic_num = 57;
|
|
missile = 3;
|
|
value = 1;
|
|
weight = 1;
|
|
full_name = "Arrows";
|
|
name = "Arrows";
|
|
ident = true;
|
|
break;
|
|
case 'pole':
|
|
variety = eItemType::TWO_HANDED;
|
|
item_level = 9;
|
|
weap_type = eSkill::POLE_WEAPONS;
|
|
graphic_num = 4;
|
|
value = 10;
|
|
weight = 20;
|
|
full_name = "Stone Spear";
|
|
name = "Spear";
|
|
ident = true;
|
|
break;
|
|
case 'helm':
|
|
variety = eItemType::HELM;
|
|
item_level = 1;
|
|
weap_type = eSkill::INVALID;
|
|
graphic_num = 76;
|
|
value = 6;
|
|
weight = 15;
|
|
full_name = "Leather Helm";
|
|
name = "Helm";
|
|
ident = true;
|
|
break;
|
|
case 'rdsk':
|
|
variety = eItemType::THROWN_MISSILE;
|
|
item_level = 9;
|
|
bonus = 1;
|
|
charges = 8;
|
|
weap_type = eSkill::THROWN_MISSILES;
|
|
graphic_num = 59;
|
|
missile = 7;
|
|
value = 10;
|
|
weight = 1;
|
|
full_name = "Iron Razordisks";
|
|
name = "Razordisks";
|
|
ident = true;
|
|
break;
|
|
case 'food':
|
|
variety = eItemType::FOOD;
|
|
graphic_num = 72;
|
|
full_name = "Food";
|
|
name = "Food";
|
|
break;
|
|
case 'spel':
|
|
variety = eItemType::NON_USE_OBJECT;
|
|
graphic_num = 63;
|
|
break;
|
|
case 'alch':
|
|
variety = eItemType::POTION;
|
|
charges = 1;
|
|
graphic_num = 60;
|
|
weight = 8;
|
|
full_name = "Potion";
|
|
name = "Potion";
|
|
magic = true;
|
|
break;
|
|
case 'spec':
|
|
item_level = -1;
|
|
full_name = "Call Special Node";
|
|
case 'shop':
|
|
graphic_num = 105; // The blank graphic
|
|
break;
|
|
}
|
|
}
|
|
|
|
cItem::cItem(eAlchemy recipe) : cItem('alch') {
|
|
full_name = get_str("magic-names", int(recipe) + 200);
|
|
switch(recipe) {
|
|
case eAlchemy::NONE: break;
|
|
case eAlchemy::CURE_WEAK:
|
|
value = 40;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 2;
|
|
abil_data[1] = int(eStatus::POISON);
|
|
break;
|
|
case eAlchemy::HEAL_WEAK:
|
|
value = 60;
|
|
ability = eItemAbil::AFFECT_HEALTH;
|
|
abil_data[0] = 2;
|
|
break;
|
|
case eAlchemy::POISON_WEAK:
|
|
value = 15;
|
|
ability = eItemAbil::POISON_WEAPON;
|
|
abil_data[0] = 2;
|
|
break;
|
|
case eAlchemy::SPEED_WEAK:
|
|
value = 50;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 2;
|
|
abil_data[1] = int(eStatus::HASTE_SLOW);
|
|
break;
|
|
case eAlchemy::POISON_MED:
|
|
value = 50;
|
|
ability = eItemAbil::POISON_WEAPON;
|
|
abil_data[0] = 4;
|
|
break;
|
|
case eAlchemy::HEAL_MED:
|
|
value = 180;
|
|
ability = eItemAbil::AFFECT_HEALTH;
|
|
abil_data[0] = 5;
|
|
break;
|
|
case eAlchemy::CURE_STRONG:
|
|
value = 200;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 8;
|
|
abil_data[1] = int(eStatus::POISON);
|
|
break;
|
|
case eAlchemy::SPEED_MED:
|
|
value = 100;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 5;
|
|
abil_data[1] = int(eStatus::HASTE_SLOW);
|
|
break;
|
|
case eAlchemy::GRAYMOLD:
|
|
value = 150;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 4;
|
|
abil_data[1] = int(eStatus::DISEASE);
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case eAlchemy::POWER_WEAK:
|
|
value = 100;
|
|
ability = eItemAbil::AFFECT_SPELL_POINTS;
|
|
abil_data[0] = 2;
|
|
break;
|
|
case eAlchemy::CLARITY:
|
|
value = 200;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 8;
|
|
abil_data[1] = int(eStatus::DUMB);
|
|
break;
|
|
case eAlchemy::POISON_STRONG:
|
|
value = 150;
|
|
ability = eItemAbil::POISON_WEAPON;
|
|
abil_data[0] = 6;
|
|
break;
|
|
case eAlchemy::HEAL_STRONG:
|
|
value = 300;
|
|
ability = eItemAbil::AFFECT_HEALTH;
|
|
abil_data[0] = 8;
|
|
break;
|
|
case eAlchemy::POISON_KILL:
|
|
value = 400;
|
|
ability = eItemAbil::POISON_WEAPON;
|
|
abil_data[0] = 8;
|
|
break;
|
|
case eAlchemy::RESURRECT:
|
|
value = 100;
|
|
ability = eItemAbil::RESURRECTION_BALM;
|
|
break;
|
|
case eAlchemy::POWER_MED:
|
|
value = 300;
|
|
ability = eItemAbil::AFFECT_SPELL_POINTS;
|
|
abil_data[0] = 5;
|
|
break;
|
|
case eAlchemy::KNOWLEDGE:
|
|
value = 500;
|
|
ability = eItemAbil::AFFECT_SKILL_POINTS;
|
|
abil_data[0] = 2;
|
|
break;
|
|
case eAlchemy::STRENGTH:
|
|
value = 175;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 8;
|
|
abil_data[1] = int(eStatus::BLESS_CURSE);
|
|
break;
|
|
case eAlchemy::BLISS:
|
|
value = 250;
|
|
ability = eItemAbil::BLISS_DOOM;
|
|
abil_data[0] = 5;
|
|
break;
|
|
case eAlchemy::POWER_STRONG:
|
|
value = 500;
|
|
ability = eItemAbil::AFFECT_SKILL_POINTS;
|
|
abil_data[0] = 8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void cItem::enchant_weapon(eEnchant enchant_type,short new_val) {
|
|
if(magic || ability != eItemAbil::NONE)
|
|
return;
|
|
if(variety != eItemType::ONE_HANDED && variety != eItemType::TWO_HANDED)
|
|
return;
|
|
magic = true;
|
|
enchanted = true;
|
|
std::string store_name = full_name;
|
|
switch(enchant_type) {
|
|
case eEnchant::PLUS_ONE:
|
|
store_name += " (+1)";
|
|
bonus++;
|
|
value = new_val;
|
|
break;
|
|
case eEnchant::PLUS_TWO:
|
|
store_name += " (+2)";
|
|
bonus += 2;
|
|
value = new_val;
|
|
break;
|
|
case eEnchant::PLUS_THREE:
|
|
store_name += " (+3)";
|
|
bonus += 3;
|
|
value = new_val;
|
|
break;
|
|
case eEnchant::SHOOT_FLAME:
|
|
store_name += " (F)";
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = 5;
|
|
abil_data[1] = int(eSpell::FLAME);
|
|
charges = 8;
|
|
break;
|
|
case eEnchant::FLAMING:
|
|
store_name += " (F!)";
|
|
value = new_val;
|
|
ability = eItemAbil::DAMAGING_WEAPON;
|
|
abil_data[0] = 5;
|
|
abil_data[1] = int(eDamageType::FIRE);
|
|
break;
|
|
case eEnchant::PLUS_FIVE:
|
|
store_name += " (+5)";
|
|
value = new_val;
|
|
bonus += 5;
|
|
break;
|
|
case eEnchant::BLESSED:
|
|
store_name += " (B)";
|
|
bonus++;
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[0] = 5;
|
|
abil_data[1] = int(eStatus::BLESS_CURSE);
|
|
charges = 8;
|
|
break;
|
|
}
|
|
if(value > 15000)
|
|
value = 15000;
|
|
if(value < 0)
|
|
value = 15000;
|
|
full_name = store_name;
|
|
}
|
|
|
|
void cItem::import_legacy(legacy::item_record_type& old){
|
|
variety = (eItemType) old.variety;
|
|
item_level = old.item_level;
|
|
awkward = old.awkward;
|
|
bonus = old.bonus;
|
|
protection = old.protection;
|
|
charges = old.charges;
|
|
if(old.type >= 1 && old.type <= 3)
|
|
weap_type = eSkill(old.type + 2);
|
|
else weap_type = eSkill::INVALID;
|
|
if(variety == eItemType::BOW || variety == eItemType::CROSSBOW || variety == eItemType::MISSILE_NO_AMMO)
|
|
weap_type = eSkill::ARCHERY;
|
|
else if(variety == eItemType::THROWN_MISSILE)
|
|
weap_type = eSkill::THROWN_MISSILES;
|
|
magic_use_type = eItemUse(old.magic_use_type);
|
|
graphic_num = old.graphic_num;
|
|
if(graphic_num >= 150) // custom item graphic
|
|
graphic_num += 850;
|
|
else if(graphic_num == 59) // duplicate mushroom graphic
|
|
graphic_num = 74;
|
|
else if(graphic_num == 17) // gauntlets moved to tinyobj
|
|
graphic_num = 133;
|
|
else if(graphic_num >= 45) // small graphics were moved up to make a bit more room for new large graphics
|
|
graphic_num += 10;
|
|
abil_data[0] = old.ability_strength;
|
|
switch(old.ability) {
|
|
// Weapon abilities
|
|
case 0:
|
|
ability = eItemAbil::NONE;
|
|
break;
|
|
case 1: // Flaming weapon
|
|
ability = eItemAbil::DAMAGING_WEAPON;
|
|
abil_data[1] = int(eDamageType::UNBLOCKABLE);
|
|
break;
|
|
case 2: // Demon slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::DEMON);
|
|
break;
|
|
case 3: // Undead slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::UNDEAD);
|
|
break;
|
|
case 4: // Lizard slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::REPTILE);
|
|
break;
|
|
case 5: // Giant slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::GIANT);
|
|
break;
|
|
case 6: // Mage slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::MAGE);
|
|
break;
|
|
case 7: // Priest slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::PRIEST);
|
|
break;
|
|
case 8: // Bug slayer
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[1] = int(eRace::BUG);
|
|
break;
|
|
case 9: // Acidic weapon
|
|
ability = eItemAbil::STATUS_WEAPON;
|
|
abil_data[1] = int(eStatus::ACID);
|
|
break;
|
|
case 10:
|
|
ability = eItemAbil::SOULSUCKER;
|
|
break;
|
|
case 11:
|
|
ability = eItemAbil::DRAIN_MISSILES;
|
|
break;
|
|
case 12:
|
|
ability = eItemAbil::WEAK_WEAPON;
|
|
break;
|
|
case 13:
|
|
ability = eItemAbil::CAUSES_FEAR;
|
|
break;
|
|
case 14: // Poisoned weapon
|
|
ability = eItemAbil::STATUS_WEAPON;
|
|
abil_data[1] = int(eStatus::POISON);
|
|
break;
|
|
// General abilities
|
|
case 30: // Protection
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::WEAPON);
|
|
break;
|
|
case 31:
|
|
ability = eItemAbil::FULL_PROTECTION;
|
|
break;
|
|
case 32: // Fire protection
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::FIRE);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 33: // Cold protection
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::COLD);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 34: // Poison protection
|
|
ability = eItemAbil::STATUS_PROTECTION;
|
|
abil_data[1] = int(eStatus::POISON);
|
|
break;
|
|
case 35: // Magic protection
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::MAGIC);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 36: // Acid protection
|
|
ability = eItemAbil::STATUS_PROTECTION;
|
|
abil_data[1] = int(eStatus::ACID);
|
|
break;
|
|
case 37:
|
|
ability = eItemAbil::SKILL;
|
|
abil_data[1] = abil_data[0]; // archive original ability strength (SKILL doesn't use abil_data[1] for anything)
|
|
abil_data[0] = item_level; // Put level into ability strength to preserve legacy behaviour
|
|
break;
|
|
case 38: // Strength
|
|
ability = eItemAbil::BOOST_STAT;
|
|
desc = "Original ability strength was " + std::to_string(abil_data[0]);
|
|
abil_data[0] = 1;
|
|
abil_data[1] = int(eSkill::STRENGTH);
|
|
break;
|
|
case 39: // Dexterity
|
|
ability = eItemAbil::BOOST_STAT;
|
|
desc = "Original ability strength was " + std::to_string(abil_data[0]);
|
|
abil_data[0] = 1;
|
|
abil_data[1] = int(eSkill::DEXTERITY);
|
|
break;
|
|
case 40: // Intelligence
|
|
ability = eItemAbil::BOOST_STAT;
|
|
desc = "Original ability strength was " + std::to_string(abil_data[0]);
|
|
abil_data[0] = 1;
|
|
abil_data[1] = int(eSkill::INTELLIGENCE);
|
|
break;
|
|
case 41:
|
|
ability = eItemAbil::ACCURACY;
|
|
break;
|
|
case 42:
|
|
ability = eItemAbil::THIEVING;
|
|
break;
|
|
case 43:
|
|
ability = eItemAbil::GIANT_STRENGTH;
|
|
abil_data[1] = abil_data[0]; // archive original ability strength (GIANT_STRENGTH doesn't use abil_data[1] for anything)
|
|
abil_data[0] = item_level; // Put level into ability strength to preserve legacy behaviour
|
|
break;
|
|
case 44:
|
|
ability = eItemAbil::LIGHTER_OBJECT;
|
|
break;
|
|
case 45:
|
|
ability = eItemAbil::HEAVIER_OBJECT;
|
|
break;
|
|
case 46:
|
|
ability = eItemAbil::OCCASIONAL_STATUS;
|
|
abil_data[1] = int(eStatus::BLESS_CURSE);
|
|
magic_use_type = eItemUse::HELP_ONE;
|
|
break;
|
|
case 47:
|
|
ability = eItemAbil::OCCASIONAL_STATUS;
|
|
abil_data[1] = int(eStatus::HASTE_SLOW);
|
|
magic_use_type = eItemUse::HELP_ONE;
|
|
break;
|
|
case 48:
|
|
ability = eItemAbil::LIFE_SAVING;
|
|
break;
|
|
case 49:
|
|
ability = eItemAbil::PROTECT_FROM_PETRIFY;
|
|
break;
|
|
case 50:
|
|
ability = eItemAbil::REGENERATE;
|
|
break;
|
|
case 51:
|
|
ability = eItemAbil::POISON_AUGMENT;
|
|
break;
|
|
case 52:
|
|
ability = eItemAbil::OCCASIONAL_STATUS;
|
|
abil_data[1] = int(eStatus::DISEASE);
|
|
magic_use_type = eItemUse::HARM_ALL;
|
|
break;
|
|
case 53:
|
|
ability = eItemAbil::WILL;
|
|
break;
|
|
case 54:
|
|
ability = eItemAbil::FREE_ACTION;
|
|
break;
|
|
case 55:
|
|
ability = eItemAbil::SPEED;
|
|
abil_data[1] = abil_data[0];
|
|
abil_data[0] = abil_data[0] / 7 + 1;
|
|
break;
|
|
case 56:
|
|
ability = eItemAbil::SLOW_WEARER;
|
|
abil_data[1] = abil_data[0];
|
|
abil_data[0] = abil_data[0] / 5;
|
|
break;
|
|
case 57: // Protect from undead
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::UNDEAD);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 58: // Protect from demons
|
|
ability = eItemAbil::DAMAGE_PROTECTION;
|
|
abil_data[1] = int(eDamageType::DEMON);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 59: // Protect from humanoids
|
|
ability = eItemAbil::PROTECT_FROM_SPECIES;
|
|
abil_data[1] = int(eRace::HUMANOID);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 60: // Protect from reptiles
|
|
ability = eItemAbil::PROTECT_FROM_SPECIES;
|
|
abil_data[1] = int(eRace::REPTILE);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 61: // Protect from giants
|
|
ability = eItemAbil::PROTECT_FROM_SPECIES;
|
|
abil_data[1] = int(eRace::GIANT);
|
|
if(abil_data[0] >= 7) abil_data[0] /= 2;
|
|
break;
|
|
case 62: // Protect from disease
|
|
ability = eItemAbil::STATUS_PROTECTION;
|
|
abil_data[1] = int(eStatus::DISEASE);
|
|
break;
|
|
// Usable abilities
|
|
case 70:
|
|
ability = eItemAbil::POISON_WEAPON;
|
|
break;
|
|
case 71:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::BLESS_CURSE);
|
|
break;
|
|
case 72:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::POISON);
|
|
break;
|
|
case 73:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::HASTE_SLOW);
|
|
break;
|
|
case 74:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::INVULNERABLE);
|
|
break;
|
|
case 75:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::MAGIC_RESISTANCE);
|
|
break;
|
|
case 76:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::WEBS);
|
|
break;
|
|
case 77:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::DISEASE);
|
|
break;
|
|
case 78:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::INVISIBLE);
|
|
break;
|
|
case 79:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::DUMB);
|
|
break;
|
|
case 80:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::MARTYRS_SHIELD);
|
|
break;
|
|
case 81:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::ASLEEP);
|
|
break;
|
|
case 82:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::PARALYZED);
|
|
break;
|
|
case 83:
|
|
ability = eItemAbil::AFFECT_STATUS;
|
|
abil_data[1] = int(eStatus::ACID);
|
|
break;
|
|
case 84:
|
|
ability = eItemAbil::BLISS_DOOM;
|
|
if(magic_use_type == eItemUse::HARM_ONE)
|
|
magic_use_type = eItemUse::HELP_ONE;
|
|
else if(magic_use_type == eItemUse::HARM_ALL)
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 85:
|
|
ability = eItemAbil::AFFECT_EXPERIENCE;
|
|
break;
|
|
case 86:
|
|
ability = eItemAbil::AFFECT_SKILL_POINTS;
|
|
break;
|
|
case 87:
|
|
ability = eItemAbil::AFFECT_HEALTH;
|
|
break;
|
|
case 88:
|
|
ability = eItemAbil::AFFECT_SPELL_POINTS;
|
|
break;
|
|
case 89:
|
|
ability = eItemAbil::BLISS_DOOM;
|
|
if(magic_use_type == eItemUse::HELP_ONE)
|
|
magic_use_type = eItemUse::HARM_ONE;
|
|
else if(magic_use_type == eItemUse::HELP_ALL)
|
|
magic_use_type = eItemUse::HARM_ALL;
|
|
break;
|
|
case 90:
|
|
ability = eItemAbil::LIGHT;
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 91:
|
|
ability = eItemAbil::AFFECT_PARTY_STATUS;
|
|
abil_data[1] = int(ePartyStatus::STEALTH);
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 92:
|
|
ability = eItemAbil::AFFECT_PARTY_STATUS;
|
|
abil_data[1] = int(ePartyStatus::FIREWALK);
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 93:
|
|
ability = eItemAbil::AFFECT_PARTY_STATUS;
|
|
abil_data[1] = int(ePartyStatus::FLIGHT);
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 94:
|
|
ability = eItemAbil::HEALTH_POISON;
|
|
if(magic_use_type == eItemUse::HARM_ONE)
|
|
magic_use_type = eItemUse::HELP_ONE;
|
|
else if(magic_use_type == eItemUse::HARM_ALL)
|
|
magic_use_type = eItemUse::HELP_ALL;
|
|
break;
|
|
case 95:
|
|
ability = eItemAbil::CALL_SPECIAL;
|
|
break;
|
|
// Spells
|
|
case 110:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::FLAME);
|
|
break;
|
|
case 111:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::FIREBALL);
|
|
break;
|
|
case 112:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::FIRESTORM);
|
|
break;
|
|
case 113:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::KILL);
|
|
break;
|
|
case 114:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::ICE_BOLT);
|
|
break;
|
|
case 115:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::SLOW);
|
|
break;
|
|
case 116:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::SHOCKWAVE);
|
|
break;
|
|
case 117:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::DISPEL_UNDEAD);
|
|
break;
|
|
case 118:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::RAVAGE_SPIRIT);
|
|
break;
|
|
case 119:
|
|
ability = eItemAbil::SUMMONING;
|
|
abil_data[1] = abil_data[0];
|
|
abil_data[0] = 50;
|
|
break;
|
|
case 120:
|
|
ability = eItemAbil::MASS_SUMMONING;
|
|
abil_data[1] = abil_data[0];
|
|
abil_data[0] = 6;
|
|
break;
|
|
case 121:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::ACID_SPRAY);
|
|
break;
|
|
case 122:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::FOUL_VAPOR);
|
|
break;
|
|
case 123:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::CLOUD_SLEEP);
|
|
break;
|
|
case 124:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::POISON);
|
|
break;
|
|
case 125:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::SHOCKSTORM);
|
|
break;
|
|
case 126:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::PARALYZE_BEAM);
|
|
break;
|
|
case 127:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::GOO_BOMB);
|
|
break;
|
|
case 128:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::STRENGTHEN_TARGET);
|
|
break;
|
|
case 129:
|
|
ability = eItemAbil::QUICKFIRE;
|
|
break;
|
|
case 130:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::CHARM_MASS);
|
|
break;
|
|
case 131:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::MAGIC_MAP);
|
|
break;
|
|
case 132:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::DISPEL_BARRIER);
|
|
break;
|
|
case 133:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::WALL_ICE_BALL);
|
|
break;
|
|
case 134:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[1] = int(eSpell::CHARM_FOE);
|
|
break;
|
|
case 135:
|
|
ability = eItemAbil::CAST_SPELL;
|
|
abil_data[0] = abil_data[0] * 2 + 1;
|
|
abil_data[1] = int(eSpell::ANTIMAGIC);
|
|
break;
|
|
// Reagents
|
|
case 150:
|
|
ability = eItemAbil::HOLLY;
|
|
break;
|
|
case 151:
|
|
ability = eItemAbil::COMFREY;
|
|
break;
|
|
case 152:
|
|
ability = eItemAbil::NETTLE;
|
|
break;
|
|
case 153:
|
|
ability = eItemAbil::WORMGRASS;
|
|
break;
|
|
case 154:
|
|
ability = eItemAbil::ASPTONGUE;
|
|
break;
|
|
case 155:
|
|
ability = eItemAbil::EMBERF;
|
|
break;
|
|
case 156:
|
|
ability = eItemAbil::GRAYMOLD;
|
|
break;
|
|
case 157:
|
|
ability = eItemAbil::MANDRAKE;
|
|
break;
|
|
case 158:
|
|
ability = eItemAbil::SAPPHIRE;
|
|
break;
|
|
case 159:
|
|
ability = eItemAbil::SMOKY_CRYSTAL;
|
|
break;
|
|
case 160:
|
|
ability = eItemAbil::RESURRECTION_BALM;
|
|
break;
|
|
case 161:
|
|
ability = eItemAbil::LOCKPICKS;
|
|
break;
|
|
// Missile abilities
|
|
case 170:
|
|
ability = eItemAbil::RETURNING_MISSILE;
|
|
break;
|
|
case 171:
|
|
ability = eItemAbil::DAMAGING_WEAPON;
|
|
abil_data[1] = int(eDamageType::FIRE);
|
|
break;
|
|
case 172:
|
|
ability = eItemAbil::EXPLODING_WEAPON;
|
|
abil_data[1] = int(eDamageType::FIRE);
|
|
break;
|
|
case 173:
|
|
ability = eItemAbil::STATUS_WEAPON;
|
|
abil_data[0] *= 2;
|
|
abil_data[1] = int(eStatus::ACID);
|
|
break;
|
|
case 174:
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[0] += 3;
|
|
abil_data[1] = int(eRace::UNDEAD);
|
|
break;
|
|
case 175:
|
|
ability = eItemAbil::SLAYER_WEAPON;
|
|
abil_data[0] += 3;
|
|
abil_data[1] = int(eRace::DEMON);
|
|
break;
|
|
case 176:
|
|
ability = eItemAbil::HEALING_WEAPON;
|
|
break;
|
|
}
|
|
type_flag = old.type_flag;
|
|
is_special = old.is_special;
|
|
value = old.value;
|
|
weight = old.weight;
|
|
special_class = old.special_class;
|
|
item_loc.x = old.item_loc.x;
|
|
item_loc.y = old.item_loc.y;
|
|
full_name = std::string(old.full_name);
|
|
name = old.name;
|
|
treas_class = old.treas_class;
|
|
ident = old.item_properties & 1;
|
|
property = old.item_properties & 2;
|
|
magic = old.item_properties & 4;
|
|
contained = old.item_properties & 8;
|
|
cursed = old.item_properties & 16;
|
|
concealed = old.item_properties & 32;
|
|
enchanted = held = false;
|
|
unsellable = old.item_properties & 16;
|
|
// Set missile, if needed
|
|
if(variety == eItemType::ARROW || variety == eItemType::BOLTS) {
|
|
missile = magic ? 4 : 3;
|
|
} else if(variety == eItemType::MISSILE_NO_AMMO) {
|
|
// Just assume it's a sling and use the rock missile.
|
|
missile = 12;
|
|
} else if(variety == eItemType::THROWN_MISSILE) {
|
|
// This is tricky... basically, all we can really do is guess.
|
|
// And the only way to guess is by examining the item's name
|
|
// We'll use the unidentified name since it's more likely to contain the appropriate generic words
|
|
auto npos = std::string::npos;
|
|
// Okay, that failed. Try examining the item's name.
|
|
if(name.find("Knife") != npos) missile = 10;
|
|
// Unidentified name limit was quite short, so the S might've been cut off
|
|
else if(name.find("Knive") != npos) missile = 10;
|
|
else if(name.find("Spear") != npos) missile = 5;
|
|
else if(name.find("Javelin") != npos) missile = 5;
|
|
else if(name.find("Razordisk") != npos) missile = 7;
|
|
else if(name.find("Star") != npos) missile = 7;
|
|
else if(name.find("Dart") != npos) missile = 1;
|
|
else if(name.find("Rock") != npos) missile = 12;
|
|
// Okay, give up. Fall back to darts since we have no idea what's correct.
|
|
else missile = 1;
|
|
}
|
|
}
|
|
|
|
std::string cItem::getAbilName() const {
|
|
bool harmful = abil_harms();
|
|
bool party = abil_group();
|
|
std::ostringstream sout;
|
|
switch(ability) {
|
|
case eItemAbil::UNUSED: break; // Invalid
|
|
case eItemAbil::NONE: sout << "No ability"; break;
|
|
case eItemAbil::HEALING_WEAPON: sout << "Heals target"; break;
|
|
case eItemAbil::RETURNING_MISSILE: sout << "Returning missile"; break;
|
|
case eItemAbil::DISTANCE_MISSILE: sout << "Farflight missile"; break;
|
|
case eItemAbil::SEEKING_MISSILE: sout << "Seeking missile"; break;
|
|
case eItemAbil::ANTIMAGIC_WEAPON: sout << "Manasucker"; break;
|
|
case eItemAbil::SOULSUCKER: sout << "Soulsucker"; break;
|
|
case eItemAbil::DRAIN_MISSILES: sout << "Drain Missiles"; break;
|
|
case eItemAbil::WEAK_WEAPON: sout << "Weak Weapon"; break;
|
|
case eItemAbil::HP_DAMAGE: sout << "Damage Linked to Health"; break;
|
|
case eItemAbil::HP_DAMAGE_REVERSE: sout << "Berserker's Weapon"; break;
|
|
case eItemAbil::SP_DAMAGE: sout << "Damage Linked to Spell Points"; break;
|
|
case eItemAbil::SP_DAMAGE_REVERSE: sout << "Wildmage's Weapon"; break;
|
|
case eItemAbil::CAUSES_FEAR: sout << "Causes Fear"; break;
|
|
case eItemAbil::WEAPON_CALL_SPECIAL: sout << "Unusual Attack Effect"; break;
|
|
case eItemAbil::FULL_PROTECTION: sout << "Full Protection"; break;
|
|
case eItemAbil::EVASION: sout << "Evasion"; break;
|
|
case eItemAbil::MARTYRS_SHIELD: sout << "Martyr's Shield"; break;
|
|
case eItemAbil::ENCUMBERING: sout << "Awkward Weapon"; break;
|
|
case eItemAbil::SKILL: sout << "Skill"; break;
|
|
case eItemAbil::BOOST_WAR: sout << "Warrior's Mantle"; break;
|
|
case eItemAbil::BOOST_MAGIC: sout << "Mage's Mantle"; break;
|
|
case eItemAbil::ACCURACY: sout << "Accuracy"; break;
|
|
case eItemAbil::THIEVING: sout << "Thieving"; break;
|
|
case eItemAbil::MAGERY: sout << "Magery"; break;
|
|
case eItemAbil::GIANT_STRENGTH: sout << "Giant Strength"; break;
|
|
case eItemAbil::LIGHTER_OBJECT: sout << "Lighter Object"; break;
|
|
case eItemAbil::HEAVIER_OBJECT: sout << "Heavier Object"; break;
|
|
case eItemAbil::HIT_CALL_SPECIAL: sout << "Unusual Defense Effect"; break;
|
|
case eItemAbil::DROP_CALL_SPECIAL: sout << "Unusual Effect When Dropped"; break;
|
|
case eItemAbil::LIFE_SAVING: sout << "Life Saving"; break;
|
|
case eItemAbil::PROTECT_FROM_PETRIFY: sout << "Protect from Petrify"; break;
|
|
case eItemAbil::REGENERATE: sout << "Regenerate"; break;
|
|
case eItemAbil::POISON_AUGMENT: sout << "Poison Augment"; break;
|
|
case eItemAbil::RADIANT: sout << "Radiance"; break;
|
|
case eItemAbil::WILL: sout << "Will"; break;
|
|
case eItemAbil::FREE_ACTION: sout << "Free Action"; break;
|
|
case eItemAbil::SPEED: sout << "Speed"; break;
|
|
case eItemAbil::SLOW_WEARER: sout << "Slow Wearer"; break;
|
|
case eItemAbil::LOCKPICKS: sout << "Lockpicks"; break;
|
|
case eItemAbil::POISON_WEAPON: sout << "Poison Weapon"; break;
|
|
case eItemAbil::CALL_SPECIAL: sout << "Unusual Ability"; break;
|
|
case eItemAbil::QUICKFIRE: sout << "Quickfire"; break;
|
|
case eItemAbil::HOLLY: sout << "Holly/Toadstool"; break;
|
|
case eItemAbil::COMFREY: sout << "Comfrey Root"; break;
|
|
case eItemAbil::NETTLE: sout << "Glowing Nettle"; break;
|
|
case eItemAbil::WORMGRASS: sout << "Crypt Shroom/Wormgrass"; break;
|
|
case eItemAbil::ASPTONGUE: sout << "Asptongue Mold"; break;
|
|
case eItemAbil::EMBERF: sout << "Ember Flower"; break;
|
|
case eItemAbil::GRAYMOLD: sout << "Graymold"; break;
|
|
case eItemAbil::MANDRAKE: sout << "Mandrake Root"; break;
|
|
case eItemAbil::SAPPHIRE: sout << "Sapphire"; break;
|
|
case eItemAbil::SMOKY_CRYSTAL: sout << "Smoky Crystal"; break;
|
|
case eItemAbil::RESURRECTION_BALM: sout << "Resurrection Balm"; break;
|
|
case eItemAbil::DAMAGING_WEAPON:
|
|
switch(eDamageType(abil_data[1])) {
|
|
case eDamageType::FIRE: sout << "Flaming"; break;
|
|
case eDamageType::MAGIC: sout << "Shocking"; break;
|
|
case eDamageType::COLD: sout << "Frosty"; break;
|
|
case eDamageType::POISON: sout << "Slimy"; break;
|
|
case eDamageType::WEAPON: sout << "Enhanced"; break;
|
|
case eDamageType::UNDEAD: sout << "Necrotic"; break;
|
|
case eDamageType::DEMON: sout << "Unholy"; break;
|
|
case eDamageType::SPECIAL:
|
|
case eDamageType::UNBLOCKABLE: sout << "Dark"; break;
|
|
case eDamageType::MARKED: break; // Invalid
|
|
}
|
|
sout << " Weapon";
|
|
break;
|
|
case eItemAbil::SLAYER_WEAPON:
|
|
switch(eRace(abil_data[1])) {
|
|
case eRace::UNKNOWN: break; // Invalid
|
|
case eRace::DEMON: sout << "Demon"; break;
|
|
case eRace::UNDEAD: sout << "Undead"; break;
|
|
case eRace::REPTILE: sout << "Lizard"; break;
|
|
case eRace::GIANT: sout << "Giant"; break;
|
|
case eRace::MAGE: sout << "Mage"; break;
|
|
case eRace::PRIEST: sout << "Priest"; break;
|
|
case eRace::BUG: sout << "Bug"; break;
|
|
case eRace::HUMAN: sout << "Human"; break;
|
|
case eRace::NEPHIL: sout << "Nephil"; break;
|
|
case eRace::SLITH: sout << "Slith"; break;
|
|
case eRace::VAHNATAI: sout << "Vahnatai"; break;
|
|
case eRace::HUMANOID: sout << "Humanoid"; break;
|
|
case eRace::BEAST: sout << "Beast"; break;
|
|
case eRace::IMPORTANT: sout << "VIP"; break; // TODO: This one should probably not exist
|
|
case eRace::SLIME: sout << "Slime"; break;
|
|
case eRace::STONE: sout << "Golem"; break;
|
|
case eRace::DRAGON: sout << "Dragon"; break;
|
|
case eRace::MAGICAL: sout << "Magical Beast"; break;
|
|
case eRace::PLANT: sout << "Plant"; break;
|
|
case eRace::BIRD: sout << "Bird"; break;
|
|
case eRace::SKELETAL: sout << "Skeleton"; break;
|
|
case eRace::GOBLIN: sout << "Goblin"; break;
|
|
}
|
|
sout << " Slayer";
|
|
break;
|
|
case eItemAbil::EXPLODING_WEAPON:
|
|
sout << "Explodes ";
|
|
switch(eDamageType(abil_data[1])) {
|
|
case eDamageType::FIRE: sout << "in flames"; break;
|
|
case eDamageType::COLD: sout << "into frost"; break;
|
|
case eDamageType::MAGIC: sout << "in sparks"; break;
|
|
case eDamageType::POISON: sout << "into slime"; break;
|
|
case eDamageType::WEAPON: sout << "in shrapnel"; break;
|
|
case eDamageType::SPECIAL:
|
|
case eDamageType::UNBLOCKABLE: sout << "in darkness"; break;
|
|
case eDamageType::UNDEAD: sout.str("Implodes"); break;
|
|
case eDamageType::DEMON: sout << "into corruption"; break;
|
|
case eDamageType::MARKED: break; // Invalid
|
|
}
|
|
break;
|
|
case eItemAbil::STATUS_WEAPON:
|
|
switch(eStatus(abil_data[1])) {
|
|
case eStatus::MAIN: break; // Invalid
|
|
case eStatus::POISONED_WEAPON: sout << "Poison-draining"; break;
|
|
case eStatus::INVULNERABLE: sout << "Piercing"; break;
|
|
case eStatus::MAGIC_RESISTANCE: sout << "Overwhelming"; break;
|
|
case eStatus::INVISIBLE: sout << "Anti-sanctuary"; break;
|
|
case eStatus::ACID: sout << "Acidic"; break;
|
|
case eStatus::POISON: sout << "Poisoned"; break;
|
|
case eStatus::BLESS_CURSE: sout << "Cursing"; break;
|
|
case eStatus::HASTE_SLOW: sout << "Slowing"; break;
|
|
case eStatus::WEBS: sout << "Webbing"; break;
|
|
case eStatus::DISEASE: sout << "Infectious"; break;
|
|
case eStatus::DUMB: sout << "Dumbfounding"; break;
|
|
case eStatus::MARTYRS_SHIELD: sout << "Martyr Draining"; break;
|
|
case eStatus::ASLEEP: sout << "Soporific"; break;
|
|
case eStatus::PARALYZED: sout << "Paralytic"; break;
|
|
case eStatus::FORCECAGE: sout << "Entrapping"; break;
|
|
case eStatus::CHARM: sout << "Charming"; break;
|
|
}
|
|
sout << " Weapon";
|
|
break;
|
|
case eItemAbil::DAMAGE_PROTECTION:
|
|
switch(eDamageType(abil_data[1])) {
|
|
case eDamageType::WEAPON: break;
|
|
case eDamageType::FIRE: sout << "Fire"; break;
|
|
case eDamageType::COLD: sout << "Cold"; break;
|
|
case eDamageType::MAGIC: sout << "Magic"; break;
|
|
case eDamageType::DEMON: sout << "Demon"; break;
|
|
case eDamageType::UNDEAD: sout << "Undead"; break;
|
|
case eDamageType::POISON: sout << "Poison"; break;
|
|
case eDamageType::SPECIAL:
|
|
case eDamageType::UNBLOCKABLE: sout << "Darkness"; break;
|
|
case eDamageType::MARKED: break; // Invalid
|
|
}
|
|
sout << " Protection";
|
|
break;
|
|
case eItemAbil::STATUS_PROTECTION:
|
|
sout << "Protect From ";
|
|
switch(eStatus(abil_data[1])) {
|
|
case eStatus::MAIN: break; // Invalid
|
|
case eStatus::POISONED_WEAPON:
|
|
case eStatus::INVULNERABLE:
|
|
case eStatus::MARTYRS_SHIELD:
|
|
case eStatus::CHARM:
|
|
case eStatus::INVISIBLE:
|
|
break; // These have no negative aspect, so protection from them isn't implemented
|
|
case eStatus::POISON: sout << "Poison"; break;
|
|
case eStatus::ACID: sout << "Acid"; break;
|
|
case eStatus::DISEASE: sout << "Disease"; break;
|
|
case eStatus::BLESS_CURSE: sout << "Curses"; break;
|
|
case eStatus::HASTE_SLOW: sout << "Slowing"; break;
|
|
case eStatus::MAGIC_RESISTANCE: sout << "Magic Vulnerability"; break;
|
|
case eStatus::WEBS: sout << "Webbing"; break;
|
|
case eStatus::DUMB: sout << "Dumbfounding"; break;
|
|
case eStatus::ASLEEP: sout << "Sleep"; break;
|
|
case eStatus::PARALYZED: sout << "Paralysis"; break;
|
|
case eStatus::FORCECAGE: sout << "Forcecage"; break;
|
|
}
|
|
break;
|
|
case eItemAbil::BOOST_STAT:
|
|
sout << get_str("skills", abil_data[1] * 2 + 1);
|
|
break;
|
|
case eItemAbil::OCCASIONAL_STATUS:
|
|
sout << "Occasional ";
|
|
switch(eStatus(abil_data[1])) {
|
|
case eStatus::MAIN: break; // Invalid
|
|
case eStatus::CHARM: // Doesn't affect PCs
|
|
case eStatus::FORCECAGE: sout << (harmful ? "Entrapment" : "Release"); break;
|
|
case eStatus::DISEASE: sout << (harmful ? "Disease" : "Cure Disease"); break;
|
|
case eStatus::HASTE_SLOW: sout << (harmful ? "Slow" : "Haste"); break;
|
|
case eStatus::BLESS_CURSE: sout << (harmful ? "Curse" : "Bless"); break;
|
|
case eStatus::POISON: sout << (harmful ? "Poison" : "Cure"); break;
|
|
case eStatus::WEBS: sout << (harmful ? "Webbing" : "Cleansing"); break;
|
|
case eStatus::DUMB: sout << (harmful ? "Dumbfounding" : "Enlightening"); break;
|
|
case eStatus::MARTYRS_SHIELD: sout << (harmful ? "Lose" : "Gain") << " Martyr's Shield"; break;
|
|
case eStatus::INVULNERABLE: sout << (harmful ? "Lose" : "Gain") << " Invulnerability"; break;
|
|
case eStatus::MAGIC_RESISTANCE: sout << "Magic " << (harmful ? "Vulnerability" : "Resistance"); break;
|
|
case eStatus::INVISIBLE: sout << (harmful ? "Lose" : "Gain") << " Sanctuary"; break;
|
|
case eStatus::POISONED_WEAPON: sout << (harmful ? "Lose" : "Gain") << " Weapon Poison"; break;
|
|
case eStatus::ASLEEP: sout << (harmful ? "Sleep" : "Hyperactivity"); break;
|
|
case eStatus::PARALYZED: sout << (harmful ? "Gain" : "Lose") << " Paralysis"; break;
|
|
case eStatus::ACID: sout << (harmful ? "Gain" : "Neutralize") << " Acid"; break;
|
|
}
|
|
sout << (party ? " Party" : " Wearer");
|
|
break;
|
|
case eItemAbil::PROTECT_FROM_SPECIES:
|
|
sout << "Protection from ";
|
|
switch(eRace(abil_data[1])) {
|
|
case eRace::UNKNOWN: break; // Invalid
|
|
case eRace::UNDEAD: sout << "Undead"; break;
|
|
case eRace::DEMON: sout << "Demons"; break;
|
|
case eRace::HUMANOID: sout << "Humanoids"; break;
|
|
case eRace::REPTILE: sout << "Reptiles"; break;
|
|
case eRace::GIANT: sout << "Giants"; break;
|
|
case eRace::HUMAN: sout << "Humans"; break;
|
|
case eRace::NEPHIL: sout << "Nephilim"; break;
|
|
case eRace::SLITH: sout << "Sliths"; break;
|
|
case eRace::VAHNATAI: sout << "Vahnatai"; break;
|
|
case eRace::BEAST: sout << "Beasts"; break;
|
|
case eRace::IMPORTANT: sout << "VIPs"; break;
|
|
case eRace::MAGE: sout << "Mages"; break;
|
|
case eRace::PRIEST: sout << "Priests"; break;
|
|
case eRace::SLIME: sout << "Slimes"; break;
|
|
case eRace::STONE: sout << "Golems"; break;
|
|
case eRace::BUG: sout << "Bugs"; break;
|
|
case eRace::DRAGON: sout << "Dragons"; break;
|
|
case eRace::MAGICAL: sout << "Magical Beasts"; break;
|
|
case eRace::PLANT: sout << "Plants"; break;
|
|
case eRace::BIRD: sout << "Birds"; break;
|
|
case eRace::SKELETAL: sout << "Skeleton"; break;
|
|
case eRace::GOBLIN: sout << "Goblin"; break;
|
|
}
|
|
break;
|
|
case eItemAbil::AFFECT_STATUS:
|
|
switch(eStatus(abil_data[1])) {
|
|
case eStatus::MAIN: break; // Invalid;
|
|
case eStatus::FORCECAGE: sout << (harmful ? "Entrapping" : "Cage Break"); break;
|
|
case eStatus::CHARM: break; // TODO: Not implemented
|
|
case eStatus::POISONED_WEAPON: sout << (harmful ? "Increase" : "Decrease") << " Weapon Poison"; break;
|
|
case eStatus::BLESS_CURSE: sout << (harmful ? "Curse" : "Bless"); break;
|
|
case eStatus::POISON: sout << (harmful ? "Cause" : "Cure") << " Poison"; break;
|
|
case eStatus::HASTE_SLOW: sout << (harmful ? "Slow" : "Haste"); break;
|
|
case eStatus::INVULNERABLE: sout << (harmful ? "Lose" : "Add") << " Invulnerability"; break;
|
|
case eStatus::MAGIC_RESISTANCE: sout << (harmful ? "Lose" : "Add") << " Magic Resistance"; break;
|
|
case eStatus::WEBS: sout << (harmful ? "Lose" : "Add") << "Webs"; break;
|
|
case eStatus::DISEASE: sout << (harmful ? "Cause" : "Cure") << " Disease"; break;
|
|
case eStatus::INVISIBLE: sout << (harmful ? "Lose" : "Add") << " Sanctuary"; break;
|
|
case eStatus::DUMB: sout << (harmful ? "Add" : "Lose") << " Dumbfounding"; break;
|
|
case eStatus::MARTYRS_SHIELD: sout << (harmful ? "Lose" : "Add") << " Martyr's Shield"; break;
|
|
case eStatus::ASLEEP: sout << (harmful ? "Cause" : "Cure") << " Sleep"; break;
|
|
case eStatus::PARALYZED: sout << (harmful ? "Cause" : "Cure") << " Paralysis"; break;
|
|
case eStatus::ACID: sout << (harmful ? "Cause" : "Cure") << " Acid"; break;
|
|
}
|
|
break;
|
|
case eItemAbil::CAST_SPELL:
|
|
sout << "Spell: " << (*cSpell::fromNum(abil_data[1])).name();
|
|
break;
|
|
case eItemAbil::BLISS_DOOM:
|
|
if(party)
|
|
sout << "Party ";
|
|
sout << (harmful ? "Doom" : "Bliss");
|
|
break;
|
|
case eItemAbil::AFFECT_EXPERIENCE:
|
|
sout << (harmful ? "Drain" : "Gain") << " Experience";
|
|
break;
|
|
case eItemAbil::AFFECT_SKILL_POINTS:
|
|
sout << (harmful ? "Drain" : "Gain") << " Skill Points";
|
|
break;
|
|
case eItemAbil::AFFECT_HEALTH:
|
|
sout << (harmful ? "Drain Health" : "Heal");
|
|
break;
|
|
case eItemAbil::AFFECT_SPELL_POINTS:
|
|
sout << (harmful ? "Drain" : "Restore") << " Spell Points";
|
|
break;
|
|
case eItemAbil::LIGHT:
|
|
sout << (harmful ? "Drain" : "Increase") << " Light";
|
|
break;
|
|
case eItemAbil::AFFECT_PARTY_STATUS:
|
|
sout << (harmful ? "Lose " : "Gain ");
|
|
switch(ePartyStatus(abil_data[1])) {
|
|
case ePartyStatus::STEALTH: sout << "Stealth"; break;
|
|
case ePartyStatus::FLIGHT: sout << "Flight"; break;
|
|
case ePartyStatus::DETECT_LIFE: sout << "Life Detection"; break;
|
|
case ePartyStatus::FIREWALK: sout << "Firewalk"; break;
|
|
}
|
|
break;
|
|
case eItemAbil::HEALTH_POISON:
|
|
sout << "Major " << (harmful ? "Poison" : "Healing");
|
|
if(party) sout << " All";
|
|
break;
|
|
case eItemAbil::SUMMONING:
|
|
sout << "Summons %s";
|
|
break;
|
|
case eItemAbil::MASS_SUMMONING:
|
|
sout << "Mass summon %s";
|
|
break;
|
|
case eItemAbil::MESSAGE:
|
|
sout << "Readable";
|
|
break;
|
|
}
|
|
return sout.str();
|
|
}
|
|
|
|
void cItem::writeTo(std::ostream& file, std::string prefix) const {
|
|
file << prefix << "VARIETY " << variety << '\n';
|
|
file << prefix << "LEVEL " << item_level << '\n';
|
|
file << prefix << "AWKWARD " << awkward << '\n';
|
|
file << prefix << "BONUS " << bonus << '\n';
|
|
file << prefix << "PROT " << protection << '\n';
|
|
file << prefix << "CHARGES " << charges << '\n';
|
|
file << prefix << "WEAPON " << weap_type << '\n';
|
|
file << prefix << "USE " << magic_use_type << '\n';
|
|
file << prefix << "ICON " << graphic_num << '\n';
|
|
file << prefix << "ABILITY " << ability << '\n';
|
|
file << prefix << "ABILSTR " << abil_data[0] << '\t' << abil_data[1] << '\n';
|
|
file << prefix << "TYPE " << type_flag << '\n';
|
|
file << prefix << "ISSPEC " << is_special << '\n';
|
|
file << prefix << "VALUE " << value << '\n';
|
|
file << prefix << "WEIGHT " << weight << '\n';
|
|
file << prefix << "SPEC " << special_class << '\n';
|
|
file << prefix << "AT " << item_loc.x << ' ' << item_loc.y << '\n';
|
|
file << prefix << "FULLNAME " << maybe_quote_string(full_name) << '\n';
|
|
file << prefix << "NAME " << maybe_quote_string(name) << '\n';
|
|
file << prefix << "TREASURE " << treas_class << '\n';
|
|
if(ident) file << prefix << "IDENTIFIED\n";
|
|
if(property) file << prefix << "PROPERTY\n";
|
|
if(magic) file << prefix << "MAGIC\n";
|
|
if(contained) file << prefix << "CONTAINED\n";
|
|
if(held) file << prefix << "HELD\n";
|
|
if(cursed) file << prefix << "CURSED\n";
|
|
if(concealed) file << prefix << "CONCEALED\n";
|
|
if(enchanted) file << prefix << "ENCHANTED\n";
|
|
if(unsellable) file << prefix << "UNSELLABLE\n";
|
|
}
|
|
|
|
void cItem::readFrom(std::istream& sin){
|
|
while(sin) {
|
|
std::string cur;
|
|
getline(sin, cur);
|
|
std::istringstream sin(cur);
|
|
sin >> cur;
|
|
if(cur == "VARIETY") sin >> variety;
|
|
else if(cur == "LEVEL") sin >> item_level;
|
|
else if(cur == "AWKWARD") sin >> awkward;
|
|
else if(cur == "BONUS") sin >> bonus;
|
|
else if(cur == "PROT") sin >> protection;
|
|
else if(cur == "CHARGES") sin >> charges;
|
|
else if(cur == "WEAPON") sin >> weap_type;
|
|
else if(cur == "USE") sin >> magic_use_type;
|
|
else if(cur == "ICON") sin >> graphic_num;
|
|
else if(cur == "ABILITY") sin >> ability;
|
|
else if(cur == "ABILSTR") sin >> abil_data[0] >> abil_data[1];
|
|
else if(cur == "TYPE") sin >> type_flag;
|
|
else if(cur == "ISSPEC") sin >> is_special;
|
|
else if(cur == "VALUE") sin >> value;
|
|
else if(cur == "WEIGHT") sin >> weight;
|
|
else if(cur == "SPEC") sin >> special_class;
|
|
else if(cur == "AT") sin >> item_loc.x >> item_loc.y;
|
|
else if(cur == "FULLNAME") full_name = read_maybe_quoted_string(sin);
|
|
else if(cur == "NAME") name = read_maybe_quoted_string(sin);
|
|
else if(cur == "TREASURE") sin >> treas_class;
|
|
else if(cur == "IDENTIFIED") ident = true;
|
|
else if(cur == "PROPERTY") property = true;
|
|
else if(cur == "MAGIC") magic = true;
|
|
else if(cur == "CONTAINED") contained = true;
|
|
else if(cur == "HELD") held = true;
|
|
else if(cur == "CURSED") cursed = true;
|
|
else if(cur == "CONCEALED") concealed = true;
|
|
else if(cur == "ENCHANTED") enchanted = true;
|
|
else if(cur == "UNSELLABLE") unsellable = true;
|
|
}
|
|
}
|