Merge the two scenario selection dialogs

Now both preset and custom scenarios are joined using the "Start Scenario" button.
Preset scenarios still get special treatment.
This commit is contained in:
2020-02-25 21:08:29 -05:00
parent 49d88c76e2
commit 093be0d99a
7 changed files with 182 additions and 176 deletions

View File

@@ -1,31 +0,0 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
<dialog defbtn='cancel'>
<button name='cancel' type='regular' top='293' left='311'>Cancel</button>
<text size='large' top='9' left='130' width='126' height='17'>Start a Scenario:</text>
<pict type='scen' size='large' num='0' top='42' left='10'/>
<text framed='true' top='34' left='81' width='292' height='80'>
The Valley of Dying Things
- Easy Difficulty<br/>
The crops have withered, the children are dying, and even the water burns.
Can you find the source of the sickness before the entire valley dies?
</text>
<text name='scen1' top='33' left='11' width='367' height='81'/>
<pict type='scen' size='large' num='1' top='129' left='10'/>
<text framed='true' top='121' left='81' width='292' height='80'>
A Small Rebellion
- Medium Difficulty<br/>
The enemy - a secret band of deadly rebels.
The job - infiltrate them, win their trust, and find their leader.
The question - are you fighting on the right side?
</text>
<text name='scen2' top='121' left='10' width='368' height='80'/>
<pict type='scen' size='large' num='2' top='216' left='10'/>
<text framed='true' top='208' left='81' width='292' height='80'>
The Za-Khazi Run
- Hard Difficulty<br/>
A fortress is under siege, and only you can get them the weapons they need to survive.
You have 20 days to find your way through the nastiest caves in Exile, or all will be lost.
</text>
<text name='scen3' top='208' left='10' width='368' height='80'/>
</dialog>

View File

@@ -1,18 +1,51 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
<dialog defbtn='cancel'>
<text size='large' top='9' left='130' width='126' height='17'>Start a Scenario:</text>
<stack name='list'>
<page>
<!-- Prefab scenarios -->
<pict type='scen' size='large' num='0' top='42' left='10'/>
<text framed='true' top='34' left='81' width='292' height='80'>
The Valley of Dying Things
- Easy Difficulty<br/>
The crops have withered, the children are dying, and even the water burns.
Can you find the source of the sickness before the entire valley dies?
</text>
<text name='scen1' top='33' left='11' width='367' height='81'/>
<pict type='scen' size='large' num='1' top='129' left='10'/>
<text framed='true' top='121' left='81' width='292' height='80'>
A Small Rebellion
- Medium Difficulty<br/>
The enemy - a secret band of deadly rebels.
The job - infiltrate them, win their trust, and find their leader.
The question - are you fighting on the right side?
</text>
<text name='scen2' top='121' left='10' width='368' height='80'/>
<pict type='scen' size='large' num='2' top='216' left='10'/>
<text framed='true' top='208' left='81' width='292' height='80'>
The Za-Khazi Run
- Hard Difficulty<br/>
A fortress is under siege, and only you can get them the weapons they need to survive.
You have 20 days to find your way through the nastiest caves in Exile, or all will be lost.
</text>
<text name='scen3' top='208' left='10' width='368' height='80'/>
</page>
<page default='true' template='scenarios'>
<!-- Custom scenarios -->
<pict type='dlog' num='16' top='10' left='10'/>
<pict name='pic1' type='scen' num='0' top='58' left='62'/>
<text name='desc1' framed='true' top='34' left='104' width='292' height='80'/>
<text outline='double' name='start1' top='32' left='59' width='342' height='84'/>
<pict name='pic2' type='scen' num='0' top='145' left='62'/>
<text name='desc2' framed='true' top='121' left='104' width='292' height='80'/>
<text outline='double' name='start2' top='118' left='59' width='342' height='84'/>
<pict name='pic3' type='scen' num='0' top='232' left='62'/>
<text name='desc3' framed='true' top='208' left='104' width='292' height='80'/>
<text outline='double' name='start3' top='205' left='59' width='342' height='84'/>
</page>
</stack>
<button name='prev' type='left' def-key='left' top='294' left='62'/>
<button name='next' type='right' def-key='right' top='294' left='125'/>
<button name='cancel' type='regular' def-key='esc' top='294' left='337'>Cancel</button>
<pict type='dlog' num='16' top='10' left='10'/>
<button name='next' type='left' def-key='left' top='294' left='62'/>
<button name='prev' type='right' def-key='right' top='294' left='125'/>
<text size='large' top='6' left='58' width='199' height='52'>Your scenarios:</text>
<pict name='pic1' type='scen' num='0' top='58' left='62'/>
<text name='desc1' framed='true' top='34' left='104' width='292' height='80'/>
<text name='start1' top='32' left='59' width='342' height='84'/>
<pict name='pic2' type='scen' num='0' top='145' left='62'/>
<text name='desc2' framed='true' top='121' left='104' width='292' height='80'/>
<text name='start2' top='118' left='59' width='342' height='84'/>
<pict name='pic3' type='scen' num='0' top='232' left='62'/>
<text name='desc3' framed='true' top='208' left='104' width='292' height='80'/>
<text name='start3' top='205' left='59' width='342' height='84'/>
</dialog>

View File

@@ -31,6 +31,7 @@
#include "scrollbar.hpp"
#include "button.hpp"
#include "pict.hpp"
#include "stack.hpp"
#include <boost/lexical_cast.hpp>
#include "prefs.hpp"
#include "shop.hpp"
@@ -55,8 +56,6 @@ extern cUniverse univ;
extern sf::Texture pc_gworld;
extern std::map<eSkill,short> skill_max;
extern std::vector<scen_header_type> scen_headers;
short sign_mode,person_graphic,store_person_graphic,store_sign_mode;
long num_talk_entries;
char null_string[256] = "";
@@ -1349,96 +1348,126 @@ void tip_of_day() {
}
static void put_scen_info(cDialog& me, short page) {
std::ostringstream sout;
static const char *difficulty[] = {"Low","Medium","High","Very High"};
for(short i = 0; i < 3; i++) {
sout.clear();
sout.str("");
sout << i + 1;
std::string n = sout.str();
if(scen_headers.size() > (page * 3 + i)) {
me["pic" + n].show();
dynamic_cast<cPict&>(me["pic" + n]).setPict(scen_headers[page * 3 + i].intro_pic);
sout.str("");
sout << scen_headers[page * 3 + i].name;
sout << " v" << int(scen_headers[page * 3 + i].ver[0]);
sout << '.' << int(scen_headers[page * 3 + i].ver[1]);
sout << '.' << int(scen_headers[page * 3 + i].ver[2]);
sout << " - | Difficulty: " << difficulty[scen_headers[page * 3 + i].difficulty];
sout << ", Rating: " << scen_headers[page * 3 + i].rating;
sout << " |" << scen_headers[page * 3 + i].who1;
sout << " |" << scen_headers[page * 3 + i].who2;
me["desc" + n].setText(sout.str());
me["start" + n].show();
}
else {
me["pic" + n].hide();
me["desc" + n].setText("");
me["start" + n].hide();
class cChooseScenario {
cDialog me{"pick-scenario"};
std::vector<scen_header_type> scen_headers;
void put_scen_info() {
std::ostringstream sout;
static const char *difficulty[] = {"Low","Medium","High","Very High"};
auto& stk = dynamic_cast<cStack&>(me["list"]);
stk.setPageCount(1 + ceil(scen_headers.size() / 3.0));
for(size_t n = 1; n < stk.getPageCount(); n++) {
short page = n - 1;
stk.setPage(n);
for(short i = 0; i < 3; i++) {
sout.clear();
sout.str("");
sout << i + 1;
std::string n = sout.str();
if(scen_headers.size() > (page * 3 + i)) {
me["pic" + n].show();
dynamic_cast<cPict&>(me["pic" + n]).setPict(scen_headers[page * 3 + i].intro_pic);
sout.str("");
sout << scen_headers[page * 3 + i].name;
sout << " v" << int(scen_headers[page * 3 + i].ver[0]);
sout << '.' << int(scen_headers[page * 3 + i].ver[1]);
sout << '.' << int(scen_headers[page * 3 + i].ver[2]);
sout << " - | Difficulty: " << difficulty[scen_headers[page * 3 + i].difficulty];
sout << ", Rating: " << scen_headers[page * 3 + i].rating;
sout << " |" << scen_headers[page * 3 + i].who1;
sout << " |" << scen_headers[page * 3 + i].who2;
me["desc" + n].setText(sout.str());
me["start" + n].show();
} else {
me["pic" + n].hide();
me["desc" + n].setText("");
me["start" + n].hide();
}
}
}
stk.setPage(0);
}
}
static bool pick_a_scen_event_filter(cDialog& me, std::string item_hit, short& page) {
if(item_hit == "cancel") {
me.setResult<short>(-1);
bool doCancel() {
scen_header_type null;
me.setResult<scen_header_type>(null);
me.toast(false);
} else if(item_hit == "next") {
if(page == 0)
page = (scen_headers.size() - 1) / 3;
else page--;
put_scen_info(me, page);
} else if(item_hit == "prev") {
if(page == (scen_headers.size() - 1) / 3)
page = 0;
else page++;
put_scen_info(me, page);
} else if(item_hit.substr(0,item_hit.length()-1) == "start") {
int scen_hit = item_hit[item_hit.length()-1] - '1';
me.setResult<short>(scen_hit + page * 3);
return true;
}
bool doSelectPage(int dir) {
auto& stk = dynamic_cast<cStack&>(me["list"]);
int curPage = stk.getPage(), nPages = stk.getPageCount();
curPage += dir;
if(curPage < 0) curPage += nPages;
else if(curPage >= nPages) curPage -= nPages;
stk.setPage(curPage);
return true;
}
bool doSelectScenario(int which) {
int page = dynamic_cast<cStack&>(me["list"]).getPage();
if(page == 0) {
scen_header_type prefab;
switch(which) {
case 0: prefab.file = "valleydy.boes"; break;
case 1: prefab.file = "stealth.boes"; break;
case 2: prefab.file = "zakhazi.boes"; break;
case 3: prefab.file = "busywork.boes"; break;
}
// Assume prefabs have the right version, I guess
prefab.prog_make_ver[0] = 2;
prefab.prog_make_ver[1] = 0;
prefab.prog_make_ver[2] = 0;
me.setResult<scen_header_type>(prefab);
} else {
int scen_hit = which + (page - 1) * 3;
if(scen_hit >= scen_headers.size()) return false;
me.setResult<scen_header_type>(scen_headers[scen_hit]);
}
me.toast(true);
return true;
}
return true;
}
public:
cChooseScenario() {
// TODO: Add a button to jump to the scenarios folder
scen_headers = build_scen_headers(); // TODO: Either make this local to this class, or make it take scen_headers by reference
}
scen_header_type run() {
using namespace std::placeholders;
extern fs::path scenDir;
if(scen_headers.empty()) { // TODO: Arrange this to be a check before calling run()
cChoiceDlog err("no-scenarios");
err->getControl("path").setText(scenDir.string());
err.show();
return scen_header_type();
}
set_cursor(sword_curs);
me["cancel"].attachClickHandler(std::bind(&cChooseScenario::doCancel, this));
me["next"].attachClickHandler(std::bind(&cChooseScenario::doSelectPage, this, 1));
me["prev"].attachClickHandler(std::bind(&cChooseScenario::doSelectPage, this, -1));
me["start1"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 0));
me["start2"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 1));
me["start3"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 2));
me["scen1"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 0));
me["scen2"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 1));
me["scen3"].attachClickHandler(std::bind(&cChooseScenario::doSelectScenario, this, 2));
put_scen_info();
if(scen_headers.size() <= 3) {
me["next"].hide();
me["prev"].hide();
}
me.run();
return me.getResult<scen_header_type>();
}
};
short pick_a_scen() {
using namespace std::placeholders;
extern fs::path scenDir;
// TODO: Add a button to jump to the scenarios folder
build_scen_headers();
if(scen_headers.empty()) {
cChoiceDlog err("no-scenarios");
err->getControl("path").setText(scenDir.string());
err.show();
return -1;
}
set_cursor(sword_curs);
cDialog pickScen("pick-scenario");
short page = 0;
pickScen.attachClickHandlers(std::bind(pick_a_scen_event_filter, _1, _2, std::ref(page)), {"cancel", "next", "prev", "start1", "start2", "start3"});
put_scen_info(pickScen, 0);
if(scen_headers.size() <= 3) {
pickScen["next"].hide();
pickScen["prev"].hide();
}
pickScen.run();
return pickScen.getResult<short>();
}
short pick_prefab_scen() {
set_cursor(sword_curs);
cChoiceDlog pickScenario("pick-prefab-scen", {"cancel", "scen1", "scen2", "scen3"});
std::string item_hit = pickScenario.show();
if(item_hit == "cancel") return -1;
else return item_hit[4] - '1';
scen_header_type pick_a_scen() {
return cChooseScenario().run();
}

View File

@@ -23,7 +23,6 @@ void edit_party();
void pick_preferences();
void save_prefs(bool resetHelp = false);
void tip_of_day();
short pick_a_scen();
short pick_prefab_scen();
struct scen_header_type pick_a_scen();
#endif

View File

@@ -34,7 +34,6 @@ extern sf::RenderWindow mini_map;
extern short which_combat_type;
extern short cur_town_talk_loaded;
extern cUniverse univ;
std::vector<scen_header_type> scen_headers;
extern bool mac_is_intel;
bool loaded_yet = false, got_nagged = false;
@@ -342,17 +341,20 @@ void start_data_dump() {
}
extern fs::path scenDir;
void build_scen_headers() {
std::vector<scen_header_type> build_scen_headers() {
fs::create_directories(scenDir);
std::cout << progDir << '\n' << scenDir << std::endl;
scen_headers.clear();
std::vector<scen_header_type> scen_headers;
fs::recursive_directory_iterator iter(scenDir);
set_cursor(watch_curs);
while(iter != fs::recursive_directory_iterator()) {
fs::file_status stat = iter->status();
if(stat.type() == fs::regular_file)
load_scenario_header(iter->path());
if(stat.type() == fs::regular_file) {
scen_header_type scen_head;
if(load_scenario_header(iter->path(), scen_head))
scen_headers.push_back(scen_head);
}
iter++;
}
if(scen_headers.size() == 0) { // no scens present
@@ -369,10 +371,11 @@ void build_scen_headers() {
return a < b;
});
}
return scen_headers;
}
// This is only called at startup, when bringing headers of active scenarios.
bool load_scenario_header(fs::path file/*,short header_entry*/){
bool load_scenario_header(fs::path file,scen_header_type& scen_head){
bool file_ok = false;
std::string fname = file.filename().string();
@@ -396,7 +399,7 @@ bool load_scenario_header(fs::path file/*,short header_entry*/){
} else if(file_ext == ".boes") {
if(fs::is_directory(file)) {
if(fs::exists(file/"header.exs"))
return load_scenario_header(file/"header.exs");
return load_scenario_header(file/"header.exs", scen_head);
} else {
unsigned char magic[2];
std::ifstream fin(file.string(), std::ios::binary);
@@ -414,7 +417,6 @@ bool load_scenario_header(fs::path file/*,short header_entry*/){
if(!load_scenario(file, temp_scenario, true))
return false;
scen_header_type scen_head;
scen_head.name = temp_scenario.scen_name;
scen_head.who1 = temp_scenario.who_wrote[0];
scen_head.who2 = temp_scenario.who_wrote[1];
@@ -431,7 +433,5 @@ bool load_scenario_header(fs::path file/*,short header_entry*/){
if(fname == "valleydy" || fname == "stealth" || fname == "zakhazi"/* || fname == "busywork" */)
return false;
scen_headers.push_back(scen_head);
return true;
}

View File

@@ -23,8 +23,8 @@ void import_anim_terrain(short mode);
void start_data_dump();
void end_data_dump();
short onm(char x_sector,char y_sector);
void build_scen_headers();
bool load_scenario_header(fs::path filename/*,short header_entry*/);
std::vector<scen_header_type> build_scen_headers();
bool load_scenario_header(fs::path filename,scen_header_type& header_entry);
fs::path locate_scenario(std::string scen_name);
void alter_rect(rectangle *r);

View File

@@ -30,7 +30,6 @@ using std::vector;
extern bool party_in_memory;
extern long register_flag;
extern sf::RenderWindow mainPtr;
extern std::vector<scen_header_type> scen_headers;
extern cUniverse univ;
extern eGameMode overall_mode;
extern sf::View mainView;
@@ -67,8 +66,10 @@ bool handle_startup_press(location the_point) {
case STARTBTN_ORDER:
pick_preferences();
break;
case STARTBTN_CUSTOM: break; // Currently unused
case STARTBTN_JOIN: // regular scen
case STARTBTN_JOIN:
if(!party_in_memory) {
if(kb::isKeyPressed(kb::LAlt) || kb::isKeyPressed(kb::RAlt)) {
force_party = true;
@@ -79,44 +80,19 @@ bool handle_startup_press(location the_point) {
}
}
switch(pick_prefab_scen()) {
case 0: scen_name = "valleydy.boes"; break;
case 1: scen_name = "stealth.boes"; break;
case 2: scen_name = "zakhazi.boes"; break;
case 3: scen_name = "busywork.boes"; break;
default:
if(force_party) party_in_memory = false;
break;
}
put_party_in_scen(scen_name);
if(force_party && scen_name != univ.party.scen_name)
party_in_memory = false;
break;
case STARTBTN_CUSTOM: // custom
if(!party_in_memory) {
if(kb::isKeyPressed(kb::LAlt) || kb::isKeyPressed(kb::RAlt)) {
force_party = true;
start_new_game(true);
} else {
cChoiceDlog("need-party").show();
break;
}
}
int scen = pick_a_scen();
if(scen < 0) {
auto scen = pick_a_scen();
if(scen.file.empty()) {
if(force_party)
party_in_memory = false;
break;
}
if(scen_headers[scen].prog_make_ver[0] > 2 || scen_headers[scen].prog_make_ver[1] > 0) {
if(scen.prog_make_ver[0] > 2 || scen.prog_make_ver[1] > 0) {
if(force_party)
party_in_memory = false;
cChoiceDlog("scen-version-mismatch").show();
break;
}
scen_name = scen_headers[scen].file;
scen_name = scen.file;
put_party_in_scen(scen_name);
if(force_party && scen_name != univ.party.scen_name)
party_in_memory = false;