diff --git a/rsrc/dialogs/adventure-notes.xml b/rsrc/dialogs/adventure-notes.xml
index 16a0800a..2dea6c55 100644
--- a/rsrc/dialogs/adventure-notes.xml
+++ b/rsrc/dialogs/adventure-notes.xml
@@ -4,16 +4,22 @@
diff --git a/src/dialogxml/dialogs/3choice.cpp b/src/dialogxml/dialogs/3choice.cpp
index fe45e1df..7ca62950 100644
--- a/src/dialogxml/dialogs/3choice.cpp
+++ b/src/dialogxml/dialogs/3choice.cpp
@@ -155,6 +155,13 @@ void cThreeChoice::init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cB
me->add(btn, cur_btn_rect, sout.str());
cur_btn_rect.right = cur_btn_rect.left - 4;
}
+ // Add a record button and hide it
+ cButton* record = new cButton(*me);
+ record->setText("Record");
+ record->attachClickHandler(std::bind(&cThreeChoice::onRecord, this, _2));
+ cur_btn_rect = {buttons_top,10,buttons_top + 23,buttons_right};
+ me->add(record, cur_btn_rect, "record");
+ record->hide();
}
void cThreeChoice::init_pict(pic_num_t pic){
@@ -174,7 +181,7 @@ std::string cThreeChoice::show(){
return "**ERROR**"; // shouldn't be reached
}
-short custom_choice_dialog(std::array& strs,short pic_num,ePicType pic_type,std::array& buttons,bool anim_pict,short anim_loops, int anim_fps, cDialog* parent) {
+short custom_choice_dialog(std::array& strs,short pic_num,ePicType pic_type,std::array& buttons,bool anim_pict,short anim_loops, int anim_fps, cUniverse* univ, cDialog* parent) {
set_cursor(sword_curs);
std::vector vec(strs.begin(), strs.end());
@@ -185,6 +192,28 @@ short custom_choice_dialog(std::array& strs,short pic_num,ePicTy
if(anim_pict)
setup_dialog_pict_anim(*(customDialog.operator->()), "pict", anim_loops, anim_fps);
+ if(univ != nullptr){
+ customDialog.setRecordHandler([vec, univ](cDialog& dlg) -> void {
+ std::string combined;
+ for(std::string msg : vec){
+ if(!msg.empty()){
+ if(!combined.empty()){
+ combined += " ||";
+ }
+ combined += msg;
+ }
+ }
+ // It's not necessarily a NOTE_SCEN and location shouldn't be empty,
+ // but these things aren't actually shown to the party in the encounter notes dialog.
+ if(univ->party.record(NOTE_SCEN, combined, "")){
+ give_help(58,0,dlg);
+ // TODO ASB is only in game source, but this function is in common source so the scenario editor can preview dialogs :(
+ /*
+ add_string_to_buf("Added to encounter notes.");
+ */
+ }
+ });
+ }
std::string item_hit = customDialog.show();
for(int i = 0; i < 3; i++) {
@@ -220,5 +249,23 @@ short once_dialog(cUniverse& univ, cSpecial& spec, eSpecCtxType cur_type, cDialo
showError("Dialog box ended up with no buttons.");
return -1;
}
- return custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c, parent);
+ return custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c, &univ, parent);
+}
+
+cThreeChoice& cThreeChoice::setRecordHandler(record_callback_t rec){
+ if(rec == nullptr){
+ hasRecord = false;
+ dlg["record"].hide();
+ }else{
+ hasRecord = true;
+ rec_f = rec;
+ dlg["record"].show();
+ }
+ return *this;
+}
+
+bool cThreeChoice::onRecord(std::string id){
+ if(hasRecord) rec_f(dlg);
+ else dlg[id].hide();
+ return hasRecord;
}
\ No newline at end of file
diff --git a/src/dialogxml/dialogs/3choice.hpp b/src/dialogxml/dialogs/3choice.hpp
index 281222be..612b8c7d 100644
--- a/src/dialogxml/dialogs/3choice.hpp
+++ b/src/dialogxml/dialogs/3choice.hpp
@@ -37,6 +37,9 @@ namespace {cBasicButtonType null_btn = boost::none;}
extern bbtt basic_buttons[71];
#endif
+/// The signature of a record handler for cThreeChoice.
+typedef std::function record_callback_t;
+
/// A choice dialog with several strings and up to three buttons.
/// This is the class used for dialogs generated by special nodes.
/// It generates the dialog dynamically from the given input.
@@ -48,6 +51,9 @@ class cThreeChoice : public cChoiceDlog {
void init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cBasicButtonType btn3);
void init_pict(pic_num_t pic);
const ePicType type;
+ record_callback_t rec_f;
+ bool hasRecord;
+ bool onRecord(std::string id);
public:
/// Create a dialog with just one button.
/// @param strings A list of the strings to place in the dialog.
@@ -70,12 +76,21 @@ public:
/// @param t The type of the icon.
/// @param parent Optionally, a parent dialog.
cThreeChoice(std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent = nullptr);
+ /// Set a record handler.
+ /// @param rec The handler.
+ /// @return This object, for method-call chaining.
+ /// @note Only one record handler can be set at a time. To remove it, set it to null.
+ /// @note The presence of the Record button is determined entirely by the presence of a record handler.
+ ///
+ /// A record handler should take one parameter, which is a reference to the dialog.
+ /// (That's the cDialog, not the cThreeChoice.) It should return void.
+ cThreeChoice& setRecordHandler(record_callback_t rec);
/// @copydoc cChoiceDlog::show()
/// @note The unique key in this case is the label specified in the button specification.
std::string show();
};
-short custom_choice_dialog(std::array& strs,short pic_num,ePicType pic_type,std::array& buttons, bool anim_pict = false, short anim_loops = -1, int anim_fps = -1, cDialog* parent = nullptr);
+short custom_choice_dialog(std::array& strs,short pic_num,ePicType pic_type,std::array& buttons, bool anim_pict = false, short anim_loops = -1, int anim_fps = -1, cUniverse* univ = nullptr, cDialog* parent = nullptr);
short once_dialog(cUniverse& univ, cSpecial& spec, eSpecCtxType cur_type, cDialog* parent = nullptr);
#endif
diff --git a/src/dialogxml/dialogs/choicedlog.hpp b/src/dialogxml/dialogs/choicedlog.hpp
index 318cca91..37e60c42 100644
--- a/src/dialogxml/dialogs/choicedlog.hpp
+++ b/src/dialogxml/dialogs/choicedlog.hpp
@@ -17,8 +17,8 @@
/// This class loads a definition from a file, so there can be any amount of other stuff in the dialog,
/// and the buttons could be arranged in any fashion you want.
class cChoiceDlog {
- cDialog dlg;
protected:
+ cDialog dlg;
/// The click handler for the dialog's buttons.
/// @param me A reference to the current dialog.
/// @param id The unique key of the clicked control.
diff --git a/src/game/boe.infodlg.cpp b/src/game/boe.infodlg.cpp
index 3acd03a1..008bf740 100644
--- a/src/game/boe.infodlg.cpp
+++ b/src/game/boe.infodlg.cpp
@@ -512,10 +512,14 @@ static bool adventure_notes_event_filter(cDialog& me, std::string item_hit, eKey
std::string n = boost::lexical_cast(i + 1);
if(univ.party.special_notes.size() > store_page_on * 3+i) {
me["str" + n].setText(univ.party.special_notes[store_page_on * 3+i].the_str);
+ me["str" + n].recalcRect();
+ me["pane" + n].recalcRect();
me["del" + n].show();
}
else {
me["str" + n].setText("");
+ me["str" + n].recalcRect();
+ me["pane" + n].recalcRect();
me["del" + n].hide();
}
}
@@ -544,6 +548,8 @@ void adventure_notes() {
std::string n = boost::lexical_cast(i + 1);
if(univ.party.special_notes.size() > i) {
encNotes["str" + n].setText(univ.party.special_notes[i].the_str);
+ encNotes["str" + n].recalcRect();
+ encNotes["pane" + n].recalcRect();
encNotes["del" + n].show();
}
else encNotes["del" + n].hide();
diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp
index 97036a6e..32b8aaaf 100644
--- a/src/game/boe.specials.cpp
+++ b/src/game/boe.specials.cpp
@@ -2637,7 +2637,7 @@ void oneshot_spec(const runtime_state& ctx) {
univ.get_strs(strs, ctx.cur_spec_type, spec.m1);
// Leave / Take
buttons[0] = 9; buttons[1] = 19;
- dlg_res = custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c);
+ dlg_res = custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c, &univ);
if(dlg_res == 1) {set_sd = false; ctx.next_spec = -1;}
else {
store_i = univ.scenario.get_stored_item(spec.ex1a);
@@ -2677,7 +2677,7 @@ void oneshot_spec(const runtime_state& ctx) {
if((spec.m1 >= 0) || (spec.m2 >= 0)) {
univ.get_strs(strs[0],strs[1], ctx.cur_spec_type, spec.m1, spec.m2);
buttons[0] = 3; buttons[1] = 2;
- dlg_res = custom_choice_dialog(strs,spec.pic,ePicType(spec.pictype),buttons, true, spec.ex1c, spec.ex2c);
+ dlg_res = custom_choice_dialog(strs,spec.pic,ePicType(spec.pictype),buttons, true, spec.ex1c, spec.ex2c, &univ);
// TODO: Make custom_choice_dialog return string?
}
else dlg_res = cChoiceDlog("basic-trap",{"yes","no"}).show() == "no";
@@ -4006,7 +4006,7 @@ void townmode_spec(const runtime_state& ctx) {
else {
univ.get_strs(strs,ctx.cur_spec_type, spec.m1);
buttons[0] = 9; buttons[1] = 35;
- if(custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c) == 1)
+ if(custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c, &univ) == 1)
ctx.next_spec = -1;
else {
int x = univ.party.get_ptr(10), y = univ.party.get_ptr(11);
@@ -4037,7 +4037,7 @@ void townmode_spec(const runtime_state& ctx) {
else {
univ.get_strs(strs, ctx.cur_spec_type,spec.m1);
buttons[0] = 9; buttons[1] = 8;
- if(custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c) == 1) {
+ if(custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, true, spec.ex1c, spec.ex2c, &univ) == 1) {
ctx.next_spec = -1;
if(ctx.which_mode == eSpecCtx::OUT_MOVE || ctx.which_mode == eSpecCtx::TOWN_MOVE || ctx.which_mode == eSpecCtx::COMBAT_MOVE)
*ctx.ret_a = 1;
@@ -4069,7 +4069,7 @@ void townmode_spec(const runtime_state& ctx) {
else {
univ.get_strs(strs,ctx.cur_spec_type, spec.m1);
buttons[0] = 20; buttons[1] = 24;
- int i = spec.ex2b == 1 ? 2 : custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons);
+ int i = spec.ex2b == 1 ? 2 : custom_choice_dialog(strs, spec.pic, ePicType(spec.pictype), buttons, false, -1, -1, &univ);
*ctx.ret_a = 1;
if(i == 1) {
ctx.next_spec = -1;