Write the code to save the general scenario data to a file
- See monster strings are now fetched from the same list as the special encounter strings instead of a list of their own - There is now a possibility for the scenario intro dialog to have a different icon than the scenario icon - Remove unused intro_mess_len field - Add method to the XML printer class to push a simple element with no attributes or child elements - Automatically close any elements before writing the document to the stream - Fix scenario editor File menu having an invisible "Close All" option that appeared when the option key was pressed
This commit is contained in:
@@ -112,16 +112,11 @@
|
||||
<xs:attribute name="town" type="xs:integer" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="town-flags" minOccurs="0" maxOccurs="10">
|
||||
<xs:element name="town-flag" minOccurs="0" maxOccurs="10">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="town-flag">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="town" type="xs:integer"/>
|
||||
<xs:attribute name="add" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="town" type="xs:integer"/>
|
||||
<xs:attribute name="add-x" type="xs:integer"/>
|
||||
<xs:attribute name="add-y" type="xs:integer"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="specials">
|
||||
@@ -133,7 +128,9 @@
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="description" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="special" type="bool"/>
|
||||
<xs:attribute name="special" type="xs:integer"/>
|
||||
<xs:attribute name="start-with" type="bool"/>
|
||||
<xs:attribute name="useable" type="bool"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
@@ -196,6 +193,20 @@
|
||||
<xs:element ref="creator"/>
|
||||
<xs:element ref="game"/>
|
||||
<xs:element ref="editor"/>
|
||||
<xs:element name="strings">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="string" type="xs:string" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="journal">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="string" type="xs:string" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="boes" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
@@ -242,9 +242,9 @@ void play_see_monster_str(unsigned short m, location monst_loc) {
|
||||
short where1 = is_out() ? univ.party.outdoor_corner.x + univ.party.i_w_c.x : univ.town.num;
|
||||
short where2 = is_out() ? univ.party.outdoor_corner.y + univ.party.i_w_c.y : univ.town.num;
|
||||
std::string placename = is_out() ? univ.out->out_name : univ.town->town_name;
|
||||
cStrDlog display_strings(str1 < 100 ? univ.scenario.monst_strs[str1] : "", str2 < 100 ? univ.scenario.monst_strs[str2] : "", "", pic, type, NULL);
|
||||
cStrDlog display_strings(str1 < 100 ? univ.scenario.spec_strs[str1] : "", str2 < 100 ? univ.scenario.spec_strs[str2] : "", "", pic, type, NULL);
|
||||
display_strings.setSound(snd);
|
||||
display_strings.setRecordHandler(cStringRecorder(NOTE_MONST).string1(str1).string2(str2).from(where1,where2).at(placename));
|
||||
display_strings.setRecordHandler(cStringRecorder(NOTE_SCEN).string1(str1).string2(str2).from(where1,where2).at(placename));
|
||||
display_strings.show();
|
||||
}
|
||||
// Then run the special, if any
|
||||
|
@@ -926,10 +926,6 @@ void cStringRecorder::operator()(cDialog& me) {
|
||||
str1 = univ.scenario.outdoors[label1b][label2b]->spec_strs[label1];
|
||||
str2 = univ.scenario.outdoors[label1b][label2b]->spec_strs[label2];
|
||||
break;
|
||||
case NOTE_MONST:
|
||||
str1 = univ.scenario.monst_strs[label1];
|
||||
str2 = univ.scenario.monst_strs[label2];
|
||||
break;
|
||||
}
|
||||
if(univ.party.record(type, str1, location))
|
||||
give_help(58,0,&me);
|
||||
|
@@ -274,7 +274,7 @@ void put_party_in_scen(std::string scen_name) {
|
||||
if(!univ.scenario.intro_strs[j].empty()) {
|
||||
for(i = 0; i < 6; i++)
|
||||
strs[i] = univ.scenario.intro_strs[i];
|
||||
custom_choice_dialog(strs,univ.scenario.intro_pic,PIC_SCEN,buttons) ;
|
||||
custom_choice_dialog(strs,univ.scenario.intro_mess_pic,PIC_SCEN,buttons) ;
|
||||
j = 6;
|
||||
}
|
||||
give_help(1,2);
|
||||
|
@@ -770,7 +770,6 @@ std::istream& operator>>(std::istream& in, eEncNoteType& type) {
|
||||
if(name == "SCEN") type = NOTE_SCEN;
|
||||
else if(name == "OUT") type = NOTE_OUT;
|
||||
else if(name == "TOWN") type = NOTE_TOWN;
|
||||
else if(name == "MONST") type = NOTE_MONST;
|
||||
else in.setstate(std::ios_base::failbit);
|
||||
return in;
|
||||
}
|
||||
@@ -786,9 +785,6 @@ std::ostream& operator<<(std::ostream& out, eEncNoteType type) {
|
||||
case NOTE_TOWN:
|
||||
out << "TOWN";
|
||||
break;
|
||||
case NOTE_MONST:
|
||||
out << "MONST";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@@ -107,8 +107,7 @@ void cScenario::append(legacy::scenario_data_type& old){
|
||||
difficulty = old.difficulty;
|
||||
intro_pic = old.intro_pic;
|
||||
default_ground = old.default_ground;
|
||||
intro_mess_pic = old.intro_mess_pic;
|
||||
intro_mess_len = old.intro_mess_len;
|
||||
intro_mess_pic = old.intro_pic;
|
||||
where_start.x = old.where_start.x;
|
||||
where_start.y = old.where_start.y;
|
||||
out_sec_start.x = old.out_sec_start.x;
|
||||
@@ -167,3 +166,17 @@ void cScenario::append(legacy::scen_item_data_type& old){
|
||||
for(i = 0; i < 256; i++)
|
||||
ter_types[i].name = old.ter_names[i];
|
||||
}
|
||||
|
||||
static std::string format_version(const unsigned char(& ver)[3]) {
|
||||
std::ostringstream fmt;
|
||||
fmt << int(ver[0]) << '.' << int(ver[1]) << '.' << int(ver[2]);
|
||||
return fmt.str();
|
||||
}
|
||||
|
||||
std::string cScenario::format_ed_version() {
|
||||
return format_version(format.prog_make_ver);
|
||||
}
|
||||
|
||||
std::string cScenario::format_scen_version() {
|
||||
return format_version(format.ver);
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
void destroy_terrain();
|
||||
public:
|
||||
unsigned short difficulty,intro_pic,default_ground;
|
||||
short intro_mess_pic,intro_mess_len;
|
||||
short intro_mess_pic;
|
||||
location where_start,out_sec_start,out_start;
|
||||
size_t which_town_start;
|
||||
short town_to_add_to[10];
|
||||
@@ -79,7 +79,6 @@ public:
|
||||
// This'll make the transition smoother once it becomes a vector.
|
||||
std::array<std::string,50> journal_strs;
|
||||
std::array<std::string,100> spec_strs;
|
||||
std::string monst_strs[100];
|
||||
bool adjust_diff : 1;
|
||||
char : 7;
|
||||
bool is_legacy;
|
||||
@@ -91,6 +90,8 @@ public:
|
||||
void append(legacy::scenario_data_type& old);
|
||||
void append(legacy::scen_item_data_type& old);
|
||||
void writeTo(std::ostream& file) const;
|
||||
std::string format_scen_version();
|
||||
std::string format_ed_version();
|
||||
|
||||
cScenario& operator=(cScenario&& other);
|
||||
cScenario(cScenario&) = delete;
|
||||
|
@@ -717,7 +717,6 @@ enum eEncNoteType {
|
||||
NOTE_SCEN,
|
||||
NOTE_OUT,
|
||||
NOTE_TOWN,
|
||||
NOTE_MONST,
|
||||
};
|
||||
|
||||
// This is a slight misnomer, as a couple of these are not true fields.
|
||||
|
@@ -45,5 +45,7 @@ void Printer::PushNode(Node* node) {
|
||||
}
|
||||
|
||||
Printer::~Printer() {
|
||||
while(!openElements.empty())
|
||||
CloseElement(openElements.top()->Value());
|
||||
stream << doc;
|
||||
}
|
||||
|
@@ -34,6 +34,11 @@ namespace ticpp {
|
||||
template<typename T> void PushText(T textVal) {
|
||||
PushNode(new Text(boost::lexical_cast<std::string>(textVal)));
|
||||
}
|
||||
template<typename T> void PushElement(std::string tagName, T elemVal) {
|
||||
OpenElement(tagName);
|
||||
PushText(elemVal);
|
||||
CloseElement(tagName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "dlogutil.hpp"
|
||||
#include "tarball.hpp"
|
||||
#include "gzstream.h"
|
||||
#include "tinyprint.hpp"
|
||||
|
||||
#define DONE_BUTTON_ITEM 1
|
||||
|
||||
@@ -48,6 +49,21 @@ template<typename Container> static void writeSpecialNodes(std::ostream& fout, C
|
||||
}
|
||||
}
|
||||
|
||||
static std::string boolstr(bool b) {
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
|
||||
template<> void ticpp::Printer::PushElement(std::string tagName, location pos) {
|
||||
OpenElement(tagName);
|
||||
PushAttribute("x", pos.x);
|
||||
PushAttribute("y", pos.y);
|
||||
CloseElement(tagName);
|
||||
}
|
||||
|
||||
static bool is_minmax(int lo, int hi, int val) {
|
||||
return minmax(lo, hi, val) == val;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -61,6 +77,126 @@ void save_scenario(fs::path toFile) {
|
||||
|
||||
// Next, the bulk scenario data.
|
||||
std::ostream& scen_data = scen_file.newFile("scenario/scenario.xml");
|
||||
ticpp::Printer data("scenario.xml", scen_data);
|
||||
data.OpenElement("scenario");
|
||||
data.PushAttribute("boes", scenario.format_ed_version());
|
||||
data.PushElement("title", scenario.scen_name);
|
||||
data.PushElement("icon", scenario.intro_pic);
|
||||
data.PushElement("id", scenario.campaign_id);
|
||||
data.PushElement("version", scenario.format_scen_version());
|
||||
data.PushElement("language", "en-US");
|
||||
data.OpenElement("author");
|
||||
data.PushElement("name", scenario.contact_info);
|
||||
// TODO: Store name and email in separate fields.
|
||||
data.PushElement("email", "");
|
||||
data.CloseElement("author");
|
||||
data.OpenElement("text");
|
||||
data.PushElement("teaser", scenario.who_wrote[0]);
|
||||
data.PushElement("teaser", scenario.who_wrote[1]);
|
||||
if(scenario.intro_pic != scenario.intro_mess_pic)
|
||||
data.PushElement("icon", scenario.intro_mess_pic);
|
||||
for(int i = 0; i < 6; i++)
|
||||
data.PushElement("intro-msg", scenario.intro_strs[i]);
|
||||
data.CloseElement("text");
|
||||
data.OpenElement("ratings");
|
||||
switch(scenario.rating) {
|
||||
case 0: data.PushElement("content", "g"); break;
|
||||
case 1: data.PushElement("content", "pg"); break;
|
||||
case 2: data.PushElement("content", "r"); break;
|
||||
case 3: data.PushElement("content", "nc17"); break;
|
||||
}
|
||||
data.PushElement("difficulty", scenario.difficulty + 1);
|
||||
data.CloseElement("ratings");
|
||||
data.OpenElement("flags");
|
||||
data.PushElement("adjust-difficulty", boolstr(scenario.adjust_diff));
|
||||
data.PushElement("legacy", boolstr(scenario.is_legacy));
|
||||
data.PushElement("custom-graphics", boolstr(scenario.uses_custom_graphics));
|
||||
data.CloseElement("flags");
|
||||
data.OpenElement("creator");
|
||||
data.PushElement("type", "oboe");
|
||||
data.PushElement("version", scenario.format_ed_version());
|
||||
// TODO: fill <os> element
|
||||
data.PushElement("os", "");
|
||||
data.CloseElement("creator");
|
||||
data.OpenElement("game");
|
||||
data.PushElement("num-towns", scenario.towns.size());
|
||||
data.PushElement("out-width", scenario.outdoors.width());
|
||||
data.PushElement("out-height", scenario.outdoors.height());
|
||||
data.PushElement("start-town", scenario.which_town_start);
|
||||
data.PushElement("town-start", scenario.where_start);
|
||||
data.PushElement("outdoor-start", scenario.out_sec_start);
|
||||
data.PushElement("sector-start", scenario.out_start);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
if(is_minmax(0, scenario.towns.size(), scenario.store_item_towns[i])) {
|
||||
data.OpenElement("store-items");
|
||||
data.PushAttribute("top", scenario.store_item_rects[i].top);
|
||||
data.PushAttribute("left", scenario.store_item_rects[i].left);
|
||||
data.PushAttribute("bottom", scenario.store_item_rects[i].bottom);
|
||||
data.PushAttribute("right", scenario.store_item_rects[i].right);
|
||||
data.PushAttribute("town", scenario.store_item_towns[i]);
|
||||
data.CloseElement("store-items");
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < 10; i++) {
|
||||
if(is_minmax(0, scenario.towns.size(), scenario.town_to_add_to[i])) {
|
||||
data.OpenElement("town-flag");
|
||||
data.PushAttribute("town", scenario.town_to_add_to[i]);
|
||||
data.PushAttribute("add-x", scenario.flag_to_add_to_town[i][0]);
|
||||
data.PushAttribute("add-y", scenario.flag_to_add_to_town[i][1]);
|
||||
data.CloseElement("town-flag");
|
||||
}
|
||||
}
|
||||
data.OpenElement("specials");
|
||||
for(int i = 0; i < 50; i++) {
|
||||
data.OpenElement("item");
|
||||
data.PushAttribute("start-with", boolstr(scenario.special_items[i].flags / 10));
|
||||
data.PushAttribute("useable", boolstr(scenario.special_items[i].flags % 10));
|
||||
data.PushAttribute("special", scenario.special_items[i].special);
|
||||
data.PushElement("name", scenario.special_items[i].name);
|
||||
data.PushElement("description", scenario.special_items[i].descr);
|
||||
data.CloseElement("item");
|
||||
}
|
||||
data.CloseElement("specials");
|
||||
for(int i = 0; i < 20; i++) {
|
||||
if(scenario.scenario_timer_times[i] > 0) {
|
||||
data.OpenElement("timer");
|
||||
data.PushAttribute("time", scenario.scenario_timer_times[i]);
|
||||
data.PushText(scenario.scenario_timer_specs[i]);
|
||||
data.CloseElement("timer");
|
||||
}
|
||||
}
|
||||
data.CloseElement("game");
|
||||
data.OpenElement("editor");
|
||||
data.PushElement("default-ground", scenario.default_ground);
|
||||
data.PushElement("last-out-section", scenario.last_out_edited);
|
||||
data.PushElement("last-town", scenario.last_town_edited);
|
||||
for(int i = 0; i < 10; i++) {
|
||||
if(scenario.storage_shortcuts[i].ter_type >= 0) {
|
||||
cScenario::cItemStorage shortcut = scenario.storage_shortcuts[i];
|
||||
data.OpenElement("storage");
|
||||
data.PushElement("on-terrain", shortcut.ter_type);
|
||||
data.PushElement("is-property", boolstr(shortcut.property));
|
||||
for(int j = 0; j < 10; j++) {
|
||||
if(shortcut.item_num[j] >= 0) {
|
||||
data.OpenElement("item");
|
||||
data.PushAttribute("chance", shortcut.item_odds[j]);
|
||||
data.PushText(shortcut.item_num[j]);
|
||||
data.CloseElement("item");
|
||||
}
|
||||
}
|
||||
data.CloseElement("storage");
|
||||
}
|
||||
}
|
||||
data.CloseElement("editor");
|
||||
data.OpenElement("strings");
|
||||
for(size_t i = 0; i < scenario.spec_strs.size(); i++)
|
||||
data.PushElement("string", scenario.spec_strs[i]);
|
||||
data.CloseElement("strings");
|
||||
data.OpenElement("journal");
|
||||
for(size_t i = 0; i < scenario.journal_strs.size(); i++)
|
||||
data.PushElement("string", scenario.journal_strs[i]);
|
||||
data.CloseElement("journal");
|
||||
data.CloseElement("scenario");
|
||||
|
||||
// Then the terrains...
|
||||
std::ostream& terrain = scen_file.newFile("scenario/terrain.xml");
|
||||
|
@@ -996,14 +996,6 @@
|
||||
</object>
|
||||
<int key="connectionID">142</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">performClose:</string>
|
||||
<reference key="source" ref="1014"/>
|
||||
<reference key="destination" ref="776162233"/>
|
||||
</object>
|
||||
<int key="connectionID">193</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">showHelp:</string>
|
||||
@@ -1162,11 +1154,6 @@
|
||||
<reference key="object" ref="705341025"/>
|
||||
<reference key="parent" ref="720053764"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">73</int>
|
||||
<reference key="object" ref="776162233"/>
|
||||
<reference key="parent" ref="720053764"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">112</int>
|
||||
<reference key="object" ref="579971712"/>
|
||||
@@ -1846,6 +1833,11 @@
|
||||
<reference key="object" ref="304878788"/>
|
||||
<reference key="parent" ref="784697102"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">886</int>
|
||||
<reference key="object" ref="776162233"/>
|
||||
<reference key="parent" ref="720053764"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
@@ -1883,7 +1875,6 @@
|
||||
<string key="690.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="691.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="72.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="73.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="75.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="79.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="795.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
@@ -1969,12 +1960,13 @@
|
||||
<string key="883.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="884.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="885.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="886.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">885</int>
|
||||
<int key="maxID">886</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
|
Reference in New Issue
Block a user