diff --git a/rsrc/dialogs/preferences.xml b/rsrc/dialogs/preferences.xml
index 8b96f093..89537bee 100644
--- a/rsrc/dialogs/preferences.xml
+++ b/rsrc/dialogs/preferences.xml
@@ -22,23 +22,25 @@
Slow
Quite Slow
+
For older machines:
-
- No graphics frills (lose special effects)
-
+ No graphics frills (lose special effects)
Turn off terrain animation
Turn of frills on shore
- Don't Save Maps
No Sounds
+ Skip splash screen on startup
+
Show room descriptions more than once
Never show instant help
Reset instant help (all help windows will reappear)
+
Make game easier (monsters much weaker)
Fewer wandering monsters
- Skip splash screen on startup
- Scale UI:
+ Show the junk bag
+
+ Scale UI:
1
1.5
diff --git a/rsrc/dialogs/select-pc-with-bag.xml b/rsrc/dialogs/select-pc-with-bag.xml
new file mode 100644
index 00000000..6b35f739
--- /dev/null
+++ b/rsrc/dialogs/select-pc-with-bag.xml
@@ -0,0 +1,22 @@
+
+
+
diff --git a/rsrc/dialogs/select-pc.xml b/rsrc/dialogs/select-pc.xml
index 202ebf45..bdf116f5 100644
--- a/rsrc/dialogs/select-pc.xml
+++ b/rsrc/dialogs/select-pc.xml
@@ -1,7 +1,7 @@
diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp
index ab61765c..329164df 100644
--- a/src/game/boe.actions.cpp
+++ b/src/game/boe.actions.cpp
@@ -820,8 +820,7 @@ static void handle_drop_item(short item_hit, bool& need_redraw) {
static void handle_item_shop_action(short item_hit) {
long i = item_hit - item_sbar->getPosition();
- cPlayer& shopper = univ.party[stat_window];
- cItem& target = shopper.items[item_hit];
+ cItem& target = stat_window<=6 ? univ.party[stat_window].items[item_hit] : univ.party.get_junk_item(item_hit);
switch(stat_screen_mode) {
case MODE_IDENTIFY:
if(!take_gold(shop_identify_cost,false))
@@ -830,14 +829,22 @@ static void handle_item_shop_action(short item_hit) {
play_sound(68);
ASB("Your item is identified.");
target.ident = true;
- shopper.combine_things();
+ if (stat_window<=6)
+ univ.party[stat_window].combine_things();
+ else {
+ univ.party.combine_junk_items();
+ set_stat_window(ITEM_WIN_JUNK);
+ }
}
break;
case MODE_SELL_WEAP: case MODE_SELL_ARMOR: case MODE_SELL_ANY:
play_sound(-39);
univ.party.gold += store_selling_values[i];
ASB("You sell your item.");
- shopper.take_item(item_hit);
+ if (stat_window<=6)
+ univ.party[stat_window].take_item(item_hit);
+ else
+ univ.party.take_junk_item(item_hit);
put_item_screen(stat_window);
break;
case MODE_ENCHANT:
diff --git a/src/game/boe.items.cpp b/src/game/boe.items.cpp
index f7709863..ca66cde9 100644
--- a/src/game/boe.items.cpp
+++ b/src/game/boe.items.cpp
@@ -196,10 +196,7 @@ void give_thing(short pc_num, short item_num) {
add_string_to_buf("Give: Item is cursed.");
else {
item_store = item_to_give;
- if (univ.party.show_junk_bag && pc_num!=7)
- who_to = char_select_pc(4, "Give item to who? (type '7' for Bag)");
- else
- who_to = char_select_pc(3, "Give item to who?");
+ who_to = char_select_pc((univ.party.show_junk_bag && pc_num!=7 && (item_to_give.cursed || !item_to_give.unsellable)) ? 4 : 3, "Give item to who?");
if(overall_mode == MODE_COMBAT && who_to < 6 && !adjacent(univ.party[pc_num].combat_pos,univ.party[who_to].combat_pos)) {
add_string_to_buf("Give: Must be adjacent.");
who_to = 6;
@@ -219,11 +216,11 @@ void give_thing(short pc_num, short item_num) {
; // ok
else {
if(who_to<6 && !univ.party[who_to].has_space())
- ASB("Can't give: PC has max. # of items.");
+ add_string_to_buf("Can't give: PC has max. # of items.");
else if(who_to<6)
- ASB("Can't give: PC carrying too much.");
+ add_string_to_buf("Can't give: PC carrying too much.");
else
- ASB("Can't give: unknown problem.");
+ add_string_to_buf("Can't give: unknown problem.");
if(how_many > 0)
item_to_give.charges += how_many;
take_given_item = false;
@@ -550,7 +547,11 @@ static bool display_item_event_filter(cDialog& me, std::string id, size_t& first
give_help(38,0,me);
return true;
}
-
+ if (current_getting_pc==7 && !item.cursed && item.unsellable) {
+ beep(); // TODO: This is a game event, so it should have a game sound, not a system alert.
+ me["prompt"].setText("The object resists any attempt to insert it into the bag.");
+ return true;
+ }
set_item_flag(&item);
play_sound(0); // formerly force_play_sound
if (current_getting_pc<6) {
@@ -559,8 +560,10 @@ static bool display_item_event_filter(cDialog& me, std::string id, size_t& first
flags |= GIVE_ALLOW_OVERLOAD;
univ.party[current_getting_pc].give_item(item, flags);
}
- else
+ else {
univ.party.give_junk_item(item, is_combat() ? -1 : is_town() ? univ.party.town_num : 200);
+ if (stat_window==ITEM_WIN_JUNK) set_stat_window(stat_window);
+ }
}
*item_array[item_hit] = cItem();
item_array.erase(item_array.begin() + item_hit);
@@ -598,7 +601,6 @@ bool display_item(location from_loc,short /*pc_num*/,short mode, bool check_cont
else if(mode == 0)
stole_something = show_get_items("Getting all adjacent items:", item_array, current_getting_pc);
else stole_something = show_get_items("Getting all nearby items:", item_array, current_getting_pc);
- if (stat_window==ITEM_WIN_JUNK) set_stat_window(stat_window); // FIXME MUST NO BE HERE
put_item_screen(stat_window);
put_pc_screen();
@@ -942,7 +944,7 @@ short char_select_pc(short mode,const char *title) {
set_cursor(sword_curs);
- cDialog selectPc("select-pc");
+ cDialog selectPc(mode==4 ? "select-pc-with-bag" : "select-pc");
selectPc.attachClickHandlers(select_pc_event_filter, {"cancel", "pick1", "pick2", "pick3", "pick4", "pick5", "pick6", "junk"});
selectPc["title"].setText(title);
diff --git a/src/game/boe.party.cpp b/src/game/boe.party.cpp
index 58e551fc..8bb7a74c 100644
--- a/src/game/boe.party.cpp
+++ b/src/game/boe.party.cpp
@@ -630,8 +630,7 @@ void do_mage_spell(short pc_num,eSpell spell_num,bool freebie) {
}
if (numDone) {
univ.party.combine_junk_items();
- if (stat_window==ITEM_WIN_JUNK)
- set_stat_window(ITEM_WIN_JUNK);
+ if (stat_window==ITEM_WIN_JUNK) set_stat_window(ITEM_WIN_JUNK);
}
}
break;
diff --git a/src/game/boe.text.cpp b/src/game/boe.text.cpp
index 9dcf1b8c..cb87c24d 100644
--- a/src/game/boe.text.cpp
+++ b/src/game/boe.text.cpp
@@ -339,11 +339,9 @@ void put_item_screen(eItemWinMode screen_num) {
if (is_town()) place_item_button(2,i,ITEMBTN_DROP);
}
}
-#if 0
- if(stat_screen_mode != MODE_INVEN && stat_screen_mode != MODE_SHOP) {
- place_buy_button(i,pc,i_num);
- }
-#endif
+ // now add identify or sell button if in shop
+ if (stat_screen_mode==MODE_IDENTIFY || stat_screen_mode==MODE_SELL_WEAP || stat_screen_mode==MODE_SELL_ARMOR || stat_screen_mode==MODE_SELL_ANY)
+ place_buy_button(i,7,i_num);
} // end of if item is there
} // end of for(short i = 0; i < 8; i++)
break;
@@ -419,18 +417,18 @@ void put_item_screen(eItemWinMode screen_num) {
}
void place_buy_button(short position,short pc_num,short item_num) {
+ if (pc_num<0 || pc_num>7) return;
rectangle dest_rect,source_rect;
rectangle button_sources[3] = {{24,0,36,30},{36,0,48,30},{48,0,60,30}};
short val_to_place;
// TODO: This is now duplicated here and in start_town_mode()
short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};
- const cPlayer& pc = univ.party[pc_num];
- const cItem& item = pc.items[item_num];
+ const cItem& item = pc_num<=6 ? univ.party[pc_num].items[item_num] : univ.party.get_junk_item(item_num);
if(item.variety == eItemType::NO_ITEM)
return;
-
+ bool const is_equipped = pc_num<=6 ? univ.party[pc_num].equip[item_num] : false;
dest_rect = item_buttons[position][ITEMBTN_SPEC];
val_to_place = (item.charges > 0) ?
@@ -447,19 +445,19 @@ void place_buy_button(short position,short pc_num,short item_num) {
}
break;
case MODE_SELL_WEAP:
- if((*item.variety).is_weapon && !pc.equip[item_num] && item.ident && val_to_place > 0 && !item.unsellable) {
+ if((*item.variety).is_weapon && !is_equipped && item.ident && val_to_place > 0 && !item.unsellable) {
item_area_button_active[position][ITEMBTN_SPEC] = true;
source_rect = button_sources[1];
}
break;
case MODE_SELL_ARMOR:
- if((*item.variety).is_armour && !pc.equip[item_num] && item.ident && val_to_place > 0 && !item.unsellable) {
+ if((*item.variety).is_armour && !is_equipped && item.ident && val_to_place > 0 && !item.unsellable) {
item_area_button_active[position][ITEMBTN_SPEC] = true;
source_rect = button_sources[1];
}
break;
case MODE_SELL_ANY:
- if(!pc.equip[item_num] && item.ident && val_to_place > 0 && !item.unsellable) {
+ if(!is_equipped && item.ident && val_to_place > 0 && !item.unsellable) {
item_area_button_active[position][ITEMBTN_SPEC] = true;
source_rect = button_sources[1];
}
diff --git a/src/game/boe.town.cpp b/src/game/boe.town.cpp
index 269fa1da..0f4080cd 100644
--- a/src/game/boe.town.cpp
+++ b/src/game/boe.town.cpp
@@ -598,6 +598,7 @@ void start_town_combat(eDirection direction) {
set_pc_moves();
pick_next_pc();
center = univ.current_pc().combat_pos;
+ UI::toolbar.reset_active_button();
UI::toolbar.draw(mainPtr);
put_pc_screen();
set_stat_window_for_pc(univ.cur_pc);
diff --git a/src/game/boe.ui.hpp b/src/game/boe.ui.hpp
index 145c405a..553ac77d 100644
--- a/src/game/boe.ui.hpp
+++ b/src/game/boe.ui.hpp
@@ -40,6 +40,7 @@ class cToolbar {
void draw_buttons();
void init();
public:
+ void reset_active_button() { active=-1; }
void draw(sf::RenderTarget& targ);
eToolbarButton button_hit(sf::RenderWindow& win, location click);
};
diff --git a/src/scenario/item.cpp b/src/scenario/item.cpp
index 5baad196..7e5d1f22 100644
--- a/src/scenario/item.cpp
+++ b/src/scenario/item.cpp
@@ -101,6 +101,26 @@ bool cItem::abil_group() const {
return false;
}
+bool cItem::can_be_combined_with(cItem const &item) const
+{
+ if (!ident || !item.ident || variety==eItemType::NO_ITEM || item.variety==eItemType::NO_ITEM ||
+ type_flag==0 || item.type_flag==0)
+ return false;
+ if (name!=item.name || weight!=item.weight || graphic_num!=item.graphic_num ||
+ value!=item.value || special_class!=item.special_class) return false;
+ if (item_level != item.item_level || awkward!=item.awkward || bonus!=item.bonus || protection!=item.protection)
+ return false;
+ if (weap_type!=item.weap_type || magic_use_type!=item.magic_use_type || ability!=item.ability)
+ return false;
+ if (ability!=eItemAbil::NONE && (abil_data[0]!=item.abil_data[0] || abil_data[1]!=item.abil_data[1]))
+ return false;
+ if (missile!=item.missile || is_special!=item.is_special)
+ return false;
+ if (magic!=item.magic || cursed!=item.cursed || enchanted!=item.enchanted || unsellable!=item.unsellable)
+ return false;
+ return true;
+}
+
cItem::cItem(){
variety = eItemType::NO_ITEM;
item_level = 0;
diff --git a/src/scenario/item.hpp b/src/scenario/item.hpp
index c1bd4c93..96b4cb37 100644
--- a/src/scenario/item.hpp
+++ b/src/scenario/item.hpp
@@ -79,7 +79,8 @@ public:
cItem();
explicit cItem(eItemPreset preset);
explicit cItem(eAlchemy recipe);
-
+ bool can_be_combined_with(cItem const &item) const;
+
cPictNum get_picture_num(bool tiny=false) const;
void import_legacy(legacy::item_record_type const & old);
void writeTo(std::ostream& file, std::string prefix = "") const;
diff --git a/src/universe/party.cpp b/src/universe/party.cpp
index 91959dd4..468267be 100644
--- a/src/universe/party.cpp
+++ b/src/universe/party.cpp
@@ -260,9 +260,7 @@ bool cParty::is_junk_item_compatible_with_town(item_num_t id, int townId) const
static bool combine_items(cItem &item1, cItem const &item2)
{
- if (item1.variety != eItemType::NO_ITEM && item1.ident && item2.ident &&
- item2.variety != eItemType::NO_ITEM && item1.type_flag == item2.type_flag &&
- item1.name == item2.name && item1.special_class == item2.special_class) {
+ if (item1.can_be_combined_with(item2)) {
short test = item1.charges + item2.charges;
if(test > 125) {
item1.charges = 125;
diff --git a/src/universe/pc.cpp b/src/universe/pc.cpp
index e9499dfe..5d6ef26c 100644
--- a/src/universe/pc.cpp
+++ b/src/universe/pc.cpp
@@ -712,9 +712,7 @@ void cPlayer::combine_things() {
for(int i = 0; i < items.size(); i++) {
if(items[i].variety != eItemType::NO_ITEM && items[i].type_flag > 0 && items[i].ident) {
for(int j = i + 1; j < items.size(); j++)
- if(items[j].variety != eItemType::NO_ITEM && items[j].type_flag == items[i].type_flag &&
- items[j].name == items[i].name && items[j].special_class == items[i].special_class &&
- items[j].ident) {
+ if(items[j].can_be_combined_with(items[i])) {
if(print_result) print_result("(items combined)");
short test = items[i].charges + items[j].charges;
if(test > 125) {