Make cPlayer::give_item() return the reason for failure

This commit is contained in:
2025-03-19 18:38:25 -05:00
parent 599f1030f2
commit c63bbd96dc
8 changed files with 42 additions and 34 deletions

View File

@@ -2033,7 +2033,7 @@ void debug_give_item() {
if(i == -1) return; if(i == -1) return;
bool was_ident = univ.scenario.scen_items[i].ident; bool was_ident = univ.scenario.scen_items[i].ident;
univ.scenario.scen_items[i].ident = true; univ.scenario.scen_items[i].ident = true;
bool given = univ.current_pc().give_item(univ.scenario.scen_items[i], GIVE_DO_PRINT | GIVE_ALLOW_OVERLOAD); bool given = univ.current_pc().give_item(univ.scenario.scen_items[i], GIVE_DO_PRINT | GIVE_ALLOW_OVERLOAD) == eBuyStatus::OK;
if(!given){ if(!given){
ASB("Debug: can't give to " + univ.current_pc().name); ASB("Debug: can't give to " + univ.current_pc().name);
given = univ.party.give_item(univ.scenario.scen_items[i], GIVE_DO_PRINT | GIVE_ALLOW_OVERLOAD); given = univ.party.give_item(univ.scenario.scen_items[i], GIVE_DO_PRINT | GIVE_ALLOW_OVERLOAD);
@@ -2055,7 +2055,7 @@ void debug_overburden() {
cPlayer& pc = univ.current_pc(); cPlayer& pc = univ.current_pc();
cItem item(ITEM_DEBUG_HEAVY); cItem item(ITEM_DEBUG_HEAVY);
// Give the PC very heavy objects that do nothing: // Give the PC very heavy objects that do nothing:
while(pc.give_item(item, GIVE_ALLOW_OVERLOAD)){} while(pc.give_item(item, GIVE_ALLOW_OVERLOAD) == eBuyStatus::OK){}
if(pc.has_space()){ if(pc.has_space()){
// I don't know why this would ever happen, since the weight is 0, but just in case: // I don't know why this would ever happen, since the weight is 0, but just in case:
ASB("Debug: failed to fill " + pc.name + "'s inventory."); ASB("Debug: failed to fill " + pc.name + "'s inventory.");

View File

@@ -207,17 +207,24 @@ void give_thing(short pc_num, short item_num) {
univ.party[pc_num].items[item_num].charges -= how_many; univ.party[pc_num].items[item_num].charges -= how_many;
item_store.charges = how_many; item_store.charges = how_many;
} }
if(univ.party[who_to].give_item(item_store,0)) { eBuyStatus give_status = univ.party[who_to].give_item(item_store,0);
if(take_given_item) switch(give_status){
univ.party[pc_num].take_item(item_num); case eBuyStatus::OK:
} if(take_given_item){
else { univ.party[pc_num].take_item(item_num);
if(!univ.party[who_to].has_space()) }
break;
case eBuyStatus::NO_SPACE:
ASB("Can't give: PC has max. # of items."); ASB("Can't give: PC has max. # of items.");
else ASB("Can't give: PC carrying too much."); if(false) // Skip first line of fallthrough
// Can't give to the recipient. Put charges back in giver's inventory: case eBuyStatus::TOO_HEAVY:
if(how_many > 0) ASB("Can't give: PC carrying too much.");
univ.party[pc_num].items[item_num].charges += how_many; // 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;
} }
} }
} }

View File

@@ -2166,7 +2166,7 @@ void do_alchemy() {
cItem store_i(potion); cItem store_i(potion);
store_i.charges = info.charges(skill); store_i.charges = info.charges(skill);
store_i.graphic_num += get_ran(1,0,2); store_i.graphic_num += get_ran(1,0,2);
if(!univ.party[pc_num].give_item(store_i,false)) { if(univ.party[pc_num].give_item(store_i,false) != eBuyStatus::OK) {
add_string_to_buf("No room in inventory. Potion placed on floor.", 2); add_string_to_buf("No room in inventory. Potion placed on floor.", 2);
place_item(store_i,univ.party.town_loc); place_item(store_i,univ.party.town_loc);
} }

View File

@@ -3275,7 +3275,7 @@ void affect_spec(const runtime_state& ctx) {
bool success = true; bool success = true;
for(short i = 0; i < 6; i++) for(short i = 0; i < 6; i++)
if(pc_num == 6 || pc_num == i) if(pc_num == 6 || pc_num == i)
success = success && univ.party[i].give_item(to_give, equip_type | GIVE_ALLOW_OVERLOAD); success = success && univ.party[i].give_item(to_give, equip_type | GIVE_ALLOW_OVERLOAD) == eBuyStatus::OK;
if(!success) if(!success)
ctx.next_spec = spec.pic; ctx.next_spec = spec.pic;
} }

View File

@@ -419,7 +419,7 @@ void handle_menu_choice(eMenu item_hit) {
if(choice < all_items.size()) { if(choice < all_items.size()) {
cItem store_i = all_items[choice]; cItem store_i = all_items[choice];
store_i.ident = true; store_i.ident = true;
if(!univ.party[current_active_pc].give_item(store_i,GIVE_ALLOW_OVERLOAD)) if(univ.party[current_active_pc].give_item(store_i,GIVE_ALLOW_OVERLOAD) != eBuyStatus::OK)
showError("Sorry, that PC has no free inventory slots left! You'll have to either drop something or give it to a different PC."); showError("Sorry, that PC has no free inventory slots left! You'll have to either drop something or give it to a different PC.");
else redraw_screen(); else redraw_screen();
} }

View File

@@ -581,7 +581,7 @@ int cParty::calc_day() const {
bool cParty::give_item(cItem item,int flags) { bool cParty::give_item(cItem item,int flags) {
for(int i = 0; i < 6; i++) { for(int i = 0; i < 6; i++) {
if(adven[i]->give_item(item,flags)) if(adven[i]->give_item(item,flags) == eBuyStatus::OK)
return true; return true;
} }
return false; return false;

View File

@@ -440,9 +440,9 @@ void cPlayer::sort_items() {
} }
} }
bool cPlayer::give_item(cItem item, int flags) { eBuyStatus cPlayer::give_item(cItem item, int flags) {
if(main_status != eMainStatus::ALIVE) if(main_status != eMainStatus::ALIVE)
return false; return eBuyStatus::NO_SPACE;
bool do_print = flags & GIVE_DO_PRINT; bool do_print = flags & GIVE_DO_PRINT;
bool allow_overload = flags & GIVE_ALLOW_OVERLOAD; bool allow_overload = flags & GIVE_ALLOW_OVERLOAD;
@@ -454,49 +454,47 @@ bool cPlayer::give_item(cItem item, int flags) {
if(check_only) do_print = false; if(check_only) do_print = false;
if(item.variety == eItemType::NO_ITEM) if(item.variety == eItemType::NO_ITEM)
return true; return eBuyStatus::OK;
if(item.variety == eItemType::GOLD) { if(item.variety == eItemType::GOLD) {
if(!party) return false; if(!party) return eBuyStatus::NO_SPACE;
if(!check_only) if(!check_only)
party->gold += item.item_level; party->gold += item.item_level;
if(do_print && print_result) if(do_print && print_result)
print_result("You get some gold."); print_result("You get some gold.");
return true; return eBuyStatus::OK;
} }
if(item.variety == eItemType::FOOD) { if(item.variety == eItemType::FOOD) {
if(!party) return false; if(!party) return eBuyStatus::NO_SPACE;
if(!check_only) if(!check_only)
party->food += item.item_level; party->food += item.item_level;
if(do_print && print_result) if(do_print && print_result)
print_result("You get some food."); print_result("You get some food.");
return true; return eBuyStatus::OK;
} }
if(item.variety == eItemType::SPECIAL) { if(item.variety == eItemType::SPECIAL) {
if(!party) return false; if(!party) return eBuyStatus::NO_SPACE;
if(!check_only) if(!check_only)
party->spec_items.insert(item.item_level); party->spec_items.insert(item.item_level);
if(do_print && print_result) if(do_print && print_result)
print_result("You get a special item."); print_result("You get a special item.");
return true; return eBuyStatus::OK;
} }
if(item.variety == eItemType::QUEST) { if(item.variety == eItemType::QUEST) {
if(!party) return false; if(!party) return eBuyStatus::NO_SPACE;
if(!check_only) if(!check_only)
party->active_quests[item.item_level] = cJob(party->calc_day()); party->active_quests[item.item_level] = cJob(party->calc_day());
if(do_print && print_result) if(do_print && print_result)
print_result("You get a quest."); print_result("You get a quest.");
return true; return eBuyStatus::OK;
} }
if(!allow_overload && item.item_weight() > free_weight()) { if(!allow_overload && item.item_weight() > free_weight()) {
if(do_print && print_result) { if(do_print && print_result) {
play_sound(41); play_sound(41);
print_result("Item too heavy to carry."); print_result("Item too heavy to carry.");
} }
return false; return eBuyStatus::TOO_HEAVY;
} }
if(main_status != eMainStatus::ALIVE) return false;
cInvenSlot real_free_space = has_space(); cInvenSlot real_free_space = has_space();
cInvenSlot extra_space = cInvenSlot(*this, INVENTORY_SIZE); cInvenSlot extra_space = cInvenSlot(*this, INVENTORY_SIZE);
@@ -513,7 +511,7 @@ bool cPlayer::give_item(cItem item, int flags) {
cInvenSlot free_space = *space_ptr; cInvenSlot free_space = *space_ptr;
if(free_space) { if(free_space) {
if(check_only) return true; if(check_only) return eBuyStatus::OK;
item.property = false; item.property = false;
item.contained = false; item.contained = false;
@@ -576,9 +574,9 @@ bool cPlayer::give_item(cItem item, int flags) {
combine_things(); combine_things();
sort_items(); sort_items();
return true; return eBuyStatus::OK;
} }
return false; return eBuyStatus::NO_SPACE;
} }
bool cPlayer::equip_item(int which_item, bool do_print) { bool cPlayer::equip_item(int which_item, bool do_print) {

View File

@@ -28,6 +28,7 @@ namespace legacy { struct pc_record_type; };
static struct no_party_t {} no_party; static struct no_party_t {} no_party;
// This enum is now also used in the context of giving items
enum class eBuyStatus {OK, NO_SPACE, NEED_GOLD, TOO_HEAVY, HAVE_LOTS}; enum class eBuyStatus {OK, NO_SPACE, NEED_GOLD, TOO_HEAVY, HAVE_LOTS};
enum ePartyPreset {PARTY_BLANK, PARTY_DEFAULT, PARTY_DEBUG}; enum ePartyPreset {PARTY_BLANK, PARTY_DEFAULT, PARTY_DEBUG};
@@ -150,7 +151,9 @@ public:
bool combine_things(bool check_only = false); bool combine_things(bool check_only = false);
void sort_items(); void sort_items();
bool give_item(cItem item, int flags); // Possible results of give_item are a subset of eBuyStatus, and shop code calls this function,
// so reuse the enum
eBuyStatus give_item(cItem item, int flags);
bool equip_item(int which_item, bool do_print); bool equip_item(int which_item, bool do_print);
bool unequip_item(int which_item, bool do_print); bool unequip_item(int which_item, bool do_print);
std::pair<cInvenSlot, cInvenSlot> get_weapons(); std::pair<cInvenSlot, cInvenSlot> get_weapons();