Several little tweaks and fixes

- Fix some uninitialized fields getting populated with random data
- Fix identity of last edited town and outdoor section not being saved
- Fix editor sometimes saving to application directory instead of overwriting the loaded scenario
- Fix town specials being saved to outdoors list and vice versa
- Fix right-most column of map not being loaded properly
- Fix town entry node for start town being called after the first turn of the scenario
- Add option to call a special node at startup (right after the intro dialog)
This commit is contained in:
2015-06-01 22:43:41 -04:00
parent 0849df0e28
commit 7dddcdb86e
13 changed files with 31 additions and 9 deletions

View File

@@ -181,6 +181,7 @@
<xs:element name="num-towns" type="xs:integer"/>
<xs:element name="out-width" type="xs:integer"/>
<xs:element name="out-height" type="xs:integer"/>
<xs:element name="on-init" type="xs:integer"/>
<xs:element name="start-town" type="xs:integer"/>
<xs:element name="town-start">
<xs:complexType>

View File

@@ -17,6 +17,7 @@
#include "boe.infodlg.h"
#include "boe.items.h"
#include <cstring>
#include <queue>
#include "boe.party.h"
#include "boe.monster.h"
#include "boe.town.h"
@@ -72,6 +73,7 @@ extern short current_ground;
extern location golem_m_locs[16];
extern cUniverse univ;
extern sf::Texture pc_gworld;
extern std::queue<pending_special_type> special_queue;
// First icon is displayed for positive values, second for negative, if -1 no negative icon.
// This omits two special cases - major poison, and normal speed; they are hard-coded.
@@ -273,6 +275,8 @@ void put_party_in_scen(std::string scen_name) {
current_pc = first_active_pc();
force_town_enter(univ.scenario.which_town_start,univ.scenario.where_start);
start_town_mode(univ.scenario.which_town_start,9);
while(!special_queue.empty())
special_queue.pop(); // Preserve legacy behaviour of not calling the "enter town" node at scenario start
center = univ.scenario.where_start;
update_explored(univ.scenario.where_start);
overall_mode = MODE_TOWN;
@@ -290,6 +294,8 @@ void put_party_in_scen(std::string scen_name) {
custom_choice_dialog(strs,univ.scenario.intro_mess_pic,PIC_SCEN,buttons) ;
j = 6;
}
short k;
run_special(eSpecCtx::STARTUP, 0, univ.scenario.init_spec, loc(0,0), &i, &j, &k);
give_help(1,2);
// Compatibility flags

View File

@@ -1953,7 +1953,7 @@ void run_special(eSpecCtx which_mode,short which_type,short start_spec,location
case eSpecCtx::TALK: case eSpecCtx::USE_SPEC_ITEM: case eSpecCtx::TOWN_HOSTILE:
case eSpecCtx::TOWN_TIMER: case eSpecCtx::SCEN_TIMER: case eSpecCtx::PARTY_TIMER:
case eSpecCtx::OUTDOOR_ENC: case eSpecCtx::FLEE_ENCOUNTER: case eSpecCtx::WIN_ENCOUNTER:
case eSpecCtx::DROP_ITEM: case eSpecCtx::SHOPPING:
case eSpecCtx::DROP_ITEM: case eSpecCtx::SHOPPING: case eSpecCtx::STARTUP:
// Default behaviour - select entire party, or active member if split or in combat
if(is_combat()) current_pc_picked_in_spec_enc = &univ.party[current_pc];
else {

View File

@@ -370,7 +370,6 @@ void start_town_mode(short which_town, short entry_dir) {
else univ.town.monst[i].active = 0;
}
handle_town_specials(town_number, (short) town_toast,(entry_dir < 9) ? univ.town->start_locs[entry_dir] : town_force_loc);
// TODO: Flush the special node queue on scenario start so that the special actually gets called.
// Flush excess doomguards and viscous goos
for(i = 0; i < univ.town.monst.size(); i++)

View File

@@ -56,6 +56,7 @@ cScenario::cScenario(bool init_strings) {
format.ver[0] = 1;
format.min_run_ver = 2;
format.prog_make_ver[0] = 2;
init_spec = -1;
default_ground = 2;
where_start.x = 24;
where_start.y = 24;

View File

@@ -65,6 +65,7 @@ public:
short intro_mess_pic;
location where_start,out_sec_start,out_start;
size_t which_town_start;
spec_num_t init_spec;
std::array<spec_loc_t,10> town_mods;
rectangle store_item_rects[3];
short store_item_towns[3];
@@ -80,6 +81,7 @@ public:
std::array<cTimer,20> scenario_timers;
std::vector<cSpecial> scen_specials;
cItemStorage storage_shortcuts[10];
// These two \/ are populated at load time and then never used again
location last_out_edited;
short last_town_edited;
scenario_header_flags format;

View File

@@ -530,6 +530,7 @@ enum class eSpecCtx {
HAIL = 25, // Special called by trying to initiate conversation
SHOPPING = 26,
DROP_ITEM = 27,
STARTUP = 28,
};
enum class eSpecType {

View File

@@ -29,8 +29,10 @@ cSpecial::cSpecial(){
m3 = -1;
ex1a = -1;
ex1b = -1;
ex1c = -1;
ex2a = -1;
ex2b = -1;
ex2c = -1;
jumpto = -1;
}

View File

@@ -94,6 +94,7 @@ cTown::cTown(cScenario& scenario, bool init_strings) : scenario(scenario) {
max_num_monst = 30000;
spec_on_entry = -1;
spec_on_entry_if_dead = -1;
spec_on_hostile = -1;
for(i = 0; i < 15; i++) {
sign_locs[i].x = 100;
}

View File

@@ -155,6 +155,7 @@ static void writeScenarioToXml(ticpp::Printer&& data) {
data.PushElement("num-towns", scenario.towns.size());
data.PushElement("out-width", scenario.outdoors.width());
data.PushElement("out-height", scenario.outdoors.height());
data.PushElement("on-init", scenario.init_spec);
data.PushElement("start-town", scenario.which_town_start);
data.PushElement("town-start", scenario.where_start);
data.PushElement("outdoor-start", scenario.out_sec_start);
@@ -307,8 +308,8 @@ static void writeScenarioToXml(ticpp::Printer&& data) {
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);
data.PushElement("last-out-section", cur_out);
data.PushElement("last-town", cur_town);
if(!scenario.custom_graphics.empty()) {
data.OpenElement("graphics");
for(size_t i = 0; i < scenario.custom_graphics.size(); i++) {
@@ -1068,8 +1069,8 @@ void save_scenario(fs::path toFile) {
fname.replace(dot,4,".boes");
else fname += ".boes";
}
scenario.scen_file = fname;
toFile = toFile.parent_path()/fname;
scenario.scen_file = toFile;
// Now write to zip file.
ogzstream zout(toFile.string().c_str());

View File

@@ -542,8 +542,8 @@ static bool commit_spec_enc(cDialog& me, std::string item_hit, node_stack_t& edi
int mode = edit_stack.top().mode, node = edit_stack.top().which;
switch(mode) {
case 0: scenario.scen_specials[node] = edit_stack.top().node; break;
case 1: town->specials[node] = edit_stack.top().node; break;
case 2: current_terrain->specials[node] = edit_stack.top().node; break;
case 1: current_terrain->specials[node] = edit_stack.top().node; break;
case 2: town->specials[node] = edit_stack.top().node; break;
}
edit_stack.pop();
if(item_hit == "okay") {

View File

@@ -696,6 +696,8 @@ static void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) {
int h;
game->GetText(&h);
scenario.outdoors.resize(scenario.outdoors.width(), h);
} else if(type == "on-init") {
game->GetText(&scenario.init_spec);
} else if(type == "start-town") {
game->GetText(&scenario.which_town_start);
// TODO: Make sure town is valid

View File

@@ -24,11 +24,10 @@ map_data load_map(std::istream& fin, bool isTown) {
int n = 0, col = 0;
eMapFeature curFeature = eMapFeature::NONE;
// vehicle_owned = true means the party owns it
bool vehicle_owned, found_something;
bool vehicle_owned;
for(char c : line) {
if(c == '#') break; // Found a comment
if(isblank(c)) continue;
found_something = true;
if(isdigit(c)) {
n *= 10;
n += c - '0';
@@ -85,6 +84,13 @@ map_data load_map(std::istream& fin, bool isTown) {
}
}
}
if(curFeature == eMapFeature::NONE)
data.set(col, row, n);
else {
if((curFeature == eMapFeature::BOAT || curFeature == eMapFeature::HORSE) && !vehicle_owned)
n += 10000;
data.addFeature(col, row, curFeature, n);
}
row++;
}
return data;