Give item: more sensible button selection

This commit is contained in:
2025-03-19 20:22:23 -05:00
parent 85baeb454c
commit 1a85fc25ae
2 changed files with 66 additions and 31 deletions

View File

@@ -181,23 +181,27 @@ bool place_item(cItem item,location where,bool contained) {
return univ.town.items.back().contained; return univ.town.items.back().contained;
} }
cItem item_store;
void give_thing(short pc_num, short item_num) { void give_thing(short pc_num, short item_num) {
short who_to,how_many = 0; short who_to,how_many = 0;
cItem item_store;
bool take_given_item = true; bool take_given_item = true;
if(univ.party[pc_num].equip[item_num] && univ.party[pc_num].items[item_num].cursed) if(univ.party[pc_num].equip[item_num] && univ.party[pc_num].items[item_num].cursed)
add_string_to_buf("Give: Item is cursed."); add_string_to_buf("Give: Item is cursed.");
else { else {
item_store = univ.party[pc_num].items[item_num]; item_store = univ.party[pc_num].items[item_num];
who_to = select_pc(eSelectPC::ONLY_LIVING_WITH_ITEM_SLOT,"Give item to who?"); who_to = select_pc(eSelectPC::ONLY_CAN_GIVE_FROM_ACTIVE,"Give item to who?");
if((overall_mode == MODE_COMBAT) && !adjacent(univ.party[pc_num].combat_pos,univ.party[who_to].combat_pos)) { // No party members can receive the item:
add_string_to_buf("Give: Must be adjacent."); if(who_to == 8){
who_to = 6; if(overall_mode == MODE_COMBAT){
ASB("Can't give: must be adjacent with enough carrying capacity.", 2);
}else{
ASB("Can't give: no one has the carrying capacity.", 2);
}
} }
if((who_to < 6) && (who_to != pc_num) if((who_to < 6) && (who_to != pc_num)) {
&& ((overall_mode != MODE_COMBAT) || (adjacent(univ.party[pc_num].combat_pos,univ.party[who_to].combat_pos)))) {
if((item_store.type_flag > 0) && (item_store.charges > 1)) { if((item_store.type_flag > 0) && (item_store.charges > 1)) {
how_many = get_num_of_items(item_store.charges); how_many = get_num_of_items(item_store.charges);
if(how_many == 0) if(how_many == 0)
@@ -208,23 +212,10 @@ void give_thing(short pc_num, short item_num) {
item_store.charges = how_many; item_store.charges = how_many;
} }
eBuyStatus give_status = univ.party[who_to].give_item(item_store,0); eBuyStatus give_status = univ.party[who_to].give_item(item_store,0);
switch(give_status){ if(give_status != eBuyStatus::OK){
case eBuyStatus::OK: // This should be impossible, because select_pc() already checked that the options
if(take_given_item){ // were viable.
univ.party[pc_num].take_item(item_num); showFatalError("Unexpectedly failed to give item!");
}
break;
case eBuyStatus::NO_SPACE:
ASB("Can't give: PC has max. # of items.");
if(false) // Skip first line of fallthrough
case eBuyStatus::TOO_HEAVY:
ASB("Can't give: PC carrying too much.");
// Can't give to the recipient. Put charges back in giver's inventory:
if(how_many > 0)
univ.party[pc_num].items[item_num].charges += how_many;
break;
default:
break;
} }
} }
} }
@@ -941,15 +932,44 @@ short select_pc(eSelectPC mode, std::string title, bool allow_choose_all) {
if(!title.empty()) if(!title.empty())
selectPc["title"].setText(title); selectPc["title"].setText(title);
bool any_options = false;
for(short i = 0; i < 6; i++) { for(short i = 0; i < 6; i++) {
std::string n = boost::lexical_cast<std::string>(i + 1); std::string n = boost::lexical_cast<std::string>(i + 1);
bool can_pick = true; bool can_pick = true;
std::string disabled_reason = "";
if(univ.party[i].main_status == eMainStatus::ABSENT || univ.party[i].main_status == eMainStatus::FLED) if(univ.party[i].main_status == eMainStatus::ABSENT || univ.party[i].main_status == eMainStatus::FLED)
can_pick = false; can_pick = false;
else switch(mode) { else switch(mode) {
case eSelectPC::ONLY_LIVING_WITH_ITEM_SLOT: case eSelectPC::ONLY_CAN_GIVE_FROM_ACTIVE:
if(!univ.party[i].has_space()) if(i == univ.cur_pc){
can_pick = false; can_pick = false;
break;
}
if((overall_mode == MODE_COMBAT) && !adjacent(univ.party[univ.cur_pc].combat_pos,univ.party[i].combat_pos)) {
can_pick = false;
disabled_reason = "too far away";
break;
}
BOOST_FALLTHROUGH;
case eSelectPC::ONLY_CAN_GIVE:
switch(univ.party[i].can_give_item(item_store)){
case eBuyStatus::TOO_HEAVY:
disabled_reason = "item too heavy";
if(false) // skip first line of fallthrough
case eBuyStatus::NO_SPACE:
disabled_reason = "no item slot";
can_pick = false;
break;
default:
break;
}
break;
case eSelectPC::ONLY_LIVING_WITH_ITEM_SLOT:
if(!univ.party[i].has_space()){
can_pick = false;
disabled_reason = "no item slot";
}
BOOST_FALLTHROUGH; BOOST_FALLTHROUGH;
case eSelectPC::ONLY_LIVING: case eSelectPC::ONLY_LIVING:
if(univ.party[i].main_status != eMainStatus::ALIVE) if(univ.party[i].main_status != eMainStatus::ALIVE)
@@ -963,14 +983,22 @@ short select_pc(eSelectPC mode, std::string title, bool allow_choose_all) {
default: default:
break; break;
} }
selectPc["pc" + n].setText(univ.party[i].name);
if(!can_pick) { if(!can_pick) {
selectPc["pick" + n].hide(); selectPc["pick" + n].hide();
selectPc["pc" + n].hide(); if(disabled_reason.empty())
selectPc["pc" + n].hide();
else
selectPc["pc" + n].appendText(": " + disabled_reason);
} else { } else {
selectPc["pc" + n].setText(univ.party[i].name); any_options = true;
} }
} }
if(!any_options){
return 8;
}
if(!allow_choose_all){ if(!allow_choose_all){
selectPc["pick-all"].hide(); selectPc["pick-all"].hide();
selectPc["all"].hide(); selectPc["all"].hide();

View File

@@ -42,10 +42,17 @@ std::string get_text_response(std::string prompt = "", pic_num_t pic = 16);
short get_num_response(short min, short max, std::string prompt, std::vector<std::string> choice_names = {}, boost::optional<short> cancel_value = boost::none); short get_num_response(short min, short max, std::string prompt, std::vector<std::string> choice_names = {}, boost::optional<short> cancel_value = boost::none);
enum class eSelectPC { enum class eSelectPC {
ONLY_LIVING,
ANY, ANY,
ONLY_LIVING,
ONLY_LIVING_WITH_ITEM_SLOT,
// Slightly different from the previous: this now checks not just for a slot,
// but also for carrying capacity, and will stack charges even if all slots are full.
// When you use this, you have to set the global item_store to your item, first.
ONLY_CAN_GIVE,
// Same as the previous, but in combat, only show *adjacent* living PCs who can take the item.
ONLY_CAN_GIVE_FROM_ACTIVE,
ONLY_DEAD, ONLY_DEAD,
ONLY_LIVING_WITH_ITEM_SLOT
}; };
// Prompt the player to choose a party member. Returns 0-5 for a pc, 6 for cancel, or 7 for all. // Prompt the player to choose a party member. Returns 0-5 for a pc, 6 for cancel, 7 for all, or 8 if no PCs fit the mode's filter.
// Pass a string poiner to no_choice_reason to get the reason why no choices were available, if none are.
short select_pc(eSelectPC mode, std::string title="", bool allow_choose_all = false); short select_pc(eSelectPC mode, std::string title="", bool allow_choose_all = false);