Implement writing item definitions to XML

This commit is contained in:
2015-01-22 12:22:40 -05:00
parent ee27e5341d
commit 670e35f9d5
5 changed files with 226 additions and 20 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<item id='0'>
<variety>shield</variety>
<level>3</level>
<pic>12</pic>

View File

@@ -21,6 +21,7 @@
<xs:enumeration value="tool"/>
<xs:enumeration value="food"/>
<xs:enumeration value="shield"/>
<xs:enumeration value="shield2"/>
<xs:enumeration value="armor"/>
<xs:enumeration value="helm"/>
<xs:enumeration value="gloves"/>
@@ -28,20 +29,22 @@
<xs:enumeration value="ring"/>
<xs:enumeration value="necklace"/>
<xs:enumeration value="poison"/>
<xs:enumeration value="non-usable"/>
<xs:enumeration value="object"/>
<xs:enumeration value="pants"/>
<xs:enumeration value="crossbow"/>
<xs:enumeration value="bolts"/>
<xs:enumeration value="missile"/>
<xs:enumeration value="special"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="weaponType">
<xs:restriction base="xs:token">
<xs:enumeration value="str"/>
<xs:enumeration value="dex"/>
<xs:enumeration value="int"/>
<xs:enumeration value="edged"/>
<xs:enumeration value="bashing"/>
<xs:enumeration value="pole"/>
<!-- The rest of these values are for potential expansion -->
<!-- Each corresponds to a skill/stat -->
<xs:enumeration value="thrown"/>
<xs:enumeration value="archery"/>
<xs:enumeration value="defense"/>
@@ -66,7 +69,8 @@
<xs:element name="bonus" type="xs:integer" minOccurs="0"/>
<xs:element name="protection" type="xs:integer" minOccurs="0"/>
<xs:element name="charges" type="xs:integer" minOccurs="0"/>
<xs:element name="melee-type" type="weaponType" minOccurs="0"/>
<xs:element name="weapon-type" type="weaponType" minOccurs="0"/>
<xs:element name="missile-type" type="xs:integer" minOccurs="0"/>
<xs:element name="pic" type="xs:integer"/>
<xs:element name="flag" type="xs:integer" minOccurs="0"/>
<xs:element name="value" type="xs:integer"/>
@@ -80,6 +84,7 @@
<xs:sequence>
<xs:element name="type" type="xs:integer"/>
<xs:element name="strength" type="xs:integer"/>
<xs:element name="data" type="xs:integer"/>
<xs:element name="use-flag" type="xs:integer" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
@@ -96,7 +101,9 @@
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="description" type="xs:string" minOccurs="0"/>
</xs:all>
<xs:attribute name="id" type="xs:integer" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="items">

View File

@@ -10,6 +10,7 @@
#include <vector>
#include <map>
#include <sstream>
#include <boost/lexical_cast.hpp>
#include "classes.h"
#include "boe.consts.h" // TODO: If this is needed here, maybe it shouldn't be in the "boe" namespace
@@ -1295,34 +1296,182 @@ void cItem::readFrom(std::istream& sin){
}
std::ostream& operator << (std::ostream& out, eSkill e){
return out << (int) e;
switch(e) {
case eSkill::STRENGTH: out << "str"; break;
case eSkill::DEXTERITY: out << "dex"; break;
case eSkill::INTELLIGENCE: out << "int"; break;
case eSkill::EDGED_WEAPONS: out << "edged"; break;
case eSkill::BASHING_WEAPONS: out << "bashing"; break;
case eSkill::POLE_WEAPONS: out << "pole"; break;
case eSkill::THROWN_MISSILES: out << "thrown"; break;
case eSkill::ARCHERY: out << "archery"; break;
case eSkill::DEFENSE: out << "defense"; break;
case eSkill::MAGE_SPELLS: out << "mage"; break;
case eSkill::PRIEST_SPELLS: out << "priest"; break;
case eSkill::MAGE_LORE: out << "mage-lore"; break;
case eSkill::ALCHEMY: out << "alchemy"; break;
case eSkill::ITEM_LORE: out << "item-lore"; break;
case eSkill::DISARM_TRAPS: out << "traps"; break;
case eSkill::LOCKPICKING: out << "lockpick"; break;
case eSkill::ASSASSINATION: out << "assassin"; break;
case eSkill::POISON: out << "poison"; break;
case eSkill::LUCK: out << "luck"; break;
default: out << "edged"; break;
}
return out;
}
std::ostream& operator << (std::ostream& out, eItemType e){
return out << (int) e;
switch(e) {
case eItemType::NO_ITEM: out << "none"; break;
case eItemType::ONE_HANDED: out << "weapon-1hand"; break;
case eItemType::TWO_HANDED: out << "weapon-2hand"; break;
case eItemType::BOW: out << "bow"; break;
case eItemType::ARROW: out << "arrow"; break;
case eItemType::CROSSBOW: out << "crossbow"; break;
case eItemType::BOLTS: out << "bolts"; break;
case eItemType::THROWN_MISSILE: out << "thrown-missile"; break;
case eItemType::MISSILE_NO_AMMO: out << "missile"; break;
case eItemType::ARMOR: out << "armor"; break;
case eItemType::HELM: out << "helm"; break;
case eItemType::GLOVES: out << "gloves"; break;
case eItemType::BOOTS: out << "boots"; break;
case eItemType::SHIELD: out << "shield"; break;
case eItemType::SHIELD_2: out << "shield2"; break;
case eItemType::PANTS: out << "pants"; break;
case eItemType::TOOL: out << "tool"; break;
case eItemType::NECKLACE: out << "necklace"; break;
case eItemType::RING: out << "ring"; break;
case eItemType::POTION: out << "potion"; break;
case eItemType::SCROLL: out << "scroll"; break;
case eItemType::WAND: out << "wand"; break;
case eItemType::WEAPON_POISON: out << "poison"; break;
case eItemType::FOOD: out << "food"; break;
case eItemType::GOLD: out << "gold"; break;
case eItemType::SPECIAL: out << "special"; break;
case eItemType::NON_USE_OBJECT: out << "object"; break;
case eItemType::UNUSED1: out << "none"; break;
}
return out;
}
std::ostream& operator << (std::ostream& out, eItemAbil e){
return out << (int) e;
}
// TODO: Perhaps this should understand symbolic names as well?
std::istream& operator >> (std::istream& in, eSkill& e){
int i;
in >> i;
if(i >= 0 && i < 19)
e = (eSkill) i;
else e = eSkill::INVALID;
std::string key;
in >> key;
e = eSkill::INVALID;
try {
int i = boost::lexical_cast<int>(key);
if(i >= 0 && i < 19)
e = (eSkill) i;
} catch(boost::bad_lexical_cast) {
if(key == "str")
e = eSkill::STRENGTH;
else if(key == "dex")
e = eSkill::DEXTERITY;
else if(key == "int")
e = eSkill::INTELLIGENCE;
else if(key == "edged")
e = eSkill::EDGED_WEAPONS;
else if(key == "bashing")
e = eSkill::BASHING_WEAPONS;
else if(key == "pole")
e = eSkill::POLE_WEAPONS;
else if(key == "thrown")
e = eSkill::THROWN_MISSILES;
else if(key == "archery")
e = eSkill::ARCHERY;
else if(key == "defense")
e = eSkill::DEFENSE;
else if(key == "mage")
e = eSkill::MAGE_SPELLS;
else if(key == "priest")
e = eSkill::PRIEST_SPELLS;
else if(key == "mage-lore")
e = eSkill::MAGE_LORE;
else if(key == "alchemy")
e = eSkill::ALCHEMY;
else if(key == "item-lore")
e = eSkill::ITEM_LORE;
else if(key == "traps")
e = eSkill::DISARM_TRAPS;
else if(key == "lockpick")
e = eSkill::LOCKPICKING;
else if(key == "assassin")
e = eSkill::ASSASSINATION;
else if(key == "poison")
e = eSkill::POISON;
else if(key == "luck")
e = eSkill::LUCK;
}
return in;
}
// TODO: Perhaps this should understand symbolic names as well?
std::istream& operator >> (std::istream& in, eItemType& e){
int i;
in >> i;
if(i > 0 && i < 28)
e = (eItemType) i;
else e = eItemType::NO_ITEM;
std::string key;
in >> key;
e = eItemType::NO_ITEM;
try {
int i = boost::lexical_cast<int>(key);
if(i > 0 && i < 28)
e = (eItemType) i;
} catch(boost::bad_lexical_cast) {
if(key == "weapon-1hand")
e = eItemType::ONE_HANDED;
else if(key == "weapon-2hand")
e = eItemType::TWO_HANDED;
else if(key == "gold")
e = eItemType::GOLD;
else if(key == "bow")
e = eItemType::BOW;
else if(key == "arrow")
e = eItemType::ARROW;
else if(key == "thrown-missile")
e = eItemType::THROWN_MISSILE;
else if(key == "potion")
e = eItemType::POTION;
else if(key == "scroll")
e = eItemType::SCROLL;
else if(key == "wand")
e = eItemType::WAND;
else if(key == "tool")
e = eItemType::TOOL;
else if(key == "food")
e = eItemType::FOOD;
else if(key == "shield")
e = eItemType::SHIELD;
else if(key == "shield2")
e = eItemType::SHIELD_2;
else if(key == "armor")
e = eItemType::ARMOR;
else if(key == "helm")
e = eItemType::HELM;
else if(key == "gloves")
e = eItemType::GLOVES;
else if(key == "boots")
e = eItemType::BOOTS;
else if(key == "ring")
e = eItemType::RING;
else if(key == "necklace")
e = eItemType::NECKLACE;
else if(key == "poison")
e = eItemType::WEAPON_POISON;
else if(key == "object")
e = eItemType::NON_USE_OBJECT;
else if(key == "pants")
e = eItemType::PANTS;
else if(key == "crossbow")
e = eItemType::CROSSBOW;
else if(key == "bolts")
e = eItemType::BOLTS;
else if(key == "missile")
e = eItemType::MISSILE_NO_AMMO;
else if(key == "special")
e = eItemType::SPECIAL;
}
return in;
}

View File

@@ -48,7 +48,6 @@ public:
bool concealed : 1;
bool enchanted : 1;
bool unsellable : 1;
public:
std::string desc;
unsigned char rec_treas_class() const;
short item_weight() const;

View File

@@ -241,6 +241,56 @@ void writeTerrainToXml(ticpp::Printer&& data) {
data.CloseElement("terrains");
}
void writeItemsToXml(ticpp::Printer&& data) {
data.OpenElement("items");
for(size_t i = 0; i < scenario.scen_items.size(); i++) {
data.OpenElement("item");
data.PushAttribute("id", i);
cItem& item = scenario.scen_items[i];
data.PushElement("variety", item.variety);
data.PushElement("level", item.item_level);
data.PushElement("awkward", item.awkward);
data.PushElement("bonus", item.bonus);
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)
data.PushElement("weapon-type", item.weap_type);
data.PushElement("missile-type", item.missile);
data.PushElement("pic", item.graphic_num);
if(item.type_flag > 0)
data.PushElement("flag", item.type_flag);
data.PushElement("name", item.name);
data.PushElement("full-name", item.full_name);
data.PushElement("treasure", item.treas_class);
data.PushElement("value", item.value);
data.PushElement("weight", item.weight);
if(item.special_class > 0)
data.PushElement("class", item.special_class);
data.OpenElement("properties");
if(item.ident) data.PushElement("identified", "true");
if(item.magic) data.PushElement("magic", "true");
if(item.cursed) data.PushElement("cursed", "true");
if(item.concealed) data.PushElement("concealed", "true");
if(item.enchanted) data.PushElement("enchanted", "true");
if(item.unsellable) data.PushElement("unsellable", "true");
data.CloseElement("properties");
if(item.ability != eItemAbil::NONE) {
data.OpenElement("ability");
data.PushElement("type", item.ability);
data.PushElement("strength", item.abil_data[0]);
data.PushElement("data", item.abil_data[1]);
data.PushElement("use-flag", item.magic_use_type);
data.CloseElement("ability");
}
if(!item.desc.empty()) data.PushElement("description", item.desc);
data.CloseElement("item");
}
data.CloseElement("items");
}
void save_scenario(fs::path toFile) {
// TODO: I'm not certain 1.0.0 is the correct version here?
scenario.format.prog_make_ver[0] = 1;
@@ -262,6 +312,7 @@ void save_scenario(fs::path toFile) {
// ...items...
std::ostream& items = scen_file.newFile("scenario/items.xml");
writeItemsToXml(ticpp::Printer("items.xml", items));
// ...and monsters
std::ostream& monsters = scen_file.newFile("scenario/monsters.xml");