Implement a dialog to edit shops in the scenario editor

This commit is contained in:
2015-02-04 13:55:22 -05:00
parent 24a128b5b8
commit 36491c818c
21 changed files with 631 additions and 20 deletions

View File

@@ -236,6 +236,9 @@ bool handle_action(location the_point,sf::Event /*event*/) {
case LB_EDIT_QUEST:
start_quest_editing();
break;
case LB_EDIT_SHOPS:
start_shops_editing();
break;
case LB_LOAD_OUT:
if(change_made) {
if(!save_check("save-section-confirm"))
@@ -447,6 +450,14 @@ bool handle_action(location the_point,sf::Event /*event*/) {
} else edit_quest(j);
start_quest_editing();
break;
case RB_SHOP:
if(option_hit) {
if(j == scenario.shops.size() - 1)
scenario.shops.pop_back();
else scenario.shops[j] = cShop("Unused Shop");
} else edit_shop(j);
start_shops_editing();
break;
}
mouse_button_held = false;
}
@@ -2074,6 +2085,7 @@ void set_up_main_screen() {
set_lb(-1,LB_TEXT,LB_EDIT_TEXT,"Edit Scenario Text");
set_lb(-1,LB_TEXT,LB_EDIT_SPECITEM,"Edit Special Items");
set_lb(-1,LB_TEXT,LB_EDIT_QUEST,"Edit Quests");
set_lb(-1,LB_TEXT,LB_EDIT_SHOPS,"Edit Shops");
set_lb(-1,LB_TEXT,LB_NO_ACTION,"");
set_lb(-1,LB_TEXT,LB_NO_ACTION,"Outdoors Options");
strb << " Section x = " << cur_out.x << ", y = " << cur_out.y;
@@ -2259,6 +2271,27 @@ void start_quest_editing() {
set_lb(NLS - 3,LB_TEXT,LB_NO_ACTION,"Command-click or right-click to delete",true);
}
void start_shops_editing() {
int num_options = scenario.shops.size() + 1;
if(overall_mode < MODE_MAIN_SCREEN)
set_up_main_screen();
overall_mode = MODE_MAIN_SCREEN;
right_sbar->show();
right_sbar->setPosition(0);
reset_rb();
right_sbar->setMaximum(num_options - NRSONPAGE);
for(int i = 0; i < num_options; i++) {
std::string title;
if(i == scenario.shops.size())
title = "Create New Shop";
else title = scenario.shops[i].getName();
title = std::to_string(i) + " - " + title;
set_rb(i, RB_SHOP, i, title);
}
redraw_screen();
set_lb(NLS - 3,LB_TEXT,LB_NO_ACTION,"Command-click or right-click to delete",true);
}
extern size_t num_strs(short mode); // defined in scen.keydlgs.cpp
// mode 0 - scen 1 - out 2 - town 3 - journal

View File

@@ -30,6 +30,7 @@ void start_monster_editing(short just_redo_text);
void start_item_editing(short just_redo_text);
void start_special_item_editing();
void start_quest_editing();
void start_shops_editing();
void start_string_editing(short mode,short just_redo_text);
void start_special_editing(short mode,short just_redo_text);
void town_entry(location spot_hit);

View File

@@ -10,6 +10,7 @@ enum eLBAction {
LB_EDIT_TEXT,
LB_EDIT_SPECITEM,
LB_EDIT_QUEST,
LB_EDIT_SHOPS,
LB_LOAD_OUT,
LB_EDIT_OUT,
LB_LOAD_TOWN,
@@ -36,6 +37,7 @@ enum eRBAction {
RB_OUT_SIGN = 14,
RB_TOWN_SIGN = 15,
RB_QUEST = 16,
RB_SHOP = 17,
};
enum eLBMode {

View File

@@ -23,6 +23,7 @@
#include "restypes.hpp"
#include "stack.hpp"
#include "spell.hpp"
#include "mathutil.hpp"
extern short cen_x, cen_y,cur_town;
extern bool mouse_button_held;
@@ -184,6 +185,8 @@ static bool pick_picture(ePicType type, cDialog& parent, std::string result_fld,
cPict& pic_ctrl = dynamic_cast<cPict&>(parent[pic_fld]);
if(type == PIC_TER_ANIM && pic < 1000)
pic += 960;
if(type == PIC_ITEM && pic_ctrl.getPicType() == PIC_TINY_ITEM)
type = PIC_TINY_ITEM;
pic_ctrl.setPict(pic,type);
}
}
@@ -944,11 +947,11 @@ static bool edit_monst_abil_event_filter(cDialog& me,std::string hit,cMonster& m
return true;
}
static short get_monst_abil_num(std::string prompt, int min, int max, cDialog& parent) {
static short get_monst_abil_num(std::string prompt, int min, int max, cDialog& parent, int cur = -1) {
cDialog numPanel("get-mabil-num", &parent);
numPanel["okay"].attachClickHandler(std::bind(&cDialog::toast, &numPanel, false));
numPanel["prompt"].setText(prompt + " (" + std::to_string(min) + "-" + std::to_string(max) + ") ");
numPanel["number"].setTextToNum(min);
numPanel["number"].setTextToNum(minmax(min,max,cur));
numPanel.run();
int result = numPanel["number"].getTextAsNum();
@@ -2052,6 +2055,344 @@ void edit_quest(size_t which_quest) {
quest_dlg.run();
}
static bool put_shop_item_in_dlog(cPict& pic, cControl& num, cControl& title, const cShop& shop, int which) {
cShopItem entry = shop.getItem(which);
num.setTextToNum(which);
pic.setPict(entry.item.graphic_num);
if(entry.type == eShopItemType::EMPTY) {
title.setText("");
return false;
}
std::string name = entry.item.full_name;
int amount = entry.quantity;
if(entry.type == eShopItemType::OPTIONAL) {
name += " [" + std::to_string(amount / 1000) + "% chance]";
amount %= 1000;
}
if(amount > 0) {
name = std::to_string(amount) + "x " + name;
}
title.setText(name);
return true;
}
static void put_shop_in_dlog(cDialog& me, const cShop& shop, size_t which_shop) {
me["num"].setText(std::to_string(which_shop) + " of " + std::to_string(scenario.shops.size()));
me["name"].setText(shop.getName());
dynamic_cast<cPict&>(me["face"]).setPict(shop.getFace());
dynamic_cast<cLedGroup&>(me["type"]).setSelected("t" + std::to_string(int(shop.getType()) + 1));
dynamic_cast<cLedGroup&>(me["prompt"]).setSelected("p" + std::to_string(int(shop.getPrompt()) + 1));
cStack& items = dynamic_cast<cStack&>(me["items"]);
for(int i = 0; i < 6; i++) {
items.setPage(i);
for(int j = 0; j < 5; j++) {
std::string id = std::to_string(j + 1);
if(put_shop_item_in_dlog(dynamic_cast<cPict&>(me["pict" + id]), me["n" + id], me["item" + id], shop, i * 5 + j)) {
if(i == 0) {
me["ed" + id].show();
me["del" + id].show();
}
} else if(i == 0) {
me["ed" + id].hide();
me["del" + id].hide();
}
}
}
items.setPage(0);
}
static bool save_shop_from_dlog(cDialog& me, cShop& shop, size_t which_shop, bool close) {
if(!me.toast(true)) return false;
shop.setName(me["name"].getText());
shop.setType(eShopType(dynamic_cast<cLedGroup&>(me["type"]).getSelected()[1] - '1'));
shop.setPrompt(eShopPrompt(dynamic_cast<cLedGroup&>(me["prompt"]).getSelected()[1] - '1'));
shop.setFace(dynamic_cast<cPict&>(me["face"]).getPicNum());
// Items are filled in as they're added by the dialog, so that's all we need to do here
scenario.shops[which_shop] = shop;
if(!close) me.untoast();
return true;
}
static bool change_shop_dlog_page(cDialog& me, std::string dir, cShop& shop, size_t& which_shop) {
if(!save_shop_from_dlog(me, shop, which_shop, false))
return true;
if(dir == "left") {
if(which_shop == 0)
which_shop = scenario.shops.size();
which_shop--;
} else if(dir == "right") {
which_shop++;
if(which_shop == scenario.shops.size())
which_shop = 0;
}
shop = scenario.shops[which_shop];
put_shop_in_dlog(me, shop, which_shop);
return true;
}
static bool change_shop_dlog_items_page(cDialog& me, std::string dir, const cShop& shop) {
cStack& items = dynamic_cast<cStack&>(me["items"]);
int curPage = items.getPage(), maxPage = items.getPageCount();
if(dir == "up") {
if(curPage == 0)
curPage = maxPage - 1;
else curPage--;
} else if(dir == "down") {
if(curPage == maxPage - 1)
curPage = 0;
else curPage++;
}
for(int i = 0; i < 5; i++) {
std::string id = std::to_string(i + 1);
if(shop.getItem(curPage * 5 + i).type == eShopItemType::EMPTY) {
me["ed" + id].hide();
me["del" + id].hide();
} else {
me["ed" + id].show();
me["del" + id].show();
}
}
items.setPage(curPage);
return true;
}
static void edit_shop_item(cDialog& parent, size_t& item, size_t& quantity, bool optional) {
using namespace std::placeholders;
int was_item = item;
cDialog item_dlg("edit-shop-item", &parent);
item_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
item_dlg["okay"].attachClickHandler(std::bind(&cDialog::toast, _1, true));
if(optional) {
item_dlg["amount"].setTextToNum(quantity % 1000);
item_dlg["chance"].setTextToNum(quantity / 1000);
item_dlg["amount"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 999, "amount"));
item_dlg["chance"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 1, 100, "chance"));
} else {
item_dlg["amount"].setTextToNum(quantity);
item_dlg["chance"].hide();
item_dlg["chance-prompt"].hide();
}
item_dlg["item"].setText(scenario.scen_items[item].full_name);
item_dlg["choose"].attachClickHandler([&item](cDialog& me, std::string, eKeyMod) -> bool {
item = choose_text(STRT_ITEM, item, &me, "Which item?");
me["item"].setText(scenario.scen_items[item].full_name);
return true;
});
item_dlg.run();
if(item_dlg.accepted()) {
quantity = item_dlg["amount"].getTextAsNum();
if(optional)
quantity += 1000 * item_dlg["chance"].getTextAsNum();
} else item = was_item;
}
static void edit_shop_special(cDialog& parent, cItem& item, size_t& quantity) {
using namespace std::placeholders;
cDialog spec_dlg("edit-shop-special", &parent);
spec_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
spec_dlg["okay"].attachClickHandler(std::bind(&cDialog::toast, _1, true));
spec_dlg["cost"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10000, "cost"));
spec_dlg["pickicon"].attachClickHandler(std::bind(pick_picture, PIC_ITEM, _1, "", "icon"));
spec_dlg["edit"].attachClickHandler([](cDialog& me, std::string, eKeyMod) -> bool {
int spec = me["node"].getTextAsNum();
if(spec < 0) spec = get_fresh_spec(0);
if(edit_spec_enc(spec, 0, &me))
me["node"].setTextToNum(spec);
return true;
});
spec_dlg["name"].setText(item.full_name);
spec_dlg["descr"].setText(item.desc);
spec_dlg["node"].setTextToNum(item.item_level);
spec_dlg["cost"].setTextToNum(item.value);
spec_dlg["amount"].setTextToNum(quantity);
dynamic_cast<cPict&>(spec_dlg["icon"]).setPict(item.graphic_num);
spec_dlg.run();
if(spec_dlg.accepted()) {
item.full_name = spec_dlg["name"].getText();
item.desc = spec_dlg["descr"].getText();
item.item_level = spec_dlg["node"].getTextAsNum();
item.value = spec_dlg["cost"].getTextAsNum();
quantity = spec_dlg["amount"].getTextAsNum();
item.graphic_num = dynamic_cast<cPict&>(spec_dlg["icon"]).getPicNum();
}
}
static bool edit_shop_entry(cDialog& me, std::string which, cShop& shop) {
int btn_i = which[2] - '0';
int i = dynamic_cast<cStack&>(me["items"]).getPage() * 5 + btn_i - 1;
cShopItem entry = shop.getItem(i);
eStrType list;
std::string prompt;
bool need_string = true;
switch(entry.type) {
case eShopItemType::EMPTY: return true;
case eShopItemType::ITEM:
case eShopItemType::OPTIONAL:
edit_shop_item(me, entry.index, entry.quantity, entry.type == eShopItemType::OPTIONAL);
entry.item = scenario.scen_items[entry.index];
shop.replaceItem(i, entry);
need_string = false;
break;
case eShopItemType::CLASS:
entry.index = get_monst_abil_num("Which special class?", 1, 100, me, entry.index);
shop.replaceSpecial(i, eShopItemType::CLASS, entry.index);
need_string = false;
break;
case eShopItemType::CALL_SPECIAL:
edit_shop_special(me, entry.item, entry.quantity);
shop.replaceItem(i, entry);
need_string = false;
break;
case eShopItemType::MAGE_SPELL: list = STRT_MAGE; prompt = "Which mage spell?"; break;
case eShopItemType::PRIEST_SPELL: list = STRT_PRIEST; prompt = "Which priest spell?"; break;
case eShopItemType::ALCHEMY: list = STRT_ALCHEMY; prompt = "Which recipe?"; break;
case eShopItemType::SKILL: list = STRT_SKILL; prompt = "Which skill?"; break;
case eShopItemType::TREASURE: list = STRT_TREASURE; prompt = "What class of treasure?"; break;
case eShopItemType::CURE_ACID: case eShopItemType::CURE_DISEASE: case eShopItemType::CURE_POISON:
case eShopItemType::CURE_DUMBFOUNDING: case eShopItemType::CURE_PARALYSIS: case eShopItemType::DESTONE:
case eShopItemType::HEAL_WOUNDS: case eShopItemType::RAISE_DEAD: case eShopItemType::REMOVE_CURSE:
case eShopItemType::RESURRECT:
list = STRT_HEALING;
break;
}
if(need_string) {
entry.index = choose_text(list, entry.index, &me, prompt);
if(list == STRT_HEALING)
shop.replaceSpecial(i, eShopItemType(int(eShopItemType::HEAL_WOUNDS) + entry.index));
else shop.replaceSpecial(i, entry.type, entry.index);
}
std::string pic_id = which, num_id = which, title_id = which;
pic_id.replace(0,2,"pict"); num_id.replace(0,2,"n"); title_id.replace(0,2,"item");
put_shop_item_in_dlog(dynamic_cast<cPict&>(me[pic_id]), me[num_id], me[title_id], shop, i);
return true;
}
static bool delete_shop_entry(cDialog& me, std::string which, cShop& shop, size_t which_shop) {
cStack& items = dynamic_cast<cStack&>(me["items"]);
int page = items.getPage();
shop.clearItem((which[3] - '1') + 5 * page);
put_shop_in_dlog(me, shop, which_shop);
items.setPage(page);
change_shop_dlog_items_page(me, "stay", shop);
return true;
}
static bool add_shop_entry(cDialog& me, std::string type, cShop& shop, size_t which_shop) {
if(shop.size() == 30) {
giveError("There is no more room in this shop to add another item. Each shop can only have up to 30 items.", &me);
return true;
}
if(type == "item" || type == "opt") {
size_t which_item = 0, amount = 0;
edit_shop_item(me, which_item, amount, type == "opt");
if(scenario.scen_items[which_item].variety == eItemType::NO_ITEM)
return true;
if(scenario.scen_items[which_item].variety == eItemType::GOLD)
return true;
if(type == "item")
shop.addItem(which_item, scenario.scen_items[which_item], amount);
else shop.addItem(which_item, scenario.scen_items[which_item], amount % 1000, amount / 1000);
} else if(type == "spec") {
cItem item('spec');
size_t amount = 0;
edit_shop_special(me, item, amount);
if(item.item_level < 0)
return true;
shop.addSpecial(item.full_name, item.desc, item.graphic_num, item.item_level, item.value, amount);
} else if(type == "class") {
int n = get_monst_abil_num("Which special class?", 0, 100, me);
if(n == 0) return true;
shop.addSpecial(eShopItemType::CLASS, n);
} else {
eStrType list;
eShopItemType item;
std::string prompt;
if(type == "mage") {
list = STRT_MAGE;
item = eShopItemType::MAGE_SPELL;
prompt = "Which mage spell?";
} else if(type == "priest") {
list = STRT_PRIEST;
item = eShopItemType::PRIEST_SPELL;
prompt = "Which priest spell?";
} else if(type == "alch") {
list = STRT_ALCHEMY;
item = eShopItemType::ALCHEMY;
prompt = "Which recipe?";
} else if(type == "skill") {
list = STRT_SKILL;
item = eShopItemType::SKILL;
prompt = "Which skill?";
} else if(type == "treas") {
list = STRT_TREASURE;
item = eShopItemType::TREASURE;
prompt = "What class of treasure?";
} else if(type == "heal") {
list = STRT_HEALING;
prompt = "What kind of healing?";
}
int i = choose_text(list, -1, &me, prompt);
if(i == -1) return true;
if(list == STRT_HEALING) {
item = eShopItemType(int(eShopItemType::HEAL_WOUNDS) + i);
i = 0;
}
shop.addSpecial(item, i);
}
put_shop_in_dlog(me, shop, which_shop);
int atItem = shop.size() - 1;
int onPage = atItem / 5;
dynamic_cast<cStack&>(me["items"]).setPage(onPage);
change_shop_dlog_items_page(me, "stay", shop);
return true;
}
void edit_shop(size_t which_shop, cDialog* parent) {
using namespace std::placeholders;
if(which_shop == scenario.shops.size())
scenario.shops.emplace_back("New Shop");
cShop shop = scenario.shops[which_shop];
cDialog shop_dlg("edit-shop", parent);
shop_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
shop_dlg["okay"].attachClickHandler(std::bind(save_shop_from_dlog, _1, std::ref(shop), std::ref(which_shop), true));
shop_dlg["pickface"].attachClickHandler(std::bind(pick_picture, PIC_TALK, _1, "", "face"));
shop_dlg.attachClickHandlers(std::bind(change_shop_dlog_items_page, _1, _2, std::ref(shop)), {"up", "down"});
shop_dlg.attachClickHandlers(std::bind(delete_shop_entry, _1, _2, std::ref(shop), std::ref(which_shop)), {"del1", "del2", "del3", "del4", "del5"});
shop_dlg.attachClickHandlers(std::bind(edit_shop_entry, _1, _2, std::ref(shop)), {"ed1", "ed2", "ed3", "ed4", "ed5"});
shop_dlg.attachClickHandlers(std::bind(add_shop_entry, _1, _2, std::ref(shop), std::ref(which_shop)), {"item", "opt", "spec", "mage", "priest", "alch", "skill", "treas", "heal", "class"});
shop_dlg["rand"].attachClickHandler([&shop,which_shop](cDialog& me, std::string, eKeyMod) -> bool {
shop = cShop('junk');
put_shop_in_dlog(me, shop, which_shop);
return true;
});
if(scenario.shops.size() == 1 || parent != nullptr) {
shop_dlg["left"].hide();
shop_dlg["right"].hide();
} else {
shop_dlg.attachClickHandlers(std::bind(change_shop_dlog_page, _1, _2, std::ref(shop), std::ref(which_shop)), {"left", "right"});
}
dynamic_cast<cStack&>(shop_dlg["items"]).setPageCount(6);
put_shop_in_dlog(shop_dlg, shop, which_shop);
shop_dlg.run();
}
static void put_save_rects_in_dlog(cDialog& me) {
short i;

View File

@@ -9,6 +9,7 @@ short edit_item_type(short which_item);
cItem edit_item_abil(cItem starting_record,short which_item,cDialog& parent);
void edit_spec_item(short which_item);
void edit_quest(size_t which_quest);
void edit_shop(size_t which_shop, cDialog* parent = nullptr);
void edit_save_rects();
void edit_horses();
void edit_add_town();

View File

@@ -177,7 +177,7 @@ short choose_text_res(std::string res_list,short first_t,short last_t,unsigned s
return dlog.show(cur_choice);
}
short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, const char* title) {
short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, std::string title) {
location view_loc;
std::vector<std::string> strings;
@@ -263,6 +263,9 @@ short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, con
case STRT_TRAP:
strings = *ResMgr::get<StringRsrc>("trap-types");
break;
case STRT_HEALING:
strings = *ResMgr::get<StringRsrc>("shop-specials");
break;
case STRT_BUTTON:
for(int btn : available_btns) {
strings.push_back(basic_buttons[btn].label);
@@ -327,6 +330,9 @@ short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, con
case STRT_QUEST_STATUS:
strings = {"Available", "Started", "Completed", "Failed"};
break;
case STRT_TREASURE:
strings = {"0 - Junk", "1 - Lousy", "2 - So-so", "3 - Good", "4 - Great"};
break;
}
if(cur_choice < 0 || cur_choice >= strings.size())
cur_choice = -1;

View File

@@ -12,6 +12,7 @@ enum eStrType {
STRT_SHOP, STRT_COST_ADJ, STRT_STAIR_MODE, STRT_TALK_NODE,
STRT_STATUS, STRT_SPELL_PAT, STRT_SUMMON, STRT_TALK,
STRT_ENCHANT, STRT_DIR, STRT_QUEST, STRT_QUEST_STATUS,
STRT_HEALING, STRT_TREASURE,
};
bool cre(short val,short min,short max,std::string text1,std::string text2,cDialog* parent) ;
@@ -21,7 +22,7 @@ void put_choice_pics(short g_type);
pic_num_t choose_graphic(short cur_choice,ePicType g_type,cDialog* parent);
short choose_background(short cur_choice, cDialog* parent);
short choose_text_res(std::string res_list,short first_t,short last_t,unsigned short cur_choice,cDialog* parent,const char *title);
short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent,const char* title);
short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent,std::string title);
void edit_text_str(short which_str,short mode);
bool edit_spec_enc(short which_node,short mode,cDialog* parent);
short get_fresh_spec(short which_mode);