Introduce two dialogs for debugging - a Set SDF dialog and a Debug Help dialog

- sd_legit() moved into cParty class
This commit is contained in:
2015-01-26 14:36:15 -05:00
parent 463af1c41e
commit 4fa0efa7d8
14 changed files with 125 additions and 64 deletions

View File

@@ -0,0 +1,32 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
<dialog defbtn='okay'>
<pict type='dlog' num='16' top='8' left='8'/>
<text top='8' left='50' width='400' height='16'>DEBUG MODE HELP</text>
<text top='22' left='50' width='400' height='250'>
Debug mode is intended to aid you in testing your scenario.
While in debug mode, monsters don't move in combat and are killed in one hit.
In addition, you have access to a lot of additional hotkeys.<br/><br/>
Debug hot keys<br/>
B - Leave town<br/>
C - Get cleaned up (lose negative status effects)<br/>
D - Toggle Debug mode<br/>
E - Stealth, Detect Life, Firewalk<br/>
F - Flight<br/>
G - Toggle Ghost mode (letting you pass through walls)<br/>
H - Heal<br/>
K - Kill everything<br/>
N - End Scenario<br/>
O - Location<br/>
Q - Magic map<br/>
R - Return to Start<br/>
S - Set stuff done flags<br/>
T - Enter Town<br/>
W - Refresh jobs/shops<br/>
= - Heal, increase magic skills<br/>
&lt; - Make one day pass<br/>
&gt; - Reset towns (excludes the one you're in, if any)<br/>
/ - Bring up this list<br/>
</text>
<button name='okay' type='regular' top='280' left='387'>OK</button>
</dialog>

19
rsrc/dialogs/set-sdf.xml Normal file
View File

@@ -0,0 +1,19 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
<dialog defbtn='okay'>
<pict type='dlog' num='7' top='8' left='8'/>
<text size='large' top='8' left='50' width='200' height='17'>Edit Stuff Done</text>
<text top='30' left='50' width='200' height='50'>
Here you can edit all the game data that lets the scenario know what you've done.
You can very easily mess up your game by doing this, so be sure you know what you're doing first.
</text>
<text top='105' left='8' width='100' height='16'>SDF Part A:</text>
<field name='x' top='103' left='110' width='80' height='16'/>
<text top='125' left='8' width='100' height='16'>SDF Part B:</text>
<field name='y' top='123' left='110' width='80' height='16'/>
<text top='145' left='8' width='100' height='16'>Value:</text>
<field name='val' top='143' left='110' width='80' height='16'/>
<text name='feedback' top='165' left='8' width='230' height='16'/>
<button name='exit' type='regular' top='185' left='187'>Exit</button>
<button name='set' type='regular' top='185' left='122'>Set</button>
</dialog>

View File

@@ -124,6 +124,9 @@ std::queue<pending_special_type> special_queue;
bool end_scenario = false;
bool current_bash_is_bash = false;
// This is defined in pc.editors.cpp since the PC editor also uses it
extern void edit_stuff_done();
void init_screen_locs() {
short i,j,k,l;
rectangle startup_base = {279,5,327,306};
@@ -1944,27 +1947,14 @@ bool handle_keystroke(sf::Event& event){
print_buf();
break;
case 'S': // TODO: Create a dedicated dialog for this.
case 'S':
if(!in_scen_debug) break;
i = get_num_response(0,299,"Enter SDF Part A");
if(i >= 0 && i < 300){
j = get_num_response(0,49,"Enter SDF Part B");
if(j >= 0 && j < 50){
int x = get_num_response(-1,255,"Enter SDF Value or -1 to print");
if(x < 256 && x >= 0)
PSD[i][j] = x;
else if(x == -1){
sout << "SDF(" << i << ',' << j << ") = " << PSD[i][j];
add_string_to_buf(sout.str());
}
}
}
edit_stuff_done();
break;
case 'T':
if(!in_scen_debug) break;
short find_direction_from;
sout << "Enter Town Number (between 0 and " << univ.scenario.towns.size() - 1 << ')';
i = get_num_response(0, univ.scenario.towns.size() - 1, "Enter Town Number");
if(i >= 0 && i < univ.scenario.towns.size()) {
if(univ.party.direction == 0) find_direction_from = 2;
@@ -2000,28 +1990,7 @@ bool handle_keystroke(sf::Event& event){
break;
case '/':
if(!in_scen_debug) break;
// TODO: Make a dialog for this instead of flooding the transcript
ASB("Debug hot keys");
ASB(" B Leave town");
ASB(" C Get cleaned up");
ASB(" D Toggle Debug mode");
ASB(" E Stealth, Detect Life, Firewalk");
ASB(" F Flight");
ASB(" G Ghost");
ASB(" H Heal");
ASB(" K Kill things");
ASB(" N End Scenario");
ASB(" O Location");
ASB(" Q Magic map");
ASB(" R Return to Start");
ASB(" S Set a SDF");
ASB(" T Enter Town");
ASB(" W Refresh jobs/shops");
ASB(" = Heal, increase magic skills");
ASB(" < Make one day pass");
ASB(" > Towns forgive you");
ASB(" / Bring up this list");
print_buf();
cChoiceDlog("help-debug").show();
break;
case 'a':
if(overall_mode < MODE_TALK_TOWN) {

View File

@@ -751,7 +751,7 @@ void handle_talk_event(location p) {
strnum2 = 0;
break;
case eTalkNode::BUY_SDF:
if((sd_legit(b,c)) && (PSD[b][c] == d)) {
if((univ.party.sd_legit(b,c)) && (PSD[b][c] == d)) {
save_talk_str1 = "You've already learned that.";
strnum1 = -1;
}
@@ -762,7 +762,7 @@ void handle_talk_event(location p) {
else {
univ.party.gold -= a;
put_pc_screen();
if(sd_legit(b,c))
if(univ.party.sd_legit(b,c))
PSD[b][c] = d;
else giveError("Invalid Stuff Done flag called in conversation.");
}
@@ -878,7 +878,7 @@ void handle_talk_event(location p) {
// TODO: Any reason not to call something like kill_monst?
univ.town.monst[store_m_num].active = 0;
// Special killing effects
if(sd_legit(univ.town.monst[store_m_num].spec1,univ.town.monst[store_m_num].spec2))
if(univ.party.sd_legit(univ.town.monst[store_m_num].spec1,univ.town.monst[store_m_num].spec2))
PSD[univ.town.monst[store_m_num].spec1][univ.town.monst[store_m_num].spec2] = 1;
}
talk_end_forced = true;

View File

@@ -713,11 +713,3 @@ void pause(short length) {
if(give_delays)
sf::sleep(time_in_ticks(len));
}
// TODO: I think this should be in a better place, maybe in cParty?
// stuff done legit, i.e. flags are within proper ranges for stuff done flag
bool sd_legit(short a, short b) {
if((minmax(0,299,a) == a) && (minmax(0,9,b) == b))
return true;
return false;
}

View File

@@ -12,4 +12,3 @@ void set_up_apple_events();
void move_sound(ter_num_t ter,short step);
void incidental_noises(bool on_surface);
void pause(short length);
bool sd_legit(short a, short b);

View File

@@ -85,7 +85,7 @@ void place_outd_wand_monst(location where,cOutdoors::cWandering group,short forc
while(i < 10) {
if(!univ.party.out_c[i].exists || ((i == 9) && (forced > 0))) {
if((sd_legit(group.end_spec1,group.end_spec2)) && (PSD[group.end_spec1][group.end_spec2] > 0))
if((univ.party.sd_legit(group.end_spec1,group.end_spec2)) && (PSD[group.end_spec1][group.end_spec2] > 0))
return;
univ.party.out_c[i].exists = true;
univ.party.out_c[i].direction = 0;

View File

@@ -1524,7 +1524,7 @@ void kill_monst(cCreature *which_m,short who_killed,eMainStatus type) {
}
// Special killing effects
if(sd_legit(which_m->spec1,which_m->spec2))
if(univ.party.sd_legit(which_m->spec1,which_m->spec2))
PSD[which_m->spec1][which_m->spec2] = 1;
if(which_m->special_on_kill >= 0)
@@ -2111,7 +2111,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
else for(i = 0; i < 10; i++) PSD[spec.sd1][i] = spec.ex1a;
break;
case eSpecType::COPY_SDF:
if(!sd_legit(spec.sd1,spec.sd2) || !sd_legit(spec.ex1a,spec.ex1b))
if(!univ.party.sd_legit(spec.sd1,spec.sd2) || !univ.party.sd_legit(spec.ex1a,spec.ex1b))
giveError("Stuff Done flag out of range.");
else PSD[spec.sd1][spec.sd2] = PSD[spec.ex1a][spec.ex1b];
break;
@@ -2146,7 +2146,7 @@ void general_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
}
break;
case eSpecType::SET_CAMP_FLAG:
if(!sd_legit(spec.sd1,spec.sd2))
if(!univ.party.sd_legit(spec.sd1,spec.sd2))
giveError("Stuff Done flag out of range (x - 0..299, y - 0..49).");
else {
set_campaign_flag(spec.sd1,spec.sd2,spec.ex1a,spec.ex1b,spec.m1,spec.ex2a);
@@ -2345,7 +2345,7 @@ void oneshot_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
spec = cur_node;
*next_spec = cur_node.jumpto;
if((sd_legit(spec.sd1,spec.sd2)) && (PSD[spec.sd1][spec.sd2] == 250)) {
if((univ.party.sd_legit(spec.sd1,spec.sd2)) && (PSD[spec.sd1][spec.sd2] == 250)) {
*next_spec = -1;
return;
}
@@ -2492,7 +2492,7 @@ void oneshot_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
if(check_mess) {
handle_message(which_mode,cur_spec_type,cur_node.m1,cur_node.m2,a,b);
}
if((set_sd) && (sd_legit(spec.sd1,spec.sd2)))
if((set_sd) && (univ.party.sd_legit(spec.sd1,spec.sd2)))
PSD[spec.sd1][spec.sd2] = 250;
}
@@ -2963,7 +2963,7 @@ void ifthen_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
switch(cur_node.type) {
case eSpecType::IF_SDF:
if(sd_legit(spec.sd1,spec.sd2)) {
if(univ.party.sd_legit(spec.sd1,spec.sd2)) {
if((spec.ex1a >= 0) && (PSD[spec.sd1][spec.sd2] >= spec.ex1a))
*next_spec = spec.ex1b;
else if((spec.ex2a >= 0) && (PSD[spec.sd1][spec.sd2] < spec.ex2a))
@@ -2986,7 +2986,7 @@ void ifthen_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
*next_spec = spec.ex1b;
break;
case eSpecType::IF_SDF_COMPARE:
if((sd_legit(spec.sd1,spec.sd2)) && (sd_legit(spec.ex1a,spec.ex1b))) {
if((univ.party.sd_legit(spec.sd1,spec.sd2)) && (univ.party.sd_legit(spec.ex1a,spec.ex1b))) {
if(PSD[spec.ex1a][spec.ex1b] < PSD[spec.sd1][spec.sd2])
*next_spec = spec.ex2b;
}
@@ -3237,7 +3237,7 @@ void ifthen_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
if(j == 3) *next_spec = spec.pictype;
break;
case eSpecType::IF_SDF_EQ:
if(sd_legit(spec.sd1,spec.sd2)) {
if(univ.party.sd_legit(spec.sd1,spec.sd2)) {
if(PSD[spec.sd1][spec.sd2] == spec.ex1a)
*next_spec = spec.ex1b;
}
@@ -4175,7 +4175,7 @@ void outdoor_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
}
void setsd(short a,short b,short val) {
if(!sd_legit(a,b)) {
if(!univ.party.sd_legit(a,b)) {
giveError("The scenario attempted to change an out of range Stuff Done flag.");
return;
}

View File

@@ -126,7 +126,7 @@ void start_town_mode(short which_town, short entry_dir) {
for(i = 0; i < 10; i++)
if(univ.scenario.town_to_add_to[i] >= 0 && univ.scenario.town_to_add_to[i] < 200 &&
town_number == univ.scenario.town_to_add_to[i] &&
sd_legit(univ.scenario.flag_to_add_to_town[i][0],univ.scenario.flag_to_add_to_town[i][1])) {
univ.party.sd_legit(univ.scenario.flag_to_add_to_town[i][0],univ.scenario.flag_to_add_to_town[i][1])) {
former_town = town_number;
town_number += PSD[univ.scenario.flag_to_add_to_town[i][0]][univ.scenario.flag_to_add_to_town[i][1]];
// Now update horses & boats
@@ -431,7 +431,7 @@ void start_town_mode(short which_town, short entry_dir) {
// Clean out unwanted monsters
for(i = 0; i < univ.town.monst.size(); i++)
if(sd_legit(univ.town.monst[i].spec1,univ.town.monst[i].spec2)) {
if(univ.party.sd_legit(univ.town.monst[i].spec1,univ.town.monst[i].spec2)) {
if(PSD[univ.town.monst[i].spec1][univ.town.monst[i].spec2] > 0)
univ.town.monst[i].active = 0;
}
@@ -1006,7 +1006,7 @@ void create_out_combat_terrain(short type,short num_walls,short /*spec_code*/) {
void elim_monst(unsigned short which,short spec_a,short spec_b) {
short i;
if(!sd_legit(spec_a,spec_b))
if(!univ.party.sd_legit(spec_a,spec_b))
return;
if(PSD[spec_a][spec_b] > 0) {
for(i = 0; i < univ.town.monst.size(); i++)
@@ -1130,7 +1130,7 @@ void erase_specials() {
//if(univ.town->spec_id[k] >= 0) {
sn = univ.town->specials[univ.town->spec_id[k]];
sd1 = sn.sd1; sd2 = sn.sd2;
if((sd_legit(sd1,sd2)) && (PSD[sd1][sd2] == 250)) {
if((univ.party.sd_legit(sd1,sd2)) && (PSD[sd1][sd2] == 250)) {
where = univ.town->special_locs[k];
if((where.x != 100) && ((where.x > univ.town->max_dim()) || (where.y > univ.town->max_dim())
|| (where.x < 0) || (where.y < 0))) {
@@ -1189,7 +1189,7 @@ void erase_out_specials() {
sn = sector.specials[sector.special_id[k]];
sd1 = sn.sd1; sd2 = sn.sd2;
if((sd_legit(sd1,sd2)) && (PSD[sd1][sd2] == 250)) {
if((univ.party.sd_legit(sd1,sd2)) && (PSD[sd1][sd2] == 250)) {
where = sector.special_locs[k];
if((where.x > 48) || (where.y > 48)
|| (where.x < 0) || (where.y < 0)) {

View File

@@ -19,6 +19,7 @@
#include "dlogutil.hpp"
#include "oldstructs.h"
#include "fileio.hpp"
#include "mathutil.hpp"
cParty::cParty(cUniverse& univ, long party_preset) : univ(univ) {
gold = 200;
@@ -982,6 +983,13 @@ iLiving& cParty::pc_present() const {
return *adven[ret];
}
// stuff done legit, i.e. flags are within proper ranges for stuff done flag
bool cParty::sd_legit(short a, short b) {
if((minmax(0,299,a) == a) && (minmax(0,49,b) == b))
return true;
return false;
}
bool operator==(const cParty::cConvers& one, const cParty::cConvers& two) {
if(one.who_said != two.who_said) return false;
if(one.in_town != two.in_town) return false;

View File

@@ -186,6 +186,8 @@ public:
iLiving& pc_present() const; // If only one pc is present, returns that pc. Otherwise returns party.
void swap_pcs(size_t a, size_t b);
bool sd_legit(short a, short b);
typedef std::vector<cEncNote>::iterator encIter;
typedef std::vector<cJournal>::iterator journalIter;
typedef std::vector<cConvers>::iterator talkIter;

View File

@@ -539,3 +539,39 @@ bool spend_xp(short pc_num, short mode, cDialog* parent) {
return xpDlog.getResult<bool>();
}
void edit_stuff_done() {
cDialog sdf_dlg("set-sdf");
sdf_dlg.attachFocusHandlers([](cDialog& me, std::string, bool losing) -> bool {
if(!losing) return true;
int x = me["x"].getTextAsNum(), y = me["y"].getTextAsNum();
if(!univ.party.sd_legit(x,y)) {
std::ostringstream strb;
strb << "SDF (" << x << ',' << y << ") does not exist!";
me["feedback"].setText(strb.str());
} else {
me["feedback"].setText("");
me["val"].setTextToNum(univ.party.stuff_done[x][y]);
}
return true;
}, {"x","y"});
sdf_dlg["set"].attachClickHandler([](cDialog& me, std::string, eKeyMod) -> bool {
int x = me["x"].getTextAsNum(), y = me["y"].getTextAsNum(), val = me["val"].getTextAsNum();
std::ostringstream strb;
if(!univ.party.sd_legit(x,y)) {
strb << "SDF (" << x << ',' << y << ") does not exist!";
me["feedback"].setText(strb.str());
} else {
strb << "You have set SDF (" << x << ',' << y << ") = " << val;
me["feedback"].setText(strb.str());
univ.party.stuff_done[x][y] = val;
}
return true;
});
sdf_dlg["exit"].attachClickHandler(std::bind(&cDialog::toast, &sdf_dlg, false));
// Initialize fields with some default values
sdf_dlg["x"].setText("0");
sdf_dlg["y"].setText("0");
sdf_dlg["val"].setTextToNum(univ.party.stuff_done[0][0]);
sdf_dlg.run();
}

View File

@@ -5,3 +5,4 @@ bool take_gold(short amount,bool print_result);
void give_spec_items();
void pick_race_abil(cPlayer *pc,short mode);
void reset_boats();
void edit_stuff_done();

View File

@@ -307,6 +307,9 @@ void handle_menu_choice(eMenu item_hit) {
case eMenu::EDIT_XP:
edit_xp(&univ.party[current_active_pc]);
break;
case eMenu::SET_SDF:
edit_stuff_done();
break;
}
}