Get the scenario, town, and outdoor details dialogs updated for new stuff

- Advanced town details now offers edit buttons to edit the specials immediately

Changes to dialog engine:
- Fix tiny buttons stretching to fill label area
- Fix LEDs stretching if label area is higher than LED button
- Fix LEDs ignoring font setting
This commit is contained in:
2015-01-21 15:59:09 -05:00
parent 2a2e7068d0
commit 41fbd73ef9
13 changed files with 123 additions and 85 deletions

View File

@@ -69,12 +69,13 @@
<xsl:for-each select='dialog/button | dialog/stack/button'>
<div>
<xsl:attribute name='class'>
<xsl:if test='/dialog/@debug = "true" and @type = "tiny"'>debug</xsl:if>
button <xsl:value-of select='./@type'/>
</xsl:attribute>
<xsl:attribute name='style'>
background-image: url('img/button/<xsl:value-of select='./@type'/>.png');
left: <xsl:value-of select='./@left'/>px; top: <xsl:value-of select='./@top'/>px;
<xsl:if test='@type = "push"'>width: <xsl:value-of select='./@width'/>;</xsl:if>
<xsl:if test='@type = "push" or @type = "tiny"'>width: <xsl:value-of select='./@width'/>px;</xsl:if>
</xsl:attribute>
<xsl:attribute name='title'>
<xsl:if test='/dialog/@debug = "true" and @name'>

View File

@@ -3,14 +3,21 @@
<dialog skin='light' defbtn='okay' debug='true'>
<!-- OK button -->
<field name='name' top='51' left='162' width='151' height='16'/>
<button name='okay' type='regular' top='176' left='354'>OK</button>
<button name='okay' type='regular' top='197' left='354'>OK</button>
<pict type='dlog' num='16' top='8' left='8'/>
<text size='large' top='6' left='50' width='256' height='17'>Outdoors Details</text>
<text top='53' left='50' width='101' height='14'>Section name:</text>
<text top='29' left='50' width='87' height='14'>Coordinates:</text>
<text name='loc' top='29' left='142' width='127' height='14'/>
<text top='85' left='50' width='101' height='90'>Comment:<br/><br/>
<text top='85' left='50' width='100' height='16'>Ambient Sound:</text>
<group name='ambient'>
<led name='snd1' top='85' left='150' width='50'>None</led>
<led name='snd2' top='85' left='210' width='50'>Drips</led>
<led name='snd3' top='85' left='270' width='50'>Birdsong</led>
<led name='snd4' top='85' left='350' width='50'>Custom</led>
</group>
<text top='106' left='50' width='101' height='90'>Comment:<br/><br/>
You can put useful notes for yourself here. It's not used by the game for anything.
</text>
<field name='comment' top='83' left='162' width='251' height='80'/>
<field name='comment' top='104' left='162' width='251' height='80'/>
</dialog>

View File

@@ -7,7 +7,7 @@
<field name='who1' top='104' left='181' width='243' height='47'/>
<field name='who2' top='159' left='181' width='243' height='47'/>
<field name='contact' top='214' left='181' width='243' height='65'/>
<button name='okay' type='regular' top='357' left='395'>OK</button>
<button name='okay' type='regular' top='446' left='395'>OK</button>
<pict type='dlog' num='16' top='8' left='8'/>
<text top='23' left='50' width='372' height='53'>
This is where you can define the various pieces of information the user will see when deciding whether or not to play your scenario.
@@ -18,41 +18,29 @@
<text top='102' left='50' width='120' height='14'>Credits, Part 1:</text>
<text top='150' left='50' width='120' height='14'>Credits, Part 2:</text>
<text top='213' left='50' width='120' height='14'>Contact Information:</text>
<text top='294' left='50' width='120' height='14'>Rating:</text>
<!--
TODO: Move these LED labels into the LED elements
-->
<text top='285' left='107' width='23' height='14'>G</text>
<text top='301' left='107' width='23' height='14'>PG</text>
<text top='318' left='107' width='23' height='14'>R</text>
<text top='335' left='107' width='32' height='14'>NC-17</text>
<!--
NOTE: These LEDs had 18 added to the width of their labels
-->
<text top='285' left='50' width='50' height='14'>Rating:</text>
<group name='rating'>
<led name='rate1' state='off' top='288' left='164' width='41'/>
<led name='rate2' state='off' top='305' left='164' width='41'/>
<led name='rate3' state='off' top='322' left='164' width='41'/>
<led name='rate4' state='off' top='339' left='164' width='50'/>
<led name='rate1' state='off' top='288' left='107' width='41'>G</led>
<led name='rate2' state='off' top='305' left='107' width='41'>PG</led>
<led name='rate3' state='off' top='322' left='107' width='41'>R</led>
<led name='rate4' state='off' top='339' left='107' width='50'>NC-17</led>
</group>
<text top='284' left='199' width='71' height='14'>Difficulty:</text>
<!--
TODO: Move these LED labels into the LED elements
-->
<text top='284' left='280' width='76' height='15'>Low Level (1-8)</text>
<text top='301' left='281' width='103' height='15'>Medium Level (9-18)</text>
<text top='318' left='281' width='76' height='15'>High Level (19-30)</text>
<text top='285' left='199' width='71' height='14'>Difficulty:</text>
<!--
TODO: Isn't there a level cap? If so, this should probably say "30-cap" (with cap replaced with the actual cap) rather than 30+.
-->
<text top='335' left='281' width='76' height='15'>Very High Level (30+)</text>
<!--
NOTE: These LEDs had 18 added to the width of their labels
-->
<group name='difficulty'>
<led name='lvl1' state='off' top='288' left='423' width='94'/>
<led name='lvl2' state='off' top='305' left='423' width='94'/>
<led name='lvl3' state='off' top='322' left='423' width='94'/>
<led name='lvl4' state='off' top='339' left='423' width='94'/>
<led name='lvl1' state='off' top='288' left='281' width='94'>Low Level (1-8)</led>
<led name='lvl2' state='off' top='305' left='281' width='94'>Medium Level (9-18)</led>
<led name='lvl3' state='off' top='322' left='281' width='94'>High Level (19-30)</led>
<led name='lvl4' state='off' top='339' left='281' width='94'>Very High Level (30+)</led>
</group>
<led name='adjust' top='356' left='50' size='small' width='350'>Adjust difficulty if played by a party stronger than recommended</led>
<text top='379' left='50' width='120' height='14'>Campaign ID:</text>
<field name='cpnid' top='378' left='181' width='100' height='16'/>
<text top='402' left='50' width='400' height='44'>
If your scenario is part of a campaign of several scenarios,
the ID specified here makes it easy to carry information from one scenario to the next.
It should be the same in each scenario in the series.
</text>
</dialog>

View File

@@ -6,8 +6,9 @@
<field name='onexit2' top='105' left='308' width='67' height='16'/>
<field name='onexit3' top='77' left='440' width='67' height='16'/>
<field name='onexit4' top='105' left='440' width='67' height='16'/>
<field name='onenter' top='142' left='405' width='67' height='16'/>
<field name='onenterdead' top='170' left='405' width='67' height='16'/>
<field name='onenter' top='134' left='405' width='67' height='16'/>
<field name='onenterdead' top='162' left='405' width='67' height='16'/>
<field name='onhostile' top='190' left='405' width='67' height='16'/>
<field name='exit1-x' top='231' left='323' width='39' height='16'/>
<field name='exit1-y' top='231' left='371' width='39' height='16'/>
<field name='exit2-x' top='258' left='323' width='39' height='16'/>
@@ -16,8 +17,8 @@
<field name='exit3-y' top='285' left='371' width='39' height='16'/>
<field name='exit4-x' top='312' left='323' width='39' height='16'/>
<field name='exit4-y' top='312' left='371' width='39' height='16'/>
<button name='okay' type='regular' top='367' left='452'>OK</button>
<button name='cancel' type='regular' def-key='esc' top='367' left='386'>Cancel</button>
<button name='okay' type='regular' top='380' left='452'>OK</button>
<button name='cancel' type='regular' def-key='esc' top='380' left='386'>Cancel</button>
<pict type='dlog' num='16' top='8' left='8'/>
<text size='large' top='6' left='50' width='256' height='17'>Advanced town details</text>
<text top='25' left='50' width='439' height='40'>
@@ -32,30 +33,31 @@
</text>
<text top='134' left='50' width='202' height='66'>
Town entry special node:
(Enter the number of the town special node to call if the party enters the town when its still alive, and/or when its been abandoned.)
(Enter the number of the town special node to call if the party enters the town when it's still alive, and/or when it's been abandoned.)
</text>
<text top='68' left='50' width='197' height='64'>
Exit town specials:
(These are the numbers of the town special nodes to call when the party tries to leave town in the given direction.)
</text>
<text top='143' left='259' width='137' height='15'>Still alive</text>
<text top='170' left='259' width='137' height='15'>Been abandoned</text>
<text top='77' left='250' width='49' height='15'>Top</text>
<text top='105' left='251' width='49' height='15'>Left</text>
<text top='77' left='381' width='53' height='15'>Bottom</text>
<text top='105' left='382' width='49' height='15'>Right</text>
<button name='edit-onenter' type='tiny' top='135' left='259' width='120' height='15'>Still alive</button>
<button name='edit-onenterdead' type='tiny' top='162' left='259' width='120' height='15'>Been abandoned</button>
<button name='edit-onhostile' type='tiny' top='189' left='259' width='120' height='15'>When Goes Hostile</button>
<button name='edit-onexit1' type='tiny' top='81' left='251' width='49' height='15'>Top</button>
<button name='edit-onexit2' type='tiny' top='109' left='251' width='49' height='15'>Left</button>
<button name='edit-onexit3' type='tiny' top='81' left='382' width='53' height='15'>Bottom</button>
<button name='edit-onexit4' type='tiny' top='109' left='382' width='49' height='15'>Right</button>
<text top='232' left='257' width='49' height='15'>Top</text>
<text top='259' left='258' width='49' height='15'>Left</text>
<text top='285' left='258' width='53' height='15'>Bottom</text>
<text top='313' left='259' width='49' height='15'>Right</text>
<text top='207' left='331' width='35' height='15'>X</text>
<text top='207' left='379' width='40' height='15'>Y</text>
<!--
TODO: Move this LED label into the LED element.
-->
<text top='336' left='50' width='320' height='27'>
<text top='212' left='331' width='35' height='15'>X</text>
<text top='212' left='379' width='40' height='15'>Y</text>
<text top='319' left='50' width='100' height='16'>Town Properties:</text>
<led name='hidden' font='plain' top='336' left='50' width='450'>
Town hidden?
(This town cannot be seen until its made visible with a special encounter.)
</text>
<led name='hidden' top='342' left='373'/>
(This town cannot be seen until it's made visible with a special encounter.)
</led>
<led name='nomap' font='plain' top='353' left='50' width='200'>No automap in this town</led>
<led name='noscry' font='plain' top='370' left='50' width='200'>Defy scrying (Magic Map doesn't work)</led>
<led name='barrier' font='plain' top='387' left='50' width='220'>Magical barriers are stronger in this town</led>
</dialog>

View File

@@ -59,7 +59,6 @@ extern cCustomGraphics spec_scen_g;
// TODO: The duplication of rectangle here shouldn't be necessary...
rectangle boat_rects[4] = {rectangle{0,0,36,28}, rectangle{0,28,36,56},rectangle{0,56,36,84},rectangle{0,84,36,112}};
bool gave_no_g_error = false;
eAmbientSound ambient_sound;
//short dest; // 0 - terrain gworld 1 - screen
// if terrain_to_draw is -1, do black
@@ -696,7 +695,7 @@ void play_ambient_sound(){ // TODO: Maybe add a system for in-town ambient sound
if(overall_mode != MODE_OUTDOORS) return; // ambient sounds are outdoors only at the moment
if(get_ran(1,1,100) > 10) return; // 10% chance per move of playing a sound
short sound_to_play;
switch(ambient_sound){
switch(univ.out->ambient_sound){
case AMBIENT_DRIP:
sound_to_play = get_ran(1,0,1);
play_sound(-drip[sound_to_play]);
@@ -706,7 +705,7 @@ void play_ambient_sound(){ // TODO: Maybe add a system for in-town ambient sound
play_sound(-bird[sound_to_play]);
break;
case AMBIENT_CUSTOM:
sound_to_play = univ.out_sound;
sound_to_play = univ.out->out_sound;
play_sound(-sound_to_play);
break;
case AMBIENT_NONE:

View File

@@ -17,6 +17,7 @@
void cOutdoors::append(legacy::outdoor_record_type& old){
int i,j;
ambient_sound = AMBIENT_NONE;
// Collect a list of unused special nodes, to be used for fixing specials that could be triggered in a boat.
std::vector<int> unused_special_slots;
for(i = 0; i < 60; i++) {

View File

@@ -26,6 +26,13 @@ namespace legacy {
class cScenario;
enum eAmbientSound {
AMBIENT_NONE,
AMBIENT_DRIP,
AMBIENT_BIRD,
AMBIENT_CUSTOM,
};
class cOutdoors {
cScenario& scenario;
public:
@@ -71,6 +78,8 @@ public:
std::array<std::string,90> spec_strs;
std::array<std::string,8> sign_strs;
bool special_spot[48][48];
eAmbientSound ambient_sound;
snd_num_t out_sound;
explicit cOutdoors(cScenario& scenario, bool init_strings = false);
void append(legacy::outdoor_record_type& old);

View File

@@ -42,21 +42,6 @@ class cTown { // formerly town_record_type
protected:
cScenario& scenario;
public:
// class cCreature { // formerly creature_start_type
// public:
// unsigned short number;
// unsigned char start_attitude;
// location start_loc;
// unsigned char mobile;
// unsigned char time_flag;
// unsigned char extra1,extra2;
// short spec1, spec2;
// char spec_enc_code,time_code;
// short monster_time,personality;
// short special_on_kill,facial_pic;
//
// cCreature& operator = (legacy::creature_start_type old);
// };
class cWandering { // formerly wandering_type
public:
mon_num_t monst[4];
@@ -105,8 +90,7 @@ public:
bool defy_mapping : 1;
bool defy_scrying : 1;
bool is_hidden : 1;
char reserved_bits : 4;
short hostile_fry_party; // number of a special to be called when the town goes hostile TODO: Not sure about this yet though
char : 4;
short difficulty;
std::string town_name;
// Using std::array here so we can have .size()

View File

@@ -145,13 +145,6 @@ public:
explicit cCurOut(cUniverse& univ);
};
enum eAmbientSound {
AMBIENT_NONE,
AMBIENT_DRIP,
AMBIENT_BIRD,
AMBIENT_CUSTOM,
};
class cUniverse{
template<typename T> using update_info = std::set<T*>;
std::map<pic_num_t, update_info<cItem>> update_items;
@@ -172,7 +165,6 @@ public:
char town_maps[200][8][64]; // formerly stored_town_maps_type
cCurOut out;
char out_maps[100][6][48]; // formerly stored_outdoor_maps_type
snd_num_t out_sound;
fs::path file;
void append(legacy::stored_town_maps_type& old);

View File

@@ -62,6 +62,10 @@ void cButton::draw(){
else style.pointSize = 12;
from_rect = btnRects[type][depressed];
to_rect = frame;
if(type == BTN_TINY) {
to_rect.right = to_rect.left + 14;
to_rect.bottom = to_rect.top + 10;
}
rect_draw_some_item(buttons[btnGW[type]],from_rect,*inWindow,to_rect,sf::BlendAlpha);
style.colour = sf::Color::Black;
style.lineHeight = 8;
@@ -244,9 +248,11 @@ void cLed::draw(){
TextStyle style;
style.pointSize = textSize;
style.lineHeight = textSize - 1;
style.font = textFont;
from_rect = ledRects[state][depressed];
to_rect = frame;
to_rect.right = to_rect.left + 14;
to_rect.bottom = to_rect.top + 10;
rect_draw_some_item(buttons[btnGW[BTN_LED]],from_rect,*inWindow,to_rect);
style.colour = parent->getDefTextClr();
to_rect.right = frame.right;

View File

@@ -2038,22 +2038,26 @@ static bool save_scen_details(cDialog& me) {
cLedGroup& rating = dynamic_cast<cLedGroup&>(me["rating"]);
scenario.rating = rating.getSelected()[4] - '1';
}
scenario.adjust_diff = dynamic_cast<cLed&>(me["adjust"]).getState() != led_red;
for(i = 0; i < 3; i++)
scenario.format.ver[i] = me["ver" + std::to_string(i + 1)].getTextAsNum();
scenario.who_wrote[0] = me["who1"].getText().substr(0, 60);
scenario.who_wrote[1] = me["who2"].getText().substr(0, 60);
scenario.contact_info = me["contact"].getText().substr(0, 256);
scenario.campaign_id = me["cpnid"].getText();
return true;
}
static void put_scen_details_in_dlog(cDialog& me) {
dynamic_cast<cLedGroup&>(me["difficulty"]).setSelected("lvl" + std::to_string(scenario.difficulty + 1));
dynamic_cast<cLedGroup&>(me["rating"]).setSelected("rate" + std::to_string(scenario.rating + 1));
dynamic_cast<cLed&>(me["adjust"]).setState(scenario.adjust_diff ? led_red : led_off);
for(int i = 0; i < 3; i++)
me["ver" + std::to_string(i + 1)].setTextToNum(scenario.format.ver[i]);
me["who1"].setText(scenario.who_wrote[0]);
me["who2"].setText(scenario.who_wrote[1]);
me["contact"].setText(scenario.contact_info);
me["cpnid"].setText(scenario.campaign_id);
}
static bool edit_scen_details_event_filter(cDialog& me, std::string, eKeyMod) {

View File

@@ -270,7 +270,7 @@ short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, con
break;
}
if(cur_choice < 0 || cur_choice >= strings.size())
cur_choice = 0;
cur_choice = -1;
cStringChoice dlog(strings, title, parent);
return dlog.show(cur_choice);

View File

@@ -434,6 +434,24 @@ void outdoor_details() {
out_dlg["loc"].setText(str_out.str());
out_dlg["comment"].setText(current_terrain->comment);
out_dlg["name"].setText(current_terrain->out_name);
dynamic_cast<cLedGroup&>(out_dlg["ambient"]).setSelected("snd" + std::to_string(int(current_terrain->ambient_sound) + 1));
out_dlg["ambient"].attachFocusHandler([](cDialog& me, std::string, bool) -> bool {
cLedGroup& lg = dynamic_cast<cLedGroup&>(me["ambient"]);
std::string hit = lg.getSelected();
std::string prev = lg.getPrevSelection();
eAmbientSound choice = eAmbientSound(hit[3] - '1');
if(choice == AMBIENT_CUSTOM) {
int i = prev == "snd4" ? current_terrain->out_sound : -1;
i = choose_text(STRT_SND, i, &me, "Choose ambient sound:");
if(i < 0) {
lg.setSelected(prev);
return false;
}
current_terrain->out_sound = i;
}
current_terrain->ambient_sound = choice;
return true;
});
out_dlg.run();
}
@@ -685,7 +703,11 @@ static bool save_advanced_town(cDialog& me, std::string, eKeyMod) {
}
town->spec_on_entry = me["onenter"].getTextAsNum();
town->spec_on_entry_if_dead = me["onenterdead"].getTextAsNum();
town->spec_on_hostile = me["onhostile"].getTextAsNum();
town->is_hidden = dynamic_cast<cLed&>(me["hidden"]).getState() != led_off;
town->defy_mapping = dynamic_cast<cLed&>(me["nomap"]).getState() != led_off;
town->defy_scrying = dynamic_cast<cLed&>(me["noscry"]).getState() != led_off;
town->strong_barriers = dynamic_cast<cLed&>(me["barrier"]).getState() != led_off;
return true;
}
@@ -699,7 +721,28 @@ static void put_advanced_town_in_dlog(cDialog& me) {
}
me["onenter"].setTextToNum(town->spec_on_entry);
me["onenterdead"].setTextToNum(town->spec_on_entry_if_dead);
me["onhostile"].setTextToNum(town->spec_on_hostile);
dynamic_cast<cLed&>(me["hidden"]).setState(town->is_hidden ? led_red : led_off);
dynamic_cast<cLed&>(me["nomap"]).setState(town->defy_mapping ? led_red : led_off);
dynamic_cast<cLed&>(me["noscry"]).setState(town->defy_scrying ? led_red : led_off);
dynamic_cast<cLed&>(me["barrier"]).setState(town->strong_barriers ? led_red : led_off);
}
static bool edit_advanced_town_special(cDialog& me, std::string hit, eKeyMod) {
std::string fld = hit.substr(5);
short spec = me[fld].getTextAsNum();
if(spec < 0 || spec > 99) {
spec = get_fresh_spec(2);
if(spec < 0) {
giveError("You can't create a new town special encounter because there are no more free special nodes.",
"To free a special node, set its type to No Special and set its Jump To special to -1.", &me);
return true;
}
}
if(edit_spec_enc(spec,2,&me)) {
me[fld].setTextToNum(spec);
}
return true;
}
void edit_advanced_town() {
@@ -711,9 +754,11 @@ void edit_advanced_town() {
auto loc_check = std::bind(check_range_msg, _1, _2, _3, -1, 47, "The town exit coordinates", "-1 if you want them ignored");
auto spec_check = std::bind(check_range_msg, _1, _2, _3, -1, 99, _4, "-1 for no special");
town_dlg.attachFocusHandlers(std::bind(spec_check, _1, _2, _3, "The town exit special"), {"onexit1", "onexit2", "onexit3", "onexit4"});
town_dlg.attachFocusHandlers(std::bind(spec_check, _1, _2, _3, "Thw town entry special"), {"onenter", "onenterdead"});
town_dlg.attachFocusHandlers(std::bind(spec_check, _1, _2, _3, "The town entry special"), {"onenter", "onenterdead"});
town_dlg["onhostile"].attachFocusHandler(std::bind(spec_check, _1, _2, _3, "The town hostile special"));
town_dlg.attachFocusHandlers(loc_check, {"exit1-x", "exit2-x", "exit3-x", "exit4-x"});
town_dlg.attachFocusHandlers(loc_check, {"exit1-y", "exit2-y", "exit3-y", "exit4-y"});
town_dlg.attachClickHandlers(edit_advanced_town_special, {"edit-onexit1", "edit-onexit2", "edit-onexit3", "edit-onexit4", "edit-onenter", "edit-onenterdead", "edit-onhostile"});
put_advanced_town_in_dlog(town_dlg);