Add test for loading legacy dialogue

Also a minor enhancement to the Set Flag dialogue node.
This commit is contained in:
2016-09-03 23:58:01 -04:00
parent d195fe5a0b
commit 67fdeb3a16
5 changed files with 391 additions and 5 deletions

View File

@@ -94,12 +94,12 @@ the value in C, the character responds with the text in Text 1. Otherwise,the ch
responds with the text in Text 2.</p>
<p>Example: Suppose A is 58, B is 3, and C is 2. If the Stuff Done flag (58,3) is 1, the
response is Text 1. If Stuff Done flag (58,3) is 5, the response is Text 2.</p>
<p><b>Node Type 2 - Set to One </b>The character responds with the text in the Text 1 and
Text 2 fields. In addition, the Stuff Done flag (A,B) is set to 1.</p>
<p><b>Node Type 2 - Set Flag </b>The character responds with the text in the Text 1 and
Text 2 fields. In addition, the Stuff Done flag (A,B) is set to C.</p>
<p>Example: You want Stuff Done flag (100,2) to be set to 1 when the party knows that
theres a treasure hidden in a tree. Old Man McGee tells them that its there when asked
theres a treasure hidden in a tree. Old Man McGee tells them that it's there when asked
about tree. When Old Man McGee is asked about tree use a talking node of this type as a
response, with A set to 100 and B set to 2.</p>
response, with A set to 100, B set to 2, and C set to 1.</p>
<p><b>Node Type 3 - Inn</b> If the party can afford it, conversation ends, and the party
is moved to a different place and healed. Field A is the cost of the inn, and field B is
the quality of the inn (Range 0 ... 3). If the party can afford it, the character says

View File

@@ -106,6 +106,7 @@
9169C3241B3B23610041002B /* libboost_thread.dylib in Copy Libraries and Frameworks */ = {isa = PBXBuildFile; fileRef = 910D9CA31B36439100414B17 /* libboost_thread.dylib */; };
9176FEC71D550EFE006EF694 /* out_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC01D550EFC006EF694 /* out_legacy.cpp */; };
9176FEC81D550EFE006EF694 /* scen_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC11D550EFC006EF694 /* scen_legacy.cpp */; };
9176FECB1D550EFE006EF694 /* talk_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC41D550EFD006EF694 /* talk_legacy.cpp */; };
9176FECC1D550EFE006EF694 /* town_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9176FEC51D550EFE006EF694 /* town_legacy.cpp */; };
9178235D1B2EA0C5007F3444 /* vorbisenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9178235C1B2EA0C5007F3444 /* vorbisenc.framework */; };
9178235E1B2EA0C5007F3444 /* vorbisenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9178235C1B2EA0C5007F3444 /* vorbisenc.framework */; };
@@ -649,6 +650,7 @@
9169C31F1B37A5D50041002B /* BoE Scenario Editor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "BoE Scenario Editor.app"; sourceTree = BUILT_PRODUCTS_DIR; };
9176FEC01D550EFC006EF694 /* out_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = out_legacy.cpp; sourceTree = "<group>"; };
9176FEC11D550EFC006EF694 /* scen_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scen_legacy.cpp; sourceTree = "<group>"; };
9176FEC41D550EFD006EF694 /* talk_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talk_legacy.cpp; sourceTree = "<group>"; };
9176FEC51D550EFE006EF694 /* town_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = town_legacy.cpp; sourceTree = "<group>"; };
9178235C1B2EA0C5007F3444 /* vorbisenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vorbisenc.framework; path = ../../../../../../Library/Frameworks/vorbisenc.framework; sourceTree = "<group>"; };
917823671B2F32DD007F3444 /* vorbisfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vorbisfile.framework; path = ../../../../../../Library/Frameworks/vorbisfile.framework; sourceTree = "<group>"; };
@@ -1362,6 +1364,7 @@
91CC173A1B421CA0003D9A69 /* scen_read.cpp */,
91CC173B1B421CA0003D9A69 /* scen_write.cpp */,
919B13A51BBDE985009905A4 /* spec_legacy.cpp */,
9176FEC41D550EFD006EF694 /* talk_legacy.cpp */,
91C2A6EE1B8FAA8E00346948 /* talk_read.cpp */,
91E381471B97675900F69B81 /* talk_write.cpp */,
91E128E31BC1624700C8BE1D /* ter_legacy.cpp */,
@@ -1899,6 +1902,7 @@
91E128E61BC19DA400C8BE1D /* init.cpp in Sources */,
9176FEC71D550EFE006EF694 /* out_legacy.cpp in Sources */,
9176FEC81D550EFE006EF694 /* scen_legacy.cpp in Sources */,
9176FECB1D550EFE006EF694 /* talk_legacy.cpp in Sources */,
9176FECC1D550EFE006EF694 /* town_legacy.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@@ -801,7 +801,7 @@ void handle_talk_event(location p) {
save_talk_str2 = "";
break;
case eTalkNode::SET_SDF:
PSD[a][b] = 1;
PSD[a][b] = c;
break;
case eTalkNode::INN:
if(univ.party.gold < a) {

View File

@@ -34,6 +34,7 @@ void cSpeech::import_legacy(legacy::talking_record_type& old, std::vector<shop_i
break;
case 2: // set SDF
talk_nodes[i].type = eTalkNode::SET_SDF;
talk_nodes[i].extras[2] = 1;
break;
case 3: // inn
talk_nodes[i].type = eTalkNode::INN;

381
test/talk_legacy.cpp Normal file
View File

@@ -0,0 +1,381 @@
//
// talk_legacy.cpp
// BoE
//
// Created by Celtic Minstrel on 16-08-09.
//
//
#include "catch.hpp"
#include "town.hpp"
#include "talking.hpp"
#include "scenario.hpp"
#include "oldstructs.hpp"
TEST_CASE("Converting legacy talk data") {
cSpeech talk;
legacy::talking_record_type old_talk;
std::vector<shop_info_t> shops;
old_talk.talk_nodes[0].personality = 12;
old_talk.talk_nodes[0].type = 0;
std::copy_n("findthem", 8, old_talk.talk_nodes[0].link1);
std::fill_n(old_talk.talk_nodes[0].extras, 4, 0);
SECTION("Basic data") {
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].personality == 12);
CHECK(talk.talk_nodes[0].type == eTalkNode::REGULAR);
CHECK(talk.talk_nodes[0].link1[0] == 'f');
CHECK(talk.talk_nodes[0].link1[1] == 'i');
CHECK(talk.talk_nodes[0].link1[2] == 'n');
CHECK(talk.talk_nodes[0].link1[3] == 'd');
CHECK(talk.talk_nodes[0].link2[0] == 't');
CHECK(talk.talk_nodes[0].link2[1] == 'h');
CHECK(talk.talk_nodes[0].link2[2] == 'e');
CHECK(talk.talk_nodes[0].link2[3] == 'm');
CHECK(talk.talk_nodes[0].extras[0] == 0);
CHECK(talk.talk_nodes[0].extras[1] == 0);
CHECK(talk.talk_nodes[0].extras[2] == 0);
CHECK(talk.talk_nodes[0].extras[3] == 0);
}
SECTION("Basic & If-Then talking nodes") {
SECTION("Depends on Flag") {
old_talk.talk_nodes[0].type = 1;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::DEP_ON_SDF);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
}
SECTION("Set to One") {
old_talk.talk_nodes[0].type = 2;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SET_SDF);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 1);
}
SECTION("Inn") {
old_talk.talk_nodes[0].type = 3;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
old_talk.talk_nodes[0].extras[3] = 15;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::INN);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
CHECK(talk.talk_nodes[0].extras[3] == 15);
}
SECTION("Depends on time") {
old_talk.talk_nodes[0].type = 4;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::DEP_ON_TIME);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
SECTION("Depends on time with event") {
old_talk.talk_nodes[0].type = 5;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::DEP_ON_TIME_AND_EVENT);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
}
SECTION("Depends on town") {
old_talk.talk_nodes[0].type = 6;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::DEP_ON_TOWN);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
}
SECTION("Shops") {
SECTION("Regular shop") {
old_talk.talk_nodes[0].type = 7;
old_talk.talk_nodes[0].extras[0] = 6;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6); // "Utterly Ridiculous"
CHECK(talk.talk_nodes[0].extras[1] == 6);
CHECK(talk.talk_nodes[0].extras[2] == 0);
REQUIRE(shops.size() == 1);
CHECK(shops[0].type == eShopItemType::ITEM);
CHECK(shops[0].first == 13);
CHECK(shops[0].count == 14);
}
SECTION("Training") {
old_talk.talk_nodes[0].type = 8;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::TRAINING);
}
SECTION("Mage spell shop") {
old_talk.talk_nodes[0].type = 9;
old_talk.talk_nodes[0].extras[0] = 6;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6);
CHECK(talk.talk_nodes[0].extras[1] == 6);
CHECK(talk.talk_nodes[0].extras[2] == 0);
REQUIRE(shops.size() == 1);
CHECK(shops[0].type == eShopItemType::MAGE_SPELL);
CHECK(shops[0].first == 43);
CHECK(shops[0].count == 14);
}
SECTION("Priest spell shop") {
old_talk.talk_nodes[0].type = 10;
old_talk.talk_nodes[0].extras[0] = 6;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6);
CHECK(talk.talk_nodes[0].extras[1] == 6);
CHECK(talk.talk_nodes[0].extras[2] == 0);
REQUIRE(shops.size() == 1);
CHECK(shops[0].type == eShopItemType::PRIEST_SPELL);
CHECK(shops[0].first == 43);
CHECK(shops[0].count == 14);
}
SECTION("Alchemy shop") {
old_talk.talk_nodes[0].type = 11;
old_talk.talk_nodes[0].extras[0] = 6;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6);
CHECK(talk.talk_nodes[0].extras[1] == 6);
CHECK(talk.talk_nodes[0].extras[2] == 0);
REQUIRE(shops.size() == 1);
CHECK(shops[0].type == eShopItemType::ALCHEMY);
CHECK(shops[0].first == 13);
CHECK(shops[0].count == 14);
}
SECTION("Healer") {
old_talk.talk_nodes[0].type = 12;
old_talk.talk_nodes[0].extras[0] = 6;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6);
CHECK(talk.talk_nodes[0].extras[1] == 5);
CHECK(talk.talk_nodes[0].extras[2] == 0);
}
SECTION("Junk Shop") {
old_talk.talk_nodes[0].type = 23;
old_talk.talk_nodes[0].extras[0] = 6;
old_talk.talk_nodes[0].extras[1] = 4;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SHOP);
CHECK(talk.talk_nodes[0].extras[0] == 6);
CHECK(talk.talk_nodes[0].extras[1] == 4);
}
SECTION("Sell weapons") {
old_talk.talk_nodes[0].type = 13;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SELL_WEAPONS);
}
SECTION("Sell armour") {
old_talk.talk_nodes[0].type = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SELL_ARMOR);
}
SECTION("Sell anything") {
old_talk.talk_nodes[0].type = 15;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::SELL_ITEMS);
}
SECTION("Identify") {
old_talk.talk_nodes[0].type = 16;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::IDENTIFY);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
SECTION("Enchant") {
old_talk.talk_nodes[0].type = 17;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::ENCHANT);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
}
SECTION("Other nodes") {
SECTION("Buy info") {
old_talk.talk_nodes[0].type = 18;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_INFO);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
SECTION("Buy SDF") {
old_talk.talk_nodes[0].type = 19;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
old_talk.talk_nodes[0].extras[3] = 15;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_SDF);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
CHECK(talk.talk_nodes[0].extras[3] == 15);
}
SECTION("Buy boat") {
old_talk.talk_nodes[0].type = 20;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_SHIP);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
}
SECTION("Buy horse") {
old_talk.talk_nodes[0].type = 21;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_HORSE);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
}
SECTION("Buy special item") {
old_talk.talk_nodes[0].type = 22;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_SPEC_ITEM);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
}
SECTION("Buy town location") {
old_talk.talk_nodes[0].type = 24;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::BUY_TOWN_LOC);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
}
SECTION("Force end") {
old_talk.talk_nodes[0].type = 25;
old_talk.talk_nodes[0].extras[0] = 12;
old_talk.talk_nodes[0].extras[1] = 13;
old_talk.talk_nodes[0].extras[2] = 14;
old_talk.talk_nodes[0].extras[3] = 15;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::END_FORCE);
CHECK(talk.talk_nodes[0].extras[0] == 12);
CHECK(talk.talk_nodes[0].extras[1] == 13);
CHECK(talk.talk_nodes[0].extras[2] == 14);
CHECK(talk.talk_nodes[0].extras[3] == 15);
}
SECTION("Force end + hostile") {
old_talk.talk_nodes[0].type = 26;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::END_FIGHT);
}
SECTION("Force end + alarm") {
old_talk.talk_nodes[0].type = 27;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::END_ALARM);
}
SECTION("Force end + die") {
old_talk.talk_nodes[0].type = 28;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::END_DIE);
}
SECTION("Call town special") {
old_talk.talk_nodes[0].type = 29;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::CALL_TOWN_SPEC);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
SECTION("Call scenario special") {
old_talk.talk_nodes[0].type = 30;
old_talk.talk_nodes[0].extras[0] = 12;
talk.import_legacy(old_talk, shops);
REQUIRE(talk.talk_nodes.size() >= 1);
CHECK(talk.talk_nodes[0].type == eTalkNode::CALL_SCEN_SPEC);
CHECK(talk.talk_nodes[0].extras[0] == 12);
}
}
}
#if 0
enum class eTalkNode {
REGULAR = 0,
DEP_ON_SDF = 1,
SET_SDF = 2,
INN = 3,
DEP_ON_TIME = 4,
DEP_ON_TIME_AND_EVENT = 5,
DEP_ON_TOWN = 6,
SHOP = 7,
TRAINING = 8,
JOB_BANK = 9,
SELL_WEAPONS = 13,
SELL_ARMOR = 14,
SELL_ITEMS = 15,
IDENTIFY = 16,
ENCHANT = 17,
BUY_INFO = 18,
BUY_SDF = 19,
BUY_SHIP = 20,
BUY_HORSE = 21,
BUY_SPEC_ITEM = 22,
RECEIVE_QUEST = 23,
BUY_TOWN_LOC = 24,
END_FORCE = 25,
END_FIGHT = 26,
END_ALARM = 27, // Town hostile
END_DIE = 28,
CALL_TOWN_SPEC = 29,
CALL_SCEN_SPEC = 30,
};
#endif