Don't display 'no item' response if another PC can shop. (#679)

These are the rules:

- If the active PC gets an empty shop, iterate from the first to last PC until finding someone who can see a shop item
    - If none can shop, show the 'no item' response
- When the active PC buys something, if this clears out the shop, iterate from the first to last PC until finding someone who can see a shop item
    - if none can see an item, stay on the empty shop of the PC that was active when the last item was bought.
- When shopping ends, if the shop interface was the last thing to change the player's active PC, it puts it back how it was.

Fix #669
This commit is contained in:
2025-03-06 20:26:25 -06:00
committed by GitHub
parent 14c36ed5a8
commit 9ca2f05c0b
3 changed files with 62 additions and 10 deletions

View File

@@ -895,6 +895,14 @@ void handle_switch_pc(short which_pc, bool& need_redraw, bool& need_reprint) {
add_string_to_buf("Set active: PC must be here & active.");
else {
univ.cur_pc = which_pc;
// The shop interface may have taken control of the active PC. If the player
// manually sets active PC before shopping ends, don't restore the active PC from before
// shopping switched it. Unless the player buys something again, forcing it to store again.
extern short store_cur_pc;
if(store_cur_pc != -1)
store_cur_pc = -1;
set_stat_window_for_pc(which_pc);
add_string_to_buf("Now " + std::string(overall_mode == MODE_SHOPPING ? "shopping" : "active") + ": " + pc.name);
adjust_spell_menus();

View File

@@ -98,8 +98,38 @@ std::vector<int> shop_array;
cShop active_shop;
short active_shop_num;
short store_cur_pc = -1;
bool start_shop_mode(short which,short cost_adj,std::string store_name, bool cancel_when_empty) {
// For healing shops, other PCs might be able to buy something if
// the active PC can't
bool start_shop_mode_other_pc(bool allow_empty = false) {
// The shop might change the current PC multiple times, but we want to restore
// it to the original active PC when shopping ends, so only store if we're
// not yet storing
if(store_cur_pc == -1)
store_cur_pc = univ.cur_pc;
// But I actually want to store the PC that's active now, so if no one can buy anything but
// we want to leave an empty shop, we can leave the PC selection where it is.
short pc_buying = univ.cur_pc;
bool other_pc_can_buy = false;
for(int i = 0; i < 6; ++i){
if(univ.party[i].main_status != eMainStatus::ABSENT){
univ.cur_pc = i;
if(start_shop_mode(active_shop_num,active_shop.getCostAdjust(),save_talk_str1,true,true)){
other_pc_can_buy = true;
break;
}
}
}
if(!other_pc_can_buy && allow_empty){
start_shop_mode(active_shop_num,active_shop.getCostAdjust(),save_talk_str1,false,true);
}
return other_pc_can_buy;
}
bool start_shop_mode(short which,short cost_adj,std::string store_name, bool cancel_when_empty, bool already_started) {
rectangle area_rect;
if(which < 0 || which >= univ.scenario.shops.size()) {
showError("The scenario tried to place you in a nonexistent shop!");
@@ -138,7 +168,8 @@ bool start_shop_mode(short which,short cost_adj,std::string store_name, bool can
area_rect = talk_area_rect;
talk_gworld().create(area_rect.width(), area_rect.height());
store_pre_shop_mode = overall_mode;
if(!already_started)
store_pre_shop_mode = overall_mode;
overall_mode = MODE_SHOPPING;
stat_screen_mode = MODE_SHOP;
shop_sbar->setPosition(0);
@@ -167,6 +198,11 @@ void end_shop_mode() {
record_action("end_shop_mode", "");
}
if(store_cur_pc >= 0){
univ.cur_pc = store_cur_pc;
store_cur_pc = -1;
}
rectangle dummy_rect = {0,0,0,0};
// This would be a place to show the text box, if I add it (and if this is not an outdoor shop).
@@ -427,8 +463,12 @@ void handle_sale(int i) {
// This looks to be redundant, but I'm just preserving the previous behavior of the code.
set_up_shop_array();
draw_shop_graphics(false,false,{});
}
// When buying from a healer, we want to select the next PC who needs healing
if(shop_array.empty()){
start_shop_mode_other_pc(true);
}
}
void handle_info_request(int what_picked) {
if(recording){
@@ -899,12 +939,16 @@ void handle_talk_node(int which_talk_entry) {
case eTalkNode::SHOP:
if(!start_shop_mode(b,a,save_talk_str1,true)){
// Second string of shop talk node: Custom message for when shop is empty
if(!save_talk_str2.empty()){
save_talk_str1 = save_talk_str2;
save_talk_str2 = "";
}else{
save_talk_str1 = "There is nothing available to buy.";
if(!start_shop_mode_other_pc()){
univ.cur_pc = store_cur_pc;
// Second string of shop talk node: Custom message for when shop is empty
if(!save_talk_str2.empty()){
save_talk_str1 = save_talk_str2;
save_talk_str2 = "";
}else{
save_talk_str1 = "There is nothing available to buy.";
}
}
}else{
can_save_talk = false;

View File

@@ -5,7 +5,7 @@
#include "dialogxml/dialogs/dialog.hpp"
#include "scenario/shop.hpp"
bool start_shop_mode(short which,short cost_adj,std::string store_name, bool cancel_when_empty = false);
bool start_shop_mode(short which,short cost_adj,std::string store_name, bool cancel_when_empty = false, bool already_started = false);
void end_shop_mode();
bool handle_shop_event(location p, cFramerateLimiter& fps_limiter);
void handle_sale(int i);