Bring up Get Items dialog when retrieving stored items from the next scenario, so that you can pick and choose which items to keep.

Also some bugfixes and stuff:
- Fix specials sometimes being run twice in a row
- Holding Control while clicking Create also makes a debug party (as an alternative to holding Command)
- Fix "How Many" popup being non-dismissible
- Reduce loading time spent on checking for missing opcodes
This commit is contained in:
2014-12-08 02:37:15 -05:00
parent 5249c6eef7
commit 34be9a0233
7 changed files with 80 additions and 69 deletions

View File

@@ -1297,8 +1297,9 @@ bool handle_action(sf::Event event)
// Note: We just check once here instead of looping because run_special also pulls from the queue.
if(!special_queue.empty()) {
s3 = 0;
run_special(special_queue.front(), &s1, &s2, &s3);
pending_special_type pending = special_queue.front();
special_queue.pop();
run_special(pending, &s1, &s2, &s3);
if (s3 > 0)
draw_terrain();
}
@@ -2526,6 +2527,7 @@ void start_new_game()
// display_intro();
if(kb::isKeyPressed(kb::LSystem) || kb::isKeyPressed(kb::RSystem)) init_party(2); // if command key held down, create debug party
else if(kb::isKeyPressed(kb::LControl) || kb::isKeyPressed(kb::RControl)) init_party(2);
else init_party(0);
//while (creation_done == false) {

View File

@@ -72,9 +72,6 @@ std::map<const eItemType, const short> excluding_types = {
short selected,item_max = 0;
short first_item_shown,store_get_mode,current_getting_pc,store_pcnum,total_items_gettable; // these 5 used for get items dialog
short item_array[130]; // NUM_TOWN_ITEMS + a bit
void sort_pc_items(short pc_num)
{
cItemRec store_item;
@@ -122,7 +119,7 @@ bool give_to_party(cItemRec item, short print_result) {
}
////
bool give_to_pc(short pc_num,cItemRec item,short print_result)
bool give_to_pc(short pc_num,cItemRec item,short print_result,bool allow_overload)
{
short free_space;
char announce_string[60];
@@ -139,7 +136,7 @@ bool give_to_pc(short pc_num,cItemRec item,short print_result)
ASB("You get some food.");
return true;
}
if (item.item_weight() >
if(!allow_overload && item.item_weight() >
amount_pc_can_carry(pc_num) - pc_carry_weight(pc_num)) {
if (print_result == true) {
// TODO: Play an error sound here
@@ -174,6 +171,7 @@ bool give_to_pc(short pc_num,cItemRec item,short print_result)
return false;
}
// TODO: Utilize the second parameter in special node processing
bool forced_give(short item_num,eItemAbil abil) ////
// if abil > 0, force abil, else ignore
{
@@ -890,7 +888,7 @@ void set_town_attitude(short lo,short hi,short att) {
}
static void put_item_graphics(cDialog& me)
static void put_item_graphics(cDialog& me, size_t& first_item_shown, short& current_getting_pc, const std::vector<cItemRec*>& item_array)
{
short i,storage;
cItemRec item;
@@ -926,8 +924,8 @@ static void put_item_graphics(cDialog& me)
if (first_item_shown == 0)
me["up"].hide();
else me["up"].show();
if ((first_item_shown > total_items_gettable - 7) ||
(total_items_gettable <= 8) )
if(first_item_shown > item_array.size() - 7 ||
item_array.size() <= 8)
me["down"].hide();
else me["down"].show();
@@ -937,9 +935,12 @@ static void put_item_graphics(cDialog& me)
std::string pict = sout.str() + "-g", name = sout.str() + "-name";
std::string detail = sout.str() + "-detail", weight = sout.str() + "-weight";
if (item_array[i + first_item_shown] != 200) { // display an item in window
try {
if(item_array.at(i + first_item_shown)->variety == eItemType::NO_ITEM)
throw std::out_of_range("");
// display an item in window
me[pict].show();
item = univ.town.items[item_array[i + first_item_shown]];
item = *item_array[i + first_item_shown];
me[name].setText(item.ident ? item.full_name : item.name);
// TODO: Party sheet items
cPict& pic = dynamic_cast<cPict&>(me[pict]);
@@ -957,7 +958,7 @@ static void put_item_graphics(cDialog& me)
storage = item.item_weight();
sprintf ((char *) message, "Weight: %d",storage);
me[weight].setText(message);
} else { // erase the spot
} catch(std::out_of_range) { // erase the spot
me[pict].hide();
me[name].setText("");
me[detail].setText("");
@@ -981,7 +982,7 @@ static void put_item_graphics(cDialog& me)
}
static bool display_item_event_filter(cDialog& me, std::string id, eKeyMod) {
static bool display_item_event_filter(cDialog& me, std::string id, size_t& first_item_shown, short& current_getting_pc, std::vector<cItemRec*>& item_array, bool allow_overload) {
cItemRec item;
if(id == "done") {
@@ -989,25 +990,23 @@ static bool display_item_event_filter(cDialog& me, std::string id, eKeyMod) {
} else if(id == "up") {
if(first_item_shown > 0) {
first_item_shown -= 8;
put_item_graphics(me);
put_item_graphics(me, first_item_shown, current_getting_pc, item_array);
}
} else if(id == "down") {
// TODO: This 116 is a magic number, and a limit to be removed
if (first_item_shown < 116) {
if (first_item_shown + 8 < item_array.size()) {
first_item_shown += 8;
put_item_graphics(me);
put_item_graphics(me, first_item_shown, current_getting_pc, item_array);
}
} else if(id.substr(0,2) == "pc") {
current_getting_pc = id[2] - '1';
put_item_graphics(me);
put_item_graphics(me, first_item_shown, current_getting_pc, item_array);
} else {
if(current_getting_pc == 6) return true;
short item_hit;
size_t item_hit;
item_hit = id[4] - '1';
item_hit += first_item_shown;
if(item_array[item_hit] >= NUM_TOWN_ITEMS)
return true;
item = univ.town.items[item_array[item_hit]];
if(item_hit >= item_array.size()) return true;
item = *item_array[item_hit];
if(item.property) {
if(me.getResult<bool>()) {
std::string choice = cChoiceDlog("steal-item.xml",{"steal","leave"}).show();
@@ -1017,19 +1016,19 @@ static bool display_item_event_filter(cDialog& me, std::string id, eKeyMod) {
item.property = false;
}
if(univ.town.items[item_array[item_hit]].variety == eItemType::GOLD) {
if(univ.town.items[item_array[item_hit]].item_level > 3000)
univ.town.items[item_array[item_hit]].item_level = 3000;
if(item_array[item_hit]->variety == eItemType::GOLD) {
if(item_array[item_hit]->item_level > 3000)
item_array[item_hit]->item_level = 3000;
set_item_flag(&item);
give_gold(univ.town.items[item_array[item_hit]].item_level,false);
give_gold(item_array[item_hit]->item_level,false);
play_sound(39); // formerly force_play_sound
} else if(univ.town.items[item_array[item_hit]].variety == eItemType::FOOD) {
give_food(univ.town.items[item_array[item_hit]].item_level,false);
} else if(item_array[item_hit]->variety == eItemType::FOOD) {
give_food(item_array[item_hit]->item_level,false);
set_item_flag(&item);
set_item_flag(&univ.town.items[item_array[item_hit]]);
set_item_flag(item_array[item_hit]);
play_sound(62); // formerly force_play_sound
} else {
if(item.item_weight() > amount_pc_can_carry(current_getting_pc) - pc_carry_weight(current_getting_pc)) {
if(!allow_overload && item.item_weight() > amount_pc_can_carry(current_getting_pc) - pc_carry_weight(current_getting_pc)) {
// TODO: Play an error sound here
me["prompt"].setText("It's too heavy to carry.");
give_help(38,0,me);
@@ -1038,13 +1037,11 @@ static bool display_item_event_filter(cDialog& me, std::string id, eKeyMod) {
set_item_flag(&item);
play_sound(0); // formerly force_play_sound
give_to_pc(current_getting_pc, item, 0);////
give_to_pc(current_getting_pc, item, false, allow_overload);
}
univ.town.items[item_array[item_hit]] = cItemRec();
for(short i = item_hit; i < 125; i++)
item_array[i] = item_array[i + 1];
total_items_gettable--;
put_item_graphics(me);
*item_array[item_hit] = cItemRec();
item_array.erase(item_array.begin() + item_hit);
put_item_graphics(me, first_item_shown, current_getting_pc, item_array);
}
return true;
}
@@ -1057,19 +1054,14 @@ bool display_item(location from_loc,short pc_num,short mode, bool check_containe
//pc_num; // < 6 - this pc only 6 - any pc
//short mode; // 0 - adjacent 1 - all in sight
{
short i,array_position = 0;
// short item_array[130];
std::vector<cItemRec*> item_array;
short i;
make_cursor_sword();
first_item_shown = 0;
store_get_mode = mode;
current_getting_pc = current_pc;
store_pcnum = pc_num;
short current_getting_pc = current_pc;
for (i = 0; i < 130; i++)
item_array[i] = 200;
total_items_gettable = 0;
for (i = 0; i < NUM_TOWN_ITEMS; i++)
if(univ.town.items[i].variety != eItemType::NO_ITEM) {
if (((adjacent(from_loc,univ.town.items[i].item_loc) == true) ||
@@ -1078,34 +1070,46 @@ bool display_item(location from_loc,short pc_num,short mode, bool check_containe
&& (can_see_light(from_loc,univ.town.items[i].item_loc,sight_obscurity) < 5))) &&
(univ.town.items[i].contained == check_container) &&
((!check_container) || (univ.town.items[i].item_loc == from_loc))) {
item_array[array_position] = i;
array_position++;
total_items_gettable++;
item_array.push_back(&univ.town.items[i]);
}
}
bool stole_something = false;
if(check_container)
stole_something = show_get_items("Looking in container:", item_array, current_getting_pc);
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);
put_item_screen(stat_window,0);
put_pc_screen();
return stole_something;
}
bool show_get_items(std::string titleText, std::vector<cItemRec*>& itemRefs, short pc_getting, bool overload) {
using namespace std::placeholders;
size_t first_item = 0;
if (!pc_gworld_loaded)
pc_gworld.loadFromImage(*ResMgr::get<ImageRsrc>("pcs"));
cDialog itemDialog("get-items.xml");
itemDialog.attachClickHandlers(display_item_event_filter, {"done", "up", "down"});
itemDialog.attachClickHandlers(display_item_event_filter, {"pc1", "pc2", "pc3", "pc4", "pc5", "pc6"});
auto handler = std::bind(display_item_event_filter, _1, _2, std::ref(first_item), std::ref(pc_getting), std::ref(itemRefs), overload);
itemDialog.attachClickHandlers(handler, {"done", "up", "down"});
itemDialog.attachClickHandlers(handler, {"pc1", "pc2", "pc3", "pc4", "pc5", "pc6"});
itemDialog.setResult(false);
cTextMsg& title = dynamic_cast<cTextMsg&>(itemDialog["title"]);
if(check_container == true)
title.setText("Looking in container:");
else if(mode == 0)
title.setText("Getting all adjacent items:");
else title.setText("Getting all nearby items:");
title.setText(titleText);
for(i = 1; i <= 8; i++) {
for(int i = 1; i <= 8; i++) {
std::ostringstream sout;
sout << "item" << i << "-key";
itemDialog[sout.str()].attachKey({false, static_cast<unsigned char>('`' + i), mod_none});
itemDialog[sout.str()].attachClickHandler(display_item_event_filter);
itemDialog[sout.str()].attachClickHandler(handler);
}
put_item_graphics(itemDialog);
put_item_graphics(itemDialog, first_item, pc_getting, itemRefs);
if (univ.party.help_received[36] == 0) {
// TODO: Not sure if I need to an initial draw
@@ -1115,9 +1119,6 @@ bool display_item(location from_loc,short pc_num,short mode, bool check_containe
itemDialog.run();
put_item_screen(stat_window,0);
put_pc_screen();
return itemDialog.getResult<bool>();
@@ -1183,7 +1184,8 @@ short custom_choice_dialog(std::array<std::string, 6>& strs,short pic_num,ePicTy
//}
static bool get_num_of_items_event_filter(cDialog& me, std::string, eKeyMod) {
me.setResult<int>(me["number"].getTextAsNum());
if(me.toast(true))
me.setResult<int>(me["number"].getTextAsNum());
return true;
}

View File

@@ -3,7 +3,7 @@
#include "pict.h"
void sort_pc_items(short pc_num);
bool give_to_pc(short pc_num,cItemRec item,short print_result);
bool give_to_pc(short pc_num,cItemRec item,short print_result,bool allow_overload = false);
bool forced_give(short item_num,eItemAbil abil);
bool GTP(short item_num);
bool silent_GTP(short item_num);
@@ -36,6 +36,7 @@ short get_prot_level(short pc_num,short abil);
void make_town_hostile();
void set_town_attitude(short lo,short hi,short att);
bool show_get_items(std::string titleText, std::vector<cItemRec*>& itemRefs, short pc_getting, bool overload = false);
bool display_item(location from_loc,short pc_num,short mode, bool check_container);
short custom_choice_dialog(std::array<std::string, 6>& strs,short pic_num,ePicType pic_type,std::array<short, 3>& buttons) ;
//short fancy_choice_dialog(short which_dlog,short parent);

View File

@@ -405,13 +405,14 @@ void init_party_scen_data()
stored_item = true;
if (stored_item == true)
if(cChoiceDlog("keep-stored-items.xml", {"yes", "no"}).show() == "yes") {
// TODO: Consider allowing them to pick and choose the items to take, using the get items dialog
std::vector<cItemRec*> saved_item_refs;
for (i = 0; i < 3;i++)
for (j = 0; j < NUM_TOWN_ITEMS; j++)
if (univ.party.stored_items[i][j].variety != eItemType::NO_ITEM)
if (!give_to_party(univ.party.stored_items[i][j],false)) {
i = 20; j = NUM_TOWN_ITEMS + 1;
}
saved_item_refs.push_back(&univ.party.stored_items[i][j]);
short pc = 0;
while(univ.party[pc].main_status != eMainStatus::ALIVE && pc < 6) pc++;
show_get_items("Choose stored items to keep:", saved_item_refs, pc, true);
}
for (i = 0; i < 3;i++)
for (j = 0; j < NUM_TOWN_ITEMS; j++) {

View File

@@ -402,7 +402,7 @@ void start_town_mode(short which_town, short entry_dir)
else univ.town.monst[i].active = 0;
}
handle_town_specials(town_number, (short) town_toast,(entry_dir < 9) ? univ.town->start_locs[entry_dir] : town_force_loc);
// TODO: Flush the special node queue on scenario start so that the special actually gets called.
// Flush excess doomguards and viscous goos
for (i = 0; i < univ.town->max_monst(); i++)

View File

@@ -80,6 +80,7 @@ public:
/// @param offset An offset in pixels between the control and the label.
/// @param bold If true, the label will be bolded.
/// @return true if the label was added, false if not (usually because it already had a label)
/// @note Even if it returns false, the label has been attached (ie, the existing label was updated).
bool addLabelFor(std::string key, std::string label, eLabelPos where, short offset, bool bold);
/// Show the dialog and start its event loop. All dialogs are modal.
void run(); // cd_run_dialog

View File

@@ -176,7 +176,11 @@ struct initer {
("start-shop", eSpecType::OUT_STORE)
;
// A check for missing types.
using underlying = std::underlying_type<eSpecType>::type;
// There's really no need to check all the way to the max of the underlying type.
// It's unlikely we'd go above 255, so unsigned char would be fine, but just in case,
// let's use unsigned short.
// Could change the actual enum's underlying type instead though?
using underlying = signed short;//std::underlying_type<eSpecType>::type;
struct node_less : std::binary_function<eSpecType, eSpecType, bool> {
bool operator()(const eSpecType& x, const eSpecType& y) const {return underlying(x) < underlying(y);}
};