diff --git a/rsrc/dialogs/edit-monster-abils.xml b/rsrc/dialogs/edit-monster-abils.xml index fc43356b..a1e0d517 100644 --- a/rsrc/dialogs/edit-monster-abils.xml +++ b/rsrc/dialogs/edit-monster-abils.xml @@ -37,6 +37,7 @@ Special treasure: Item to drop when killed: + Chance of dropping: (0-100) diff --git a/src/dialogxml/dialogs/strchoice.cpp b/src/dialogxml/dialogs/strchoice.cpp index f84bbe1f..be546087 100644 --- a/src/dialogxml/dialogs/strchoice.cpp +++ b/src/dialogxml/dialogs/strchoice.cpp @@ -15,9 +15,11 @@ #include #include "dialogxml/widgets/field.hpp" +#include "dialogxml/dialogs/strdlog.hpp" #include "fileio/resmgr/res_dialog.hpp" #include "sounds.hpp" #include "gfx/render_shapes.hpp" +#include "tools/cursors.hpp" const sf::Color HILITE_COLOUR = Colours::LIGHT_GREEN; @@ -310,3 +312,71 @@ void cStringChoice::savePage() { strings[string_idx] = dlg[text_id].getText(); } } + +static bool get_num_response_event_filter(cDialog& me, std::string, eKeyMod) { + if(me.toast(true)){ + me.setResult(me["number"].getTextAsNum()); + } + return true; +} + +short get_num_response(short min, short max, std::string prompt, std::vector choice_names, boost::optional cancel_value, short initial_value, std::string extra_led, bool* led_output) { + std::ostringstream sout; + sout << prompt; + + set_cursor(sword_curs); + + cDialog numPanel(*ResMgr::dialogs.get("get-num")); + numPanel.attachClickHandlers(get_num_response_event_filter, {"okay"}); + + if(extra_led.empty()){ + numPanel["extra-led"].hide(); + }else{ + numPanel["extra-led"].setText(extra_led); + numPanel["extra-led"].recalcRect(); + if(led_output != nullptr) + dynamic_cast(numPanel["extra-led"]).setState(*led_output ? led_red : led_off); + } + + sout << " (" << min << '-' << max << ')'; + numPanel["prompt"].setText(sout.str()); + numPanel["number"].setTextToNum(initial_value); + if(!choice_names.empty()){ + numPanel["choose"].attachClickHandler([&choice_names, &prompt](cDialog& me,std::string,eKeyMod) -> bool { + cStringChoice choose_dlg(choice_names, prompt, &me); + me["number"].setTextToNum(choose_dlg.show(me["number"].getTextAsNum())); + return true; + }); + }else{ + numPanel["choose"].hide(); + } + if(min < max) + numPanel["number"].attachFocusHandler([min,max](cDialog& me,std::string,bool losing) -> bool { + if(!losing) return true; + int val = me["number"].getTextAsNum(); + if(val < min || val > max) { + showError("Number out of range!"); + return false; + } + return true; + }); + + bool cancel_clicked = false; + if(cancel_value){ + numPanel["cancel"].attachClickHandler([cancel_value, &cancel_clicked](cDialog& me,std::string,eKeyMod) -> bool { + cancel_clicked = true; + me.setResult(*cancel_value); + me.toast(false); + return true; + }); + }else{ + numPanel["cancel"].hide(); + } + + numPanel.run(); + if(!cancel_clicked && led_output != nullptr){ + *led_output = dynamic_cast(numPanel["extra-led"]).getState() == led_red; + } + + return numPanel.getResult(); +} \ No newline at end of file diff --git a/src/dialogxml/dialogs/strchoice.hpp b/src/dialogxml/dialogs/strchoice.hpp index 3d48f0f0..f76d7769 100644 --- a/src/dialogxml/dialogs/strchoice.hpp +++ b/src/dialogxml/dialogs/strchoice.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "dialog.hpp" #include "dialogxml/widgets/ledgroup.hpp" @@ -78,4 +79,9 @@ public: std::vector getStrings() const { return strings; } }; +// Prompt the player/designer for a number, which might be an index in a given list of strings. +// Specify cancel_value to show a cancel button, which will return the given value (for example, -1) +// Specify extra_led and led_output to show a labeled LED which will assign led_output with its status unless the dialog is canceled +short get_num_response(short min, short max, std::string prompt, std::vector choice_names = {}, boost::optional cancel_value = boost::none, short initial_value = 0, std::string extra_led = "", bool* led_output = nullptr); + #endif diff --git a/src/game/boe.items.cpp b/src/game/boe.items.cpp index 64e621ce..4e9cc41c 100644 --- a/src/game/boe.items.cpp +++ b/src/game/boe.items.cpp @@ -854,67 +854,6 @@ std::string get_text_response(std::string prompt, pic_num_t pic) { return result; } -short get_num_response(short min, short max, std::string prompt, std::vector choice_names, boost::optional cancel_value, short initial_value, std::string extra_led, bool* led_output) { - std::ostringstream sout; - sout << prompt; - - set_cursor(sword_curs); - - cDialog numPanel(*ResMgr::dialogs.get("get-num")); - numPanel.attachClickHandlers(get_num_of_items_event_filter, {"okay"}); - - if(extra_led.empty()){ - numPanel["extra-led"].hide(); - }else{ - numPanel["extra-led"].setText(extra_led); - numPanel["extra-led"].recalcRect(); - if(led_output != nullptr) - dynamic_cast(numPanel["extra-led"]).setState(*led_output ? led_red : led_off); - } - - sout << " (" << min << '-' << max << ')'; - numPanel["prompt"].setText(sout.str()); - numPanel["number"].setTextToNum(initial_value); - if(!choice_names.empty()){ - numPanel["choose"].attachClickHandler([&choice_names, &prompt](cDialog& me,std::string,eKeyMod) -> bool { - cStringChoice choose_dlg(choice_names, prompt, &me); - me["number"].setTextToNum(choose_dlg.show(me["number"].getTextAsNum())); - return true; - }); - }else{ - numPanel["choose"].hide(); - } - if(min < max) - numPanel["number"].attachFocusHandler([min,max](cDialog& me,std::string,bool losing) -> bool { - if(!losing) return true; - int val = me["number"].getTextAsNum(); - if(val < min || val > max) { - showError("Number out of range!"); - return false; - } - return true; - }); - - bool cancel_clicked = false; - if(cancel_value){ - numPanel["cancel"].attachClickHandler([cancel_value, &cancel_clicked](cDialog& me,std::string,eKeyMod) -> bool { - cancel_clicked = true; - me.setResult(*cancel_value); - me.toast(false); - return true; - }); - }else{ - numPanel["cancel"].hide(); - } - - numPanel.run(); - if(!cancel_clicked && led_output != nullptr){ - *led_output = dynamic_cast(numPanel["extra-led"]).getState() == led_red; - } - - return numPanel.getResult(); -} - static bool select_pc_event_filter (cDialog& me, std::string item_hit, eKeyMod) { me.toast(true); if(item_hit == "pick-all"){ diff --git a/src/game/boe.items.hpp b/src/game/boe.items.hpp index f7870fe0..6a727512 100644 --- a/src/game/boe.items.hpp +++ b/src/game/boe.items.hpp @@ -35,10 +35,6 @@ void reset_item_max(); short item_val(cItem item); void place_treasure(location where,short level,short loot,short mode); std::string get_text_response(std::string prompt = "", pic_num_t pic = 16); -// Prompt the player for a number, which might be an index in a given list of strings. -// Specify cancel_value to show a cancel button, which will return the given value (for example, -1) -// Specify extra_led and led_output to show a labeled LED which will assign led_output with its status unless the dialog is canceled -short get_num_response(short min, short max, std::string prompt, std::vector choice_names = {}, boost::optional cancel_value = boost::none, short initial_value = 0, std::string extra_led = "", bool* led_output = nullptr); enum class eSelectPC { ANY, diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp index 70857a80..f40b905d 100644 --- a/src/game/boe.specials.cpp +++ b/src/game/boe.specials.cpp @@ -28,6 +28,7 @@ #include "dialogxml/dialogs/strdlog.hpp" #include "dialogxml/dialogs/choicedlog.hpp" #include "dialogxml/dialogs/3choice.hpp" +#include "dialogxml/dialogs/strchoice.hpp" #include "fileio/fileio.hpp" #include #include "spell.hpp" diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp index 69b51c6f..5a714051 100644 --- a/src/scenedit/scen.core.cpp +++ b/src/scenedit/scen.core.cpp @@ -1414,6 +1414,17 @@ cMonster edit_monst_abil(cMonster initial,short which,cDialog& parent) { cDialog monst_dlg(*ResMgr::dialogs.get("edit-monster-abils"),&parent); monst_dlg["loot-item"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, 399, "Item To Drop", "-1 for no item")); + + monst_dlg["pick-item"].attachClickHandler([](cDialog& me, std::string, eKeyMod) -> bool { + std::vector item_names; + for(cItem& item : scenario.scen_items){ + item_names.push_back(item.full_name); + } + short current = me["loot-item"].getTextAsNum(); + short i = get_num_response(0, scenario.scen_items.size()-1, "Which item?", item_names, current, current); + me["loot-item"].setTextToNum(i); + return true; + }); monst_dlg["loot-chance"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, 100, "Dropping Chance", "-1 for no item")); monst_dlg.attachClickHandlers(std::bind(edit_monst_abil_detail, _1, _2, std::ref(initial)), {"abil-edit1", "abil-edit2", "abil-edit3", "abil-edit4"}); monst_dlg.attachClickHandlers(std::bind(edit_monst_abil_event_filter, _1, _2, std::ref(initial)), {"okay", "cancel", "abil-up", "abil-down", "edit-see", "pick-snd"});