diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index 71c53c02b..ee5e3f912 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -920,7 +920,7 @@ void handle_switch_pc_items(short which_pc, bool& need_redraw) { set_stat_window_for_pc(which_pc); if(overall_mode == MODE_SHOPPING) { set_up_shop_array(); - draw_shop_graphics(0,item_screen_button_rects[which_pc]); // rect is dummy + draw_shop_graphics(false,false,item_screen_button_rects[which_pc]); // rect is dummy } } } @@ -1623,7 +1623,7 @@ bool handle_action(const sf::Event& event, cFramerateLimiter& fps_limiter) { put_item_screen(stat_window); if(overall_mode == MODE_SHOPPING) { set_up_shop_array(); - draw_shop_graphics(0,pc_buttons[0][PCBTN_NAME]); + draw_shop_graphics(false,false,pc_buttons[0][PCBTN_NAME]); } } diff --git a/src/game/boe.consts.hpp b/src/game/boe.consts.hpp index a4f3b3157..dffd510fe 100644 --- a/src/game/boe.consts.hpp +++ b/src/game/boe.consts.hpp @@ -164,6 +164,8 @@ const int UI_LAYER_MENUBAR = 1200; const int talk_gword_offset_x = 19; const int talk_gword_offset_y = 7; +const int TALK_WORD_SIZE = 18; + #ifdef __APPLE__ enum eMenuChoice { MENU_CHOICE_NONE, diff --git a/src/game/boe.dlgutil.cpp b/src/game/boe.dlgutil.cpp index bf0690efe..efcf8e809 100644 --- a/src/game/boe.dlgutil.cpp +++ b/src/game/boe.dlgutil.cpp @@ -149,7 +149,7 @@ bool start_shop_mode(short which,short cost_adj,std::string store_name, bool can put_background(); - draw_shop_graphics(0,area_rect); + draw_shop_graphics(false,false,area_rect); put_item_screen(stat_window); give_help(26,27); @@ -177,12 +177,13 @@ void end_shop_mode() { shop_sbar->hide(); done_btn->hide(); - help_btn->hide(); if(store_pre_shop_mode == MODE_TALKING) { save_talk_str1 = "You conclude your business."; save_talk_str2 = ""; place_talk_str(save_talk_str1, save_talk_str2, 0, dummy_rect); update_last_talk(TALK_BUSINESS); + }else{ + help_btn->hide(); } overall_mode = store_pre_shop_mode; @@ -243,22 +244,25 @@ bool handle_shop_event(location p, cFramerateLimiter& fps_limiter) { // Since shop UI was drawn into the game window with offsets, we need to apply // the same offsets to event catching areas. rectangle active_rect { shopping_rects[i][SHOPRECT_ACTIVE_AREA] }; + rectangle visual_rect { active_rect }; + visual_rect.right += 10; active_rect.offset(talk_gword_offset_x, talk_gword_offset_y); rectangle item_help_rect { shopping_rects[i][SHOPRECT_ITEM_HELP] }; + rectangle visual_item_help_rect { item_help_rect }; item_help_rect.offset(talk_gword_offset_x, talk_gword_offset_y); if(p.in(active_rect)) { - click_shop_rect(active_rect); + click_shop_rect(visual_rect, false); handle_sale(what_picked); return true; } else if(p.in(item_help_rect)){ - click_shop_rect(item_help_rect); + click_shop_rect(visual_item_help_rect, true); handle_info_request(what_picked); return true; } } - return false; + return p.in(rectangle(talk_gworld)); } void handle_sale(int i) { @@ -419,14 +423,14 @@ void handle_sale(int i) { } // Maybe that was the last of that item, so re-init the shop array just in case. set_up_shop_array(); - draw_shop_graphics(0,dummy_rect); + draw_shop_graphics(false,false,dummy_rect); print_buf(); put_pc_screen(); put_item_screen(stat_window); // This looks to be redundant, but I'm just preserving the previous behavior of the code. set_up_shop_array(); - draw_shop_graphics(false, {}); + draw_shop_graphics(false,false,{}); } @@ -581,22 +585,32 @@ void set_up_shop_array() { static void reset_talk_words() { // first initialise talk_words here talk_words.clear(); - static const rectangle preset_rects[9] = { - rectangle{366,4,386,54}, rectangle{366,70,386,130}, rectangle{366,136,386,186}, - rectangle{389,4,409,54}, rectangle{389,70,409,120}, rectangle{389,121,409,186}, - rectangle{389,210,409,270}, rectangle{366,190,386,270}, - rectangle{343,4,363,134}, + static const std::vector preset_word_locs = { + {4, 366}, {70, 366}, {136, 366}, + {4, 389}, {70, 389}, {121, 389}, + {210, 389}, {190, 366}, + {4, 343} }; - static const char*const preset_words[9] = { + static const std::vector preset_words = { "Look", "Name", "Job", "Buy", "Sell", "Record", "Done", "Go Back", "Ask About...", }; + TextStyle style; + style.font = FONT_DUNGEON; + style.pointSize = TALK_WORD_SIZE; // Place buttons at bottom. - for(short i = 0; i < 9; i++) { - word_rect_t preset_word(preset_words[i], preset_rects[i]); + for(short i = 0; i < preset_words.size(); i++) { + std::string word = preset_words[i]; + location tl = preset_word_locs[i]; + location br = tl; + short h; + br.x += string_length(word, style, &h); + br.y += h; + rectangle rect {tl,br}; + word_rect_t preset_word(word, rect); preset_word.on = PRESET_WORD_ON; preset_word.off = PRESET_WORD_OFF; switch(i) { @@ -1143,7 +1157,7 @@ bool handle_talk_event(location p, cFramerateLimiter& fps_limiter) { break; } handle_talk_node(which_talk_entry); - return clicked_word; + return clicked_word || p.in(rectangle(talk_gworld)); } //town_num; // Will be 0 - 200 for town, 200 - 290 for outdoors diff --git a/src/game/boe.graphics.cpp b/src/game/boe.graphics.cpp index a0f2b9e5e..8c14eb8ac 100644 --- a/src/game/boe.graphics.cpp +++ b/src/game/boe.graphics.cpp @@ -521,7 +521,7 @@ void redraw_screen(int refresh) { refresh_talking(); break; case MODE_SHOPPING: - if(refresh & REFRESH_DLOG) draw_shop_graphics(0,{0,0,0,0}); + if(refresh & REFRESH_DLOG) draw_shop_graphics(false,false,{0,0,0,0}); refresh_shopping(); break; default: diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index 5b241595f..d61c23c66 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -830,11 +830,25 @@ static void replay_action(Element& action) { click_talk_rect(word_rect); handle_talk_node(word_rect.node); return; - }else if(t == "click_shop_rect"){ + } + + // Legacy action: clicking any shop button used to highlight both the info + // button and the item text (which was a bug) + else if(t == "click_shop_rect"){ rectangle rect = boost::lexical_cast(action.GetText()); click_shop_rect(rect); return; - }else if(t == "end_shop_mode"){ + } + // Fixed versions: + else if(t == "click_shop_item"){ + rectangle rect = boost::lexical_cast(action.GetText()); + click_shop_rect(rect, false); + }else if(t == "click_shop_item_help"){ + rectangle rect = boost::lexical_cast(action.GetText()); + click_shop_rect(rect, true); + } + + else if(t == "end_shop_mode"){ end_shop_mode(); return; }else if(t == "scrollbar_setPosition"){ diff --git a/src/game/boe.newgraph.cpp b/src/game/boe.newgraph.cpp index 797d71f2a..e0c66e2dd 100644 --- a/src/game/boe.newgraph.cpp +++ b/src/game/boe.newgraph.cpp @@ -599,15 +599,16 @@ void do_explosion_anim(short /*sound_num*/,short special_draw, short snd) { store_booms[i].boom_type = -1; } -void click_shop_rect(rectangle area_rect) { +void click_shop_rect(rectangle area_rect, bool item_help) { if(recording){ - record_action("click_shop_rect", boost::lexical_cast(area_rect)); + std::string action_name = item_help ? "click_shop_item_help" : "click_shop_item"; + record_action(action_name, boost::lexical_cast(area_rect)); } - draw_shop_graphics(1,area_rect); + draw_shop_graphics(!item_help,item_help,area_rect); mainPtr.display(); play_sound(37, time_in_ticks(5)); - draw_shop_graphics(0,area_rect); + draw_shop_graphics(false,false,area_rect); } @@ -627,7 +628,7 @@ graf_pos calc_item_rect(int num,rectangle& to_rect) { } // mode 1 - drawing dark for button press -void draw_shop_graphics(bool pressed,rectangle clip_area_rect) { +void draw_shop_graphics(bool item_pressed, bool item_help_pressed, rectangle clip_area_rect) { rectangle area_rect,item_info_from = {11,42,24,56}; rectangle face_rect = {6,6,38,38}; @@ -650,20 +651,24 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) { style.font = FONT_DUNGEON; style.pointSize = 18; + area_rect = rectangle(talk_gworld); talk_gworld.setActive(false); - if(pressed) { + // Only re-render on top of the item that is clicked: + if(item_pressed || item_help_pressed) { + clip_area_rect.offset(-area_rect.left, -area_rect.top); clip_rect(talk_gworld, clip_area_rect); + } else { + frame_rect(talk_gworld, area_rect, Colours::BLACK); + area_rect.inset(1,1); + tileImage(talk_gworld, area_rect,bg[12]); + + frame_rect(talk_gworld, shop_frame, Colours::BLACK); } - area_rect = rectangle(talk_gworld); - frame_rect(talk_gworld, area_rect, Colours::BLACK); - area_rect.inset(1,1); - tileImage(talk_gworld, area_rect,bg[12]); - - frame_rect(talk_gworld, shop_frame, Colours::BLACK); - - // Place store icon - if(!pressed) { + // Place store icon: + // We can skip this when rendering for a button press, but it won't matter anyway + // because button press rendering is clipped anyway. + if(!item_pressed || item_help_pressed) { rectangle from_rect = {0,0,32,32}; std::shared_ptr from_gw; int i = std::max(0, active_shop.getFace()); @@ -717,7 +722,7 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) { } win_draw_string(talk_gworld,shopper_name,title.str(),eTextMode::LEFT_TOP,style); - if(pressed) + if(item_pressed) style.colour = Colours::TITLE_BLUE; else style.colour = Colours::BLACK; @@ -779,7 +784,7 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) { rect_draw_some_item(invenbtn_gworld, {0, 29, 7, 36}, talk_gworld, cost_rect, sf::BlendAlpha); style.pointSize = 10; win_draw_string(talk_gworld,shopping_rects[i][SHOPRECT_ITEM_EXTRA],cur_info_str,eTextMode::WRAP,style); - rect_draw_some_item(invenbtn_gworld,item_info_from,talk_gworld,shopping_rects[i][SHOPRECT_ITEM_HELP],pressed ? sf::BlendNone : sf::BlendAlpha); + rect_draw_some_item(invenbtn_gworld,item_info_from,talk_gworld,shopping_rects[i][SHOPRECT_ITEM_HELP],item_help_pressed ? sf::BlendNone : sf::BlendAlpha); } // Finally, cost info and help strs @@ -801,6 +806,9 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) { shop_sbar->show(); else shop_sbar->hide(); done_btn->show(); + done_btn->draw(); + help_btn->show(); + help_btn->draw(); } void refresh_shopping() { @@ -845,6 +853,7 @@ void click_talk_rect(word_rect_t word) { style.colour = word.on; win_draw_string(mainPtr, wordRect, word.word, eTextMode::WRAP, style); place_talk_face(); + help_btn->draw(); mainPtr.display(); play_sound(37, time_in_ticks(5)); rect_draw_some_item(talk_gworld.getTexture(),talkRect,mainPtr,talk_area_rect); @@ -863,7 +872,7 @@ void place_talk_str(std::string str_to_place,std::string str_to_place2,short col TextStyle style; style.font = FONT_DUNGEON; - style.pointSize = 18; + style.pointSize = TALK_WORD_SIZE; if(c_rect.right > 0) { mainPtr.setActive(false); diff --git a/src/game/boe.newgraph.hpp b/src/game/boe.newgraph.hpp index 7b7446594..1d34e5933 100644 --- a/src/game/boe.newgraph.hpp +++ b/src/game/boe.newgraph.hpp @@ -59,8 +59,8 @@ void add_missile(location dest,miss_num_t missile_type,short path_type,short x_a void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj, bool use_unique_ran = false); void do_missile_anim(short num_steps,location missile_origin,short sound_num) ; void do_explosion_anim(short sound_num,short expand,short snd = -1); -void click_shop_rect(rectangle area_rect); -void draw_shop_graphics(bool pressed,rectangle clip_area_rect); +void click_shop_rect(rectangle area_rect, bool item_help = false); +void draw_shop_graphics(bool item_pressed, bool item_help_pressed, rectangle clip_area_rect); void refresh_shopping(); void click_talk_rect(word_rect_t word); void place_talk_str(std::string str_to_place,std::string str_to_place2,short color,rectangle c_rect);