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:
2015-01-13 20:54:51 -05:00
parent 0aec4c4c5d
commit f282c06bfa
12 changed files with 192 additions and 41 deletions

View File

@@ -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");