More read/write test cases for monsters, especially monster abilities
Fixes: - For radiate abilities, the pattern was not saved and defaulted to single instead of square on load - For summon abilities, what to summon was not saved and chance was incorrectly saved
This commit is contained in:
@@ -40,6 +40,18 @@
|
||||
<xs:enumeration value="hostile-b"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="spellPattern">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="single"/>
|
||||
<xs:enumeration value="square"/>
|
||||
<xs:enumeration value="small-square"/>
|
||||
<xs:enumeration value="open-square"/>
|
||||
<xs:enumeration value="radius-2"/>
|
||||
<xs:enumeration value="radius-3"/>
|
||||
<xs:enumeration value="plus"/>
|
||||
<xs:enumeration value="wall"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="permille">
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:fractionDigits value="1"/>
|
||||
@@ -182,15 +194,11 @@
|
||||
<xs:element name="summon">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="type">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="type"/>
|
||||
<xs:enumeration value="lvl"/>
|
||||
<xs:enumeration value="race"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:choice minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="type" type="xs:integer"/>
|
||||
<xs:element name="lvl" type="xs:integer"/>
|
||||
<xs:element name="race" type="species"/>
|
||||
</xs:choice>
|
||||
<xs:element name="min" type="xs:integer"/>
|
||||
<xs:element name="max" type="xs:integer"/>
|
||||
<xs:element name="duration" type="xs:integer"/>
|
||||
@@ -239,6 +247,7 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="pattern" type="spellPattern" minOccurs="0"/>
|
||||
<xs:element name="chance" type="permille"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="type" use="required">
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/ptr_container/ptr_set.hpp>
|
||||
#include "simpletypes.hpp"
|
||||
#include "spell.hpp"
|
||||
|
||||
std::string oboeVersionString() {
|
||||
unsigned short M, m, f;
|
||||
@@ -646,3 +647,20 @@ std::istream& operator>> (std::istream& in, eContentRating& rating) {
|
||||
in.setstate(std::ios::failbit);
|
||||
return in;
|
||||
}
|
||||
|
||||
// MARK: eSpellPat
|
||||
|
||||
cEnumLookup spell_pat_strs = {
|
||||
"single", "square", "small-square", "open-square", "radius-2", "radius-3", "plus", "wall",
|
||||
};
|
||||
|
||||
std::ostream& operator<< (std::ostream& out, eSpellPat pat) {
|
||||
writeEnum(out, pat, spell_pat_strs, "single");
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>> (std::istream& in, eSpellPat& pat) {
|
||||
if(!readEnum(in, pat, spell_pat_strs, PAT_SINGLE))
|
||||
in.setstate(std::ios::failbit);
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -170,4 +170,7 @@ std::istream& operator >> (std::istream& in, eMonstTime& e);
|
||||
std::ostream& operator<< (std::ostream& out, eAttitude node);
|
||||
std::istream& operator>> (std::istream& in, eAttitude& node);
|
||||
std::ostream& operator<<(std::ostream& out, const cMonster::cAttack& att);
|
||||
std::ostream& operator<< (std::ostream& out, eSpellPat pat);
|
||||
std::istream& operator>> (std::istream& in, eSpellPat& pat);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -572,17 +572,21 @@ void writeMonstersToXml(ticpp::Printer&& data, cScenario& scenario) {
|
||||
case eMonstAbilCat::SUMMON:
|
||||
data.OpenElement("summon");
|
||||
data.PushAttribute("type", abil);
|
||||
data.PushElement("type", param.summon.type);
|
||||
if(param.summon.type == eMonstSummon::SPECIES)
|
||||
data.PushElement("race", eRace(param.summon.what));
|
||||
else data.PushElement(boost::lexical_cast<std::string>(param.summon.type), param.summon.what);
|
||||
data.PushElement("min", param.summon.min);
|
||||
data.PushElement("max", param.summon.max);
|
||||
data.PushElement("duration", param.summon.len);
|
||||
data.PushElement("chance", param.summon.chance);
|
||||
str << std::fixed << std::setprecision(1) << float(param.summon.chance)/10;
|
||||
data.PushElement("chance", str.str());
|
||||
data.CloseElement("summon");
|
||||
break;
|
||||
case eMonstAbilCat::RADIATE:
|
||||
data.OpenElement("radiate");
|
||||
data.PushAttribute("type", abil);
|
||||
data.PushElement("type", param.radiate.type);
|
||||
data.PushElement("pattern", param.radiate.pat);
|
||||
data.PushElement("chance", param.radiate.chance);
|
||||
data.CloseElement("radiate");
|
||||
break;
|
||||
|
||||
@@ -1261,14 +1261,12 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) {
|
||||
} else if(type == "summon") {
|
||||
if(getMonstAbilCategory(abil_type) != eMonstAbilCat::SUMMON)
|
||||
throw xBadVal(type, "type", val, data.Row(), data.Column(), fname);
|
||||
std::set<std::string> reqs = {"type", "min", "max", "duration", "chance"};
|
||||
std::set<std::string> reqs = {"type+what", "min", "max", "duration", "chance"};
|
||||
auto& summon = abil.summon;
|
||||
for(elem = elem.begin(&data); elem != elem.end(); elem++) {
|
||||
elem->GetValue(&type);
|
||||
reqs.erase(type);
|
||||
if(type == "type") {
|
||||
elem->GetText(&summon.type);
|
||||
} else if(type == "min") {
|
||||
if(type == "min") {
|
||||
elem->GetText(&summon.min);
|
||||
} else if(type == "max") {
|
||||
elem->GetText(&summon.max);
|
||||
@@ -1278,7 +1276,17 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) {
|
||||
long double percent;
|
||||
elem->GetText(&percent);
|
||||
summon.chance = percent * 10;
|
||||
} else {
|
||||
if(type == "type" || type == "lvl") {
|
||||
elem->GetText(&summon.what);
|
||||
} else if(type == "race") {
|
||||
eRace race;
|
||||
elem->GetText(&race);
|
||||
summon.what = (mon_num_t) race;
|
||||
} else throw xBadNode(type, elem->Row(), elem->Column(), fname);
|
||||
reqs.erase("type+what");
|
||||
summon.type = boost::lexical_cast<eMonstSummon>(type);
|
||||
}
|
||||
}
|
||||
if(!reqs.empty())
|
||||
throw xMissingElem("summon", *reqs.begin(), data.Row(), data.Column(), fname);
|
||||
@@ -1287,11 +1295,14 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) {
|
||||
throw xBadVal(type, "type", val, data.Row(), data.Column(), fname);
|
||||
std::set<std::string> reqs = {"type", "chance"};
|
||||
auto& radiate = abil.radiate;
|
||||
radiate.pat = PAT_SQ; // Default radiate pattern is 3x3 square
|
||||
for(elem = elem.begin(&data); elem != elem.end(); elem++) {
|
||||
elem->GetValue(&type);
|
||||
reqs.erase(type);
|
||||
if(type == "type") {
|
||||
elem->GetText(&radiate.type);
|
||||
} else if(type == "pattern") {
|
||||
elem->GetText(&radiate.pat);
|
||||
} else if(type == "chance") {
|
||||
elem->GetText(&radiate.chance);
|
||||
} else throw xBadNode(type, elem->Row(), elem->Column(), fname);
|
||||
@@ -1315,7 +1326,7 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) {
|
||||
elem->GetText(&special.extra3);
|
||||
num_params++;
|
||||
}
|
||||
}
|
||||
} else throw xBadNode(type, data.Row(), data.Column(), fname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
test/files/monsters/abil_gen/bad_damage.xml
Normal file
22
test/files/monsters/abil_gen/bad_damage.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='dmg'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_gen/bad_extra.xml
Normal file
20
test/files/monsters/abil_gen/bad_extra.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='drain-sp'>
|
||||
<extra>5</extra>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
22
test/files/monsters/abil_gen/bad_field.xml
Normal file
22
test/files/monsters/abil_gen/bad_field.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='field'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_gen/bad_node.xml
Normal file
20
test/files/monsters/abil_gen/bad_node.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='dmg'>
|
||||
<bad></bad>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
22
test/files/monsters/abil_gen/bad_status.xml
Normal file
22
test/files/monsters/abil_gen/bad_status.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='status'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_gen/bad_type.xml
Normal file
19
test/files/monsters/abil_gen/bad_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='missile'>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
25
test/files/monsters/abil_gen/minimal_damage.xml
Normal file
25
test/files/monsters/abil_gen/minimal_damage.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='dmg'>
|
||||
<type>ray</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
<missile>2</missile>
|
||||
<range>10</range>
|
||||
<extra>fire</extra>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
25
test/files/monsters/abil_gen/minimal_field.xml
Normal file
25
test/files/monsters/abil_gen/minimal_field.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='field'>
|
||||
<type>ray</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
<missile>2</missile>
|
||||
<range>10</range>
|
||||
<extra>cloud-sleep</extra>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
24
test/files/monsters/abil_gen/minimal_range.xml
Normal file
24
test/files/monsters/abil_gen/minimal_range.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='drain-sp'>
|
||||
<type>ray</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
<missile>2</missile>
|
||||
<range>10</range>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
25
test/files/monsters/abil_gen/minimal_status.xml
Normal file
25
test/files/monsters/abil_gen/minimal_status.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='status'>
|
||||
<type>ray</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
<missile>2</missile>
|
||||
<range>10</range>
|
||||
<extra>poison</extra>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
22
test/files/monsters/abil_gen/minimal_touch.xml
Normal file
22
test/files/monsters/abil_gen/minimal_touch.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='drain-sp'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_gen/missing_elem.xml
Normal file
19
test/files/monsters/abil_gen/missing_elem.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='dmg'>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_missile/bad_node.xml
Normal file
20
test/files/monsters/abil_missile/bad_node.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<missile type='missile'>
|
||||
<bad></bad>
|
||||
</missile>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_missile/bad_type.xml
Normal file
19
test/files/monsters/abil_missile/bad_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<missile type='dmg'>
|
||||
</missile>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
25
test/files/monsters/abil_missile/minimal.xml
Normal file
25
test/files/monsters/abil_missile/minimal.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<missile type='missile'>
|
||||
<type>arrow</type>
|
||||
<missile>3</missile>
|
||||
<strength>2d6</strength>
|
||||
<skill>8</skill>
|
||||
<range>10</range>
|
||||
<chance>80</chance>
|
||||
</missile>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_missile/missing_elem.xml
Normal file
19
test/files/monsters/abil_missile/missing_elem.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<missile type='missile'>
|
||||
</missile>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_radiate/bad_node.xml
Normal file
20
test/files/monsters/abil_radiate/bad_node.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<radiate type='radiate'>
|
||||
<bad></bad>
|
||||
</radiate>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_radiate/bad_type.xml
Normal file
19
test/files/monsters/abil_radiate/bad_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<radiate type='dmg'>
|
||||
</radiate>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
21
test/files/monsters/abil_radiate/minimal.xml
Normal file
21
test/files/monsters/abil_radiate/minimal.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<radiate type='radiate'>
|
||||
<type>cloud-sleep</type>
|
||||
<chance>75</chance>
|
||||
</radiate>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_radiate/missing_elem.xml
Normal file
19
test/files/monsters/abil_radiate/missing_elem.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<radiate type='radiate'>
|
||||
</radiate>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
22
test/files/monsters/abil_radiate/pattern.xml
Normal file
22
test/files/monsters/abil_radiate/pattern.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<radiate type='radiate'>
|
||||
<type>cloud-sleep</type>
|
||||
<pattern>plus</pattern>
|
||||
<chance>75</chance>
|
||||
</radiate>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_spec/bad_node.xml
Normal file
20
test/files/monsters/abil_spec/bad_node.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<special type='old-heat'>
|
||||
<bad></bad>
|
||||
</special>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_spec/bad_type.xml
Normal file
19
test/files/monsters/abil_spec/bad_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<special type='dmg'>
|
||||
</special>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
22
test/files/monsters/abil_spec/minimal.xml
Normal file
22
test/files/monsters/abil_spec/minimal.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<special type='old-heat'>
|
||||
<param>1</param>
|
||||
<param>2</param>
|
||||
<param>3</param>
|
||||
</special>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
23
test/files/monsters/abil_spec/too_many_params.xml
Normal file
23
test/files/monsters/abil_spec/too_many_params.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<special type='old-heat'>
|
||||
<param>1</param>
|
||||
<param>2</param>
|
||||
<param>3</param>
|
||||
<param>4</param>
|
||||
</special>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
20
test/files/monsters/abil_summon/bad_node.xml
Normal file
20
test/files/monsters/abil_summon/bad_node.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='summon'>
|
||||
<bad></bad>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_summon/bad_type.xml
Normal file
19
test/files/monsters/abil_summon/bad_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='dmg'>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
24
test/files/monsters/abil_summon/minimal_lvl.xml
Normal file
24
test/files/monsters/abil_summon/minimal_lvl.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='summon'>
|
||||
<lvl>3</lvl>
|
||||
<min>1</min>
|
||||
<max>5</max>
|
||||
<duration>15</duration>
|
||||
<chance>50</chance>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
24
test/files/monsters/abil_summon/minimal_race.xml
Normal file
24
test/files/monsters/abil_summon/minimal_race.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='summon'>
|
||||
<race>reptile</race>
|
||||
<min>1</min>
|
||||
<max>5</max>
|
||||
<duration>15</duration>
|
||||
<chance>50</chance>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
24
test/files/monsters/abil_summon/minimal_type.xml
Normal file
24
test/files/monsters/abil_summon/minimal_type.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='summon'>
|
||||
<type>32</type>
|
||||
<min>1</min>
|
||||
<max>5</max>
|
||||
<duration>15</duration>
|
||||
<chance>50</chance>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/abil_summon/missing_elem.xml
Normal file
19
test/files/monsters/abil_summon/missing_elem.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<summon type='summon'>
|
||||
</summon>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/bad_abil_bad_attr.xml
Normal file
19
test/files/monsters/bad_abil_bad_attr.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general thing='stuff'>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/bad_abil_no_type.xml
Normal file
19
test/files/monsters/bad_abil_no_type.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/bad_abil_type_attr.xml
Normal file
19
test/files/monsters/bad_abil_type_attr.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='bad'>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
19
test/files/monsters/bad_abil_type_none.xml
Normal file
19
test/files/monsters/bad_abil_type_none.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='none'>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
18
test/files/monsters/bad_abil_type_tag.xml
Normal file
18
test/files/monsters/bad_abil_type_tag.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<bad type="dmg"></bad>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
27
test/files/monsters/duplicate_attr.xml
Normal file
27
test/files/monsters/duplicate_attr.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<abilities>
|
||||
<general type='drain-sp'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
<general type='drain-sp'>
|
||||
<type>touch</type>
|
||||
<strength>8</strength>
|
||||
<chance>60</chance>
|
||||
</general>
|
||||
</abilities>
|
||||
</monster>
|
||||
</monsters>
|
||||
27
test/files/monsters/immunity.xml
Normal file
27
test/files/monsters/immunity.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity>
|
||||
<all>true</all>
|
||||
<fear>true</fear>
|
||||
<fire>10</fire>
|
||||
<cold>20</cold>
|
||||
<magic>30</magic>
|
||||
<poison>40</poison>
|
||||
<undead>50</undead>
|
||||
<demon>60</demon>
|
||||
<weird>70</weird>
|
||||
<weap>80</weap>
|
||||
<spec>90</spec>
|
||||
</immunity>
|
||||
</monster>
|
||||
</monsters>
|
||||
27
test/files/monsters/optional.xml
Normal file
27
test/files/monsters/optional.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<monsters boes="2.0.0">
|
||||
<monster id='1'>
|
||||
<name>Test Monster</name>
|
||||
<level>1</level>
|
||||
<armor>0</armor>
|
||||
<skill>2</skill>
|
||||
<hp>10</hp>
|
||||
<speed>4</speed>
|
||||
<race>humanoid</race>
|
||||
<attacks/>
|
||||
<pic h='1' w='1'>5</pic>
|
||||
<attitude>hostile-a</attitude>
|
||||
<immunity/>
|
||||
<default-face>12</default-face>
|
||||
<speed>3</speed>
|
||||
<summon>3</summon>
|
||||
<treasure>4</treasure>
|
||||
<mage>1</mage>
|
||||
<priest>2</priest>
|
||||
<voice>42</voice>
|
||||
<onsight>91</onsight>
|
||||
<loot>
|
||||
<type>128</type>
|
||||
<chance>35</chance>
|
||||
</loot>
|
||||
</monster>
|
||||
</monsters>
|
||||
@@ -151,4 +151,320 @@ TEST_CASE("Loading a monster type definition") {
|
||||
CHECK(scen.scen_monsters[1].a[2].dice == 1);
|
||||
CHECK(scen.scen_monsters[1].a[2].sides == 8);
|
||||
}
|
||||
SECTION("With some immunities") {
|
||||
fin.open("files/monsters/immunity.xml");
|
||||
doc = xmlDocFromStream(fin, "immunity.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].mindless);
|
||||
CHECK(scen.scen_monsters[1].invuln);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::FIRE] == 10);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::COLD] == 20);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::MAGIC] == 30);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::POISON] == 40);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::UNDEAD] == 50);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::DEMON] == 60);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::UNBLOCKABLE] == 70);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::WEAPON] == 80);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::SPECIAL] == 90);
|
||||
// TODO: Setting special damage resistance shouldn't be allowed though
|
||||
}
|
||||
SECTION("With some misc optional data") {
|
||||
fin.open("files/monsters/optional.xml");
|
||||
doc = xmlDocFromStream(fin, "optional.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].speed == 3);
|
||||
CHECK(scen.scen_monsters[1].mu == 1);
|
||||
CHECK(scen.scen_monsters[1].cl == 2);
|
||||
CHECK(scen.scen_monsters[1].treasure == 4);
|
||||
CHECK(scen.scen_monsters[1].corpse_item == 128);
|
||||
CHECK(scen.scen_monsters[1].corpse_item_chance == 35);
|
||||
CHECK(scen.scen_monsters[1].summon_type == 3);
|
||||
CHECK(scen.scen_monsters[1].default_facial_pic == 12);
|
||||
CHECK(scen.scen_monsters[1].ambient_sound == 42);
|
||||
CHECK(scen.scen_monsters[1].see_spec == 91);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Loading monster abilities") {
|
||||
ifstream fin;
|
||||
cScenario scen;
|
||||
Document doc;
|
||||
fin.exceptions(ios::badbit);
|
||||
|
||||
SECTION("With an invalid category") {
|
||||
fin.open("files/monsters/bad_abil_type_tag.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_abil_type_tag.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("With missing type attribute") {
|
||||
fin.open("files/monsters/bad_abil_no_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_abil_no_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr);
|
||||
}
|
||||
SECTION("With an invalid attribute") {
|
||||
fin.open("files/monsters/bad_abil_bad_attr.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_abil_bad_attr.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr);
|
||||
}
|
||||
SECTION("With an invalid type") {
|
||||
fin.open("files/monsters/bad_abil_type_attr.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_abil_type_attr.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception);
|
||||
}
|
||||
SECTION("With a type of none") {
|
||||
fin.open("files/monsters/bad_abil_type_none.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_abil_type_none.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("General Abilities") {
|
||||
SECTION("With a bad ability type") {
|
||||
fin.open("files/monsters/abil_gen/bad_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("With an invalid subtag") {
|
||||
fin.open("files/monsters/abil_gen/bad_node.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_node.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("Missing a required subtag") {
|
||||
fin.open("files/monsters/abil_gen/missing_elem.xml");
|
||||
doc = xmlDocFromStream(fin, "missing_elem.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Minimal touch ability") {
|
||||
fin.open("files/monsters/abil_gen/minimal_touch.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_touch.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.type == eMonstGen::TOUCH);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.strength == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.odds == 600);
|
||||
}
|
||||
SECTION("Minimal ranged ability") {
|
||||
fin.open("files/monsters/abil_gen/minimal_range.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_range.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.type == eMonstGen::RAY);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.strength == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.odds == 600);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.pic == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.range == 10);
|
||||
}
|
||||
SECTION("With an extra value when not needed") {
|
||||
fin.open("files/monsters/abil_gen/bad_extra.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_extra.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("Damage ability without type") {
|
||||
fin.open("files/monsters/abil_gen/bad_damage.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_damage.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Field ability without type") {
|
||||
fin.open("files/monsters/abil_gen/bad_field.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_field.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Status ability without type") {
|
||||
fin.open("files/monsters/abil_gen/bad_status.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_status.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Ranged damage ability") {
|
||||
fin.open("files/monsters/abil_gen/minimal_damage.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_damage.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.type == eMonstGen::RAY);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.strength == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.odds == 600);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.pic == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.range == 10);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.dmg == eDamageType::FIRE);
|
||||
}
|
||||
SECTION("Ranged field ability") {
|
||||
fin.open("files/monsters/abil_gen/minimal_field.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_field.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.type == eMonstGen::RAY);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.strength == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.odds == 600);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.pic == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.range == 10);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.fld == CLOUD_SLEEP);
|
||||
}
|
||||
SECTION("Ranged status ability") {
|
||||
fin.open("files/monsters/abil_gen/minimal_status.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_status.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.type == eMonstGen::RAY);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.strength == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.odds == 600);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.pic == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.range == 10);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.stat == eStatus::POISON);
|
||||
}
|
||||
}
|
||||
SECTION("Missile Abilities") {
|
||||
SECTION("With a bad ability type") {
|
||||
fin.open("files/monsters/abil_missile/bad_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("With an invalid subtag") {
|
||||
fin.open("files/monsters/abil_missile/bad_node.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_node.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("Missing a required subtag") {
|
||||
fin.open("files/monsters/abil_missile/missing_elem.xml");
|
||||
doc = xmlDocFromStream(fin, "missing_elem.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Minimal ability") {
|
||||
fin.open("files/monsters/abil_missile/minimal.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.type == eMonstMissile::ARROW);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.pic == 3);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.dice == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.sides == 6);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.skill == 8);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.range == 10);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.odds == 800);
|
||||
}
|
||||
}
|
||||
SECTION("Radiate Abilities") {
|
||||
SECTION("With a bad ability type") {
|
||||
fin.open("files/monsters/abil_radiate/bad_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("With an invalid subtag") {
|
||||
fin.open("files/monsters/abil_radiate/bad_node.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_node.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("Missing a required subtag") {
|
||||
fin.open("files/monsters/abil_radiate/missing_elem.xml");
|
||||
doc = xmlDocFromStream(fin, "missing_elem.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Minimal ability") {
|
||||
fin.open("files/monsters/abil_radiate/minimal.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.type == CLOUD_SLEEP);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.pat == PAT_SQ);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.chance == 75);
|
||||
}
|
||||
SECTION("With non-default spell pattern") {
|
||||
fin.open("files/monsters/abil_radiate/pattern.xml");
|
||||
doc = xmlDocFromStream(fin, "pattern.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.type == CLOUD_SLEEP);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.pat == PAT_PLUS);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.chance == 75);
|
||||
}
|
||||
}
|
||||
SECTION("Summon Abilities") {
|
||||
SECTION("With a bad ability type") {
|
||||
fin.open("files/monsters/abil_summon/bad_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("With an invalid subtag") {
|
||||
fin.open("files/monsters/abil_summon/bad_node.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_node.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("Missing a required subtag") {
|
||||
fin.open("files/monsters/abil_summon/missing_elem.xml");
|
||||
doc = xmlDocFromStream(fin, "missing_elem.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
|
||||
}
|
||||
SECTION("Minimal type ability") {
|
||||
fin.open("files/monsters/abil_summon/minimal_type.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_type.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::TYPE);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == 32);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
|
||||
}
|
||||
SECTION("Minimal level ability") {
|
||||
fin.open("files/monsters/abil_summon/minimal_lvl.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_lvl.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::LEVEL);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == 3);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
|
||||
}
|
||||
SECTION("Minimal race ability") {
|
||||
fin.open("files/monsters/abil_summon/minimal_race.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal_race.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::SPECIES);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == int(eRace::REPTILE));
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
|
||||
}
|
||||
}
|
||||
SECTION("Special Abilities") {
|
||||
SECTION("With a bad ability type") {
|
||||
fin.open("files/monsters/abil_spec/bad_type.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_type.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
|
||||
}
|
||||
SECTION("With an invalid subtag") {
|
||||
fin.open("files/monsters/abil_spec/bad_node.xml");
|
||||
doc = xmlDocFromStream(fin, "bad_node.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("With too many parameters") {
|
||||
fin.open("files/monsters/abil_spec/too_many_params.xml");
|
||||
doc = xmlDocFromStream(fin, "too_many_params.xml");
|
||||
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
|
||||
}
|
||||
SECTION("With all parameters") {
|
||||
fin.open("files/monsters/abil_spec/minimal.xml");
|
||||
doc = xmlDocFromStream(fin, "minimal.xml");
|
||||
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
|
||||
REQUIRE(scen.scen_monsters.size() >= 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].active);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra1 == 1);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra2 == 2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra3 == 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,24 @@ extern Document xmlDocFromStream(istream& stream, string name);
|
||||
extern void readMonstersFromXml(Document&& data, cScenario& scenario);
|
||||
extern void writeMonstersToXml(Printer&& data, cScenario& scenario);
|
||||
|
||||
// Some setup to make monster abilities printable and comparable
|
||||
using MissileAbil = decltype(uAbility::missile);
|
||||
using GeneralAbil = decltype(uAbility::gen);
|
||||
using SummonAbil = decltype(uAbility::summon);
|
||||
using RadiateAbil = decltype(uAbility::radiate);
|
||||
using SpecialAbil = decltype(uAbility::special);
|
||||
|
||||
static ostream& operator<< (ostream& out, const MissileAbil& abil);
|
||||
static ostream& operator<< (ostream& out, const GeneralAbil& abil);
|
||||
static ostream& operator<< (ostream& out, const SummonAbil& abil);
|
||||
static ostream& operator<< (ostream& out, const RadiateAbil& abil);
|
||||
static ostream& operator<< (ostream& out, const SpecialAbil& abil);
|
||||
static bool operator == (const MissileAbil& lhs, const MissileAbil& rhs);
|
||||
static bool operator == (const GeneralAbil& lhs, const GeneralAbil& rhs);
|
||||
static bool operator == (const SummonAbil& lhs, const SummonAbil& rhs);
|
||||
static bool operator == (const RadiateAbil& lhs, const RadiateAbil& rhs);
|
||||
static bool operator == (const SpecialAbil& lhs, const SpecialAbil& rhs);
|
||||
|
||||
static void in_and_out(string name, cScenario& scen) {
|
||||
string fpath = "junk/monst_";
|
||||
fpath += name;
|
||||
@@ -62,10 +80,287 @@ TEST_CASE("Saving monster types") {
|
||||
CHECK(scen.scen_monsters[1].y_width == 2);
|
||||
CHECK(scen.scen_monsters[1].picture_num == 17);
|
||||
CHECK(scen.scen_monsters[1].default_attitude == eAttitude::HOSTILE_B);
|
||||
CHECK_FALSE(scen.scen_monsters[1].mindless);
|
||||
CHECK_FALSE(scen.scen_monsters[1].invuln);
|
||||
CHECK_FALSE(scen.scen_monsters[1].invisible);
|
||||
CHECK_FALSE(scen.scen_monsters[1].guard);
|
||||
for(int i = 0; i <= 8; i++) {
|
||||
eDamageType dmg = eDamageType(i);
|
||||
CAPTURE(dmg);
|
||||
CHECK(scen.scen_monsters[1].resist[dmg] == 100);
|
||||
}
|
||||
}
|
||||
SECTION("With most optional information") {
|
||||
scen.scen_monsters[1].speed = 3;
|
||||
scen.scen_monsters[1].mu = 1;
|
||||
scen.scen_monsters[1].cl = 2;
|
||||
scen.scen_monsters[1].treasure = 4;
|
||||
scen.scen_monsters[1].corpse_item = 128;
|
||||
scen.scen_monsters[1].corpse_item_chance = 35;
|
||||
scen.scen_monsters[1].mindless = true;
|
||||
scen.scen_monsters[1].invuln = true;
|
||||
scen.scen_monsters[1].invisible = true;
|
||||
scen.scen_monsters[1].guard = true;
|
||||
scen.scen_monsters[1].summon_type = 3;
|
||||
scen.scen_monsters[1].default_facial_pic = 12;
|
||||
scen.scen_monsters[1].ambient_sound = 42;
|
||||
scen.scen_monsters[1].see_spec = 91;
|
||||
in_and_out("full", scen);
|
||||
CHECK(scen.scen_monsters[1].speed == 3);
|
||||
CHECK(scen.scen_monsters[1].mu == 1);
|
||||
CHECK(scen.scen_monsters[1].cl == 2);
|
||||
CHECK(scen.scen_monsters[1].treasure == 4);
|
||||
CHECK(scen.scen_monsters[1].corpse_item == 128);
|
||||
CHECK(scen.scen_monsters[1].corpse_item_chance == 35);
|
||||
CHECK(scen.scen_monsters[1].mindless);
|
||||
CHECK(scen.scen_monsters[1].invuln);
|
||||
CHECK(scen.scen_monsters[1].invisible);
|
||||
CHECK(scen.scen_monsters[1].guard);
|
||||
CHECK(scen.scen_monsters[1].summon_type == 3);
|
||||
CHECK(scen.scen_monsters[1].default_facial_pic == 12);
|
||||
CHECK(scen.scen_monsters[1].ambient_sound == 42);
|
||||
CHECK(scen.scen_monsters[1].see_spec == 91);
|
||||
}
|
||||
SECTION("With resistances") {
|
||||
scen.scen_monsters[1].resist[eDamageType::WEAPON] = 5;
|
||||
scen.scen_monsters[1].resist[eDamageType::FIRE] = 10;
|
||||
scen.scen_monsters[1].resist[eDamageType::POISON] = 15;
|
||||
scen.scen_monsters[1].resist[eDamageType::MAGIC] = 20;
|
||||
scen.scen_monsters[1].resist[eDamageType::UNBLOCKABLE] = 25;
|
||||
scen.scen_monsters[1].resist[eDamageType::COLD] = 30;
|
||||
scen.scen_monsters[1].resist[eDamageType::UNDEAD] = 35;
|
||||
scen.scen_monsters[1].resist[eDamageType::DEMON] = 40;
|
||||
scen.scen_monsters[1].resist[eDamageType::SPECIAL] = 45;
|
||||
in_and_out("resistance", scen);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::WEAPON] == 5);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::FIRE] == 10);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::POISON] == 15);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::MAGIC] == 20);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::UNBLOCKABLE] == 25);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::COLD] == 30);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::UNDEAD] == 35);
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::DEMON] == 40);
|
||||
// This one should not be saved, so we expect it to revert to default
|
||||
CHECK(scen.scen_monsters[1].resist[eDamageType::SPECIAL] == 100);
|
||||
}
|
||||
SECTION("With attacks") {
|
||||
scen.scen_monsters[1].a[0].dice = 1;
|
||||
scen.scen_monsters[1].a[0].sides = 4;
|
||||
scen.scen_monsters[1].a[1].dice = 2;
|
||||
scen.scen_monsters[1].a[1].sides = 6;
|
||||
scen.scen_monsters[1].a[1].type = eMonstMelee::STAB;
|
||||
scen.scen_monsters[1].a[2].sides = 3;
|
||||
scen.scen_monsters[1].a[2].dice = 8;
|
||||
scen.scen_monsters[1].a[2].type = eMonstMelee::SLIME;
|
||||
in_and_out("attacks", scen);
|
||||
CHECK(scen.scen_monsters[1].a[0].dice == 1);
|
||||
CHECK(scen.scen_monsters[1].a[0].sides == 4);
|
||||
CHECK(scen.scen_monsters[1].a[0].type == eMonstMelee::SWING);
|
||||
CHECK(scen.scen_monsters[1].a[1].dice == 2);
|
||||
CHECK(scen.scen_monsters[1].a[1].sides == 6);
|
||||
CHECK(scen.scen_monsters[1].a[1].type == eMonstMelee::STAB);
|
||||
CHECK(scen.scen_monsters[1].a[2].sides == 3);
|
||||
CHECK(scen.scen_monsters[1].a[2].dice == 8);
|
||||
CHECK(scen.scen_monsters[1].a[2].type == eMonstMelee::SLIME);
|
||||
}
|
||||
SECTION("With an ability of every type") {
|
||||
MissileAbil missile = {true, eMonstMissile::SPINE, 5, 1, 8, 7, 10, 500};
|
||||
RadiateAbil radiate = {true, WALL_FIRE, 450, PAT_RAD3};
|
||||
SummonAbil summon = {true, eMonstSummon::TYPE, 128, 1, 8, 50, 580};
|
||||
SpecialAbil
|
||||
split = {true, 1, 2, 3},
|
||||
martyr = {true, 4, 5, 6},
|
||||
absorb = {true, 7, 8, 9},
|
||||
web = {true, 10, 11, 12},
|
||||
heat = {true, 13, 14, 15},
|
||||
special = {true, 16, 17, 18},
|
||||
hit = {true, 19, 20, 21},
|
||||
death = {true, 22, 23, 24};
|
||||
GeneralAbil
|
||||
damage = {true, eMonstGen::RAY, 3, 6, 12, 450},
|
||||
damage2 = {true, eMonstGen::TOUCH, -1, 4, 0, 250},
|
||||
status = {true, eMonstGen::GAZE, 2, 9, 20, 400},
|
||||
status2 = {true, eMonstGen::TOUCH, -1, 13, 0, 600},
|
||||
field = {true, eMonstGen::SPIT, 11, 14, 16, 150},
|
||||
petrify = {true, eMonstGen::BREATH, 15, 18, 22, 350},
|
||||
sp = {true, eMonstGen::RAY, 17, 24, 26, 100},
|
||||
xp = {true, eMonstGen::GAZE, 19, 27, 28, 120},
|
||||
kill = {true, eMonstGen::BREATH, 21, 32, 30, 300},
|
||||
food = {true, eMonstGen::SPIT, 23, 35, 40, 240},
|
||||
gold = {true, eMonstGen::GAZE, 29, 38, 36, 750},
|
||||
stun = {true, eMonstGen::RAY, 31, 33, 34, 800};
|
||||
damage.dmg = eDamageType::FIRE;
|
||||
damage2.dmg = eDamageType::COLD;
|
||||
status.stat = eStatus::PARALYZED;
|
||||
status2.stat = eStatus::POISON;
|
||||
field.fld = FIELD_ANTIMAGIC;
|
||||
stun.stat = eStatus::HASTE_SLOW;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile = missile;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen = damage;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::DAMAGE2].gen = damage2;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen = status;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::STATUS2].gen = status2;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen = field;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::PETRIFY].gen = petrify;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen = sp;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::DRAIN_XP].gen = xp;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::KILL].gen = kill;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::STEAL_FOOD].gen = food;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::STEAL_GOLD].gen = gold;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::STUN].gen = stun;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::SPLITS].special = split;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::MARTYRS_SHIELD].special = martyr;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::ABSORB_SPELLS].special = absorb;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::MISSILE_WEB].special = web;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special = heat;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::SPECIAL].special = special;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::HIT_TRIGGER].special = hit;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::DEATH_TRIGGER].special = death;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate = radiate;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon = summon;
|
||||
in_and_out("abilities", scen);
|
||||
// Data stored in irrelevant slots should not be saved.
|
||||
split.extra2 = split.extra3 = 0;
|
||||
martyr.extra3 = absorb.extra3 = 0;
|
||||
web.extra3 = special.extra3 = 0;
|
||||
hit.extra3 = death.extra2 = death.extra3 = 0;
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile == missile);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen == damage);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE2].gen == damage2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen == status);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS2].gen == status2);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen == field);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::PETRIFY].gen == petrify);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen == sp);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_XP].gen == xp);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::KILL].gen == kill);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STEAL_FOOD].gen == food);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STEAL_GOLD].gen == gold);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STUN].gen == stun);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SPLITS].special == split);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MARTYRS_SHIELD].special == martyr);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::ABSORB_SPELLS].special == absorb);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE_WEB].special == web);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special == heat);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SPECIAL].special == special);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::HIT_TRIGGER].special == hit);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DEATH_TRIGGER].special == death);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate == radiate);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon == summon);
|
||||
}
|
||||
SECTION("Test granularity of permille chances") {
|
||||
MissileAbil missile = {true, eMonstMissile::SPINE, 5, 1, 8, 7, 10};
|
||||
for(int i = 0; i <= 1000; i++) {
|
||||
missile.odds = i;
|
||||
scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile = missile;
|
||||
in_and_out("permille granularity", scen);
|
||||
CAPTURE(i);
|
||||
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.odds == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& out, const MissileAbil& abil) {
|
||||
out << "Missile {";
|
||||
if(!abil.active) return out << "inactive}";
|
||||
out << "type = " << abil.type << ", ";
|
||||
out << "missile = " << abil.pic << ", ";
|
||||
out << "strength = " << abil.dice << 'd' << abil.sides << ", ";
|
||||
out << "skill = " << abil.skill << ", ";
|
||||
out << "range = " << abil.range << ", ";
|
||||
out << "chance = " << abil.odds << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator == (const MissileAbil& lhs, const MissileAbil& rhs) {
|
||||
if(lhs.active != rhs.active) return false;
|
||||
if(lhs.type != rhs.type) return false;
|
||||
if(lhs.pic != rhs.pic) return false;
|
||||
if(lhs.dice != rhs.dice) return false;
|
||||
if(lhs.sides != rhs.sides) return false;
|
||||
if(lhs.skill != rhs.skill) return false;
|
||||
if(lhs.range != rhs.range) return false;
|
||||
if(lhs.odds != rhs.odds) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& out, const GeneralAbil& abil) {
|
||||
out << "General {";
|
||||
if(!abil.active) return out << "inactive}";
|
||||
out << "type = " << abil.type << ", ";
|
||||
if(abil.type != eMonstGen::TOUCH)
|
||||
out << "missile = " << abil.pic << ", ";
|
||||
out << "strength = " << abil.strength << ", ";
|
||||
if(abil.type != eMonstGen::TOUCH)
|
||||
out << "range = " << abil.range << ", ";
|
||||
out << "chance = " << abil.odds << ", ";
|
||||
out << "extra = " << abil.dmg << " | " << abil.stat << " | " << abil.fld << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator == (const GeneralAbil& lhs, const GeneralAbil& rhs) {
|
||||
if(lhs.active != rhs.active) return false;
|
||||
if(lhs.type != rhs.type) return false;
|
||||
if(lhs.strength != rhs.strength) return false;
|
||||
if(lhs.odds != rhs.odds) return false;
|
||||
if(lhs.dmg != rhs.dmg) return false;
|
||||
if(lhs.stat != rhs.stat) return false;
|
||||
if(lhs.fld != rhs.fld) return false;
|
||||
if(lhs.type == eMonstGen::TOUCH) return true;
|
||||
if(lhs.pic != rhs.pic) return false;
|
||||
if(lhs.range != rhs.range) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& out, const SummonAbil& abil) {
|
||||
out << "Summon {";
|
||||
if(!abil.active) return out << "inactive}";
|
||||
out << "type = " << abil.type << ", ";
|
||||
out << "what = " << abil.what << ", ";
|
||||
out << "count = " << abil.min << '-' << abil.max << ", ";
|
||||
out << "duration = " << abil.len << ", ";
|
||||
out << "chance = " << abil.chance << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator == (const SummonAbil& lhs, const SummonAbil& rhs) {
|
||||
if(lhs.active != rhs.active) return false;
|
||||
if(lhs.type != rhs.type) return false;
|
||||
if(lhs.what != rhs.what) return false;
|
||||
if(lhs.min != rhs.min) return false;
|
||||
if(lhs.max != rhs.max) return false;
|
||||
if(lhs.len != rhs.len) return false;
|
||||
if(lhs.chance != rhs.chance) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& out, const RadiateAbil& abil) {
|
||||
out << "Radiate {";
|
||||
if(!abil.active) return out << "inactive}";
|
||||
out << "type = " << abil.type << ", ";
|
||||
out << "pattern = " << abil.pat << ", ";
|
||||
out << "chance = " << abil.chance << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator == (const RadiateAbil& lhs, const RadiateAbil& rhs) {
|
||||
if(lhs.active != rhs.active) return false;
|
||||
if(lhs.type != rhs.type) return false;
|
||||
if(lhs.pat != rhs.pat) return false;
|
||||
if(lhs.chance != rhs.chance) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream& out, const SpecialAbil& abil) {
|
||||
if(!abil.active) return out << "Special {inactive}";
|
||||
out << "Special {" << abil.extra1 << ", " << abil.extra2 << ", " << abil.extra3 << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator == (const SpecialAbil& lhs, const SpecialAbil& rhs) {
|
||||
if(lhs.active != rhs.active) return false;
|
||||
if(lhs.extra1 != rhs.extra1) return false;
|
||||
if(lhs.extra2 != rhs.extra2) return false;
|
||||
if(lhs.extra3 != rhs.extra3) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user