Reform PC editor menu -> command mapping so that the non-platform-dependent code doesn't need to know where the menuitem is

- Also disable edit menus when no party loaded and fix item menus not being populated if the party is in a scenario
This commit is contained in:
2015-01-05 17:17:34 -05:00
parent dfe54fd0a2
commit 04b9aec921
7 changed files with 148 additions and 159 deletions

View File

@@ -2,7 +2,7 @@ All of your character's damage has now been healed. Dead characters are still de
All of your characters (even dead ones) now have their maximum number of spell points.
All of your characters who were dead (or dust, or stoned) are now alive and intact. You may wish to select Heal Party now.
All negative conditions (poison, dumbfounding, disease, paralysis, etc.) have been removed from your characters (even dead ones).
Before you can do this, you need to load in an Blades of Exile save file. Select Open from the file menu.
All boats and horses are now your property.
Any major NPCs you may have slain, such as Erika or the dragons, are now alive again. You should now use the Leave Town and then Reset Towns menu items to make sure the characters appear.
You are now considered a member of the Anama church. You can no longer cast Mage spells. To get the full effect of this, add Anama Rings above.

View File

@@ -74,12 +74,8 @@ void Handle_One_Event();
void Handle_Activate();
void Handle_Update();
void Mouse_Pressed();
void handle_help_menu(int item_hit);
void handle_file_menu(int item_hit);
void handle_edit_menus(int item_hit);
bool verify_restore_quit(bool mode);
void set_up_apple_events();
void handle_item_menu(int item_hit);
//item_record_type convert_item (short_item_record_type s_item);
extern bool cur_scen_is_mac;
extern fs::path progDir;
@@ -192,33 +188,28 @@ void Mouse_Pressed() {
All_Done = verify_restore_quit(false);
}
void handle_help_menu(int item_hit) {
//char desk_acc_name[256];
//short desk_acc_num;
switch(item_hit) {
case 1:
cChoiceDlog("about-pced").show();
break;
default:
//GetItem (apple_menu,item_hit,desk_acc_name);
//desk_acc_num = OpenDeskAcc(desk_acc_name);
break;
}
static void display_strings(short nstr, pic_num_t pic) {
cStrDlog display_strings(get_str("pcedit", nstr), "", "Editing party", pic, PIC_DLOG);
display_strings.setSound(57);
display_strings.show();
}
void handle_file_menu(int item_hit) {
void handle_menu_choice(eMenu item_hit) {
int i,j,k;
fs::path file;
switch(item_hit) {
case 1://save
case eMenu::NONE: break;
case eMenu::ABOUT:
cChoiceDlog("about-pced").show();
break;
case eMenu::FILE_SAVE:
save_party(file_in_mem, univ);
break;
case 2://save as
case eMenu::FILE_SAVE_AS:
file = nav_put_party();
if(!file.empty()) save_party(file, univ);
break;
case 3://open
case eMenu::FILE_OPEN:
if(verify_restore_quit(true)){
file = nav_get_party();
if(!file.empty()) {
@@ -226,45 +217,24 @@ void handle_file_menu(int item_hit) {
file_in_mem = file;
party_in_scen = !univ.party.scen_name.empty();
if(!party_in_scen) load_base_item_defs();
scen_items_loaded = true;
update_item_menu();
}
}
menu_activate();
}
break;
// TODO: Implement these two
case 4: //close
break;
case 5: //revert;
break;
case 7://quit
case eMenu::QUIT:
All_Done = verify_restore_quit(false);
break;
}
}
static void display_strings(short nstr, pic_num_t pic) {
cStrDlog display_strings(get_str("pcedit", nstr), "", "Editing party", pic, PIC_DLOG);
display_strings.setSound(57);
display_strings.show();
}
void handle_edit_menus(int item_hit) {
short i,j,k;
if(file_in_mem.empty()) {
display_strings(5, 7);
return;
}
switch(item_hit) {
case 1:
case eMenu::EDIT_GOLD:
edit_gold_or_food(0);
break;
case 2:
case eMenu::EDIT_FOOD:
edit_gold_or_food(1);
break;
case 103:
case eMenu::LEAVE_TOWN:
if(univ.party.is_split() > 0) {
cChoiceDlog("reunite-first").show();
break;
@@ -273,7 +243,7 @@ void handle_edit_menus(int item_hit) {
leave_town();
break;
case 16:
case eMenu::REUNITE_PARTY:
if(univ.party.is_split() == 0) {
cChoiceDlog("not-split").show();
break;
@@ -286,29 +256,29 @@ void handle_edit_menus(int item_hit) {
break;
case 104:
case eMenu::RESET_TOWNS:
display_strings(20,7);
for(i = 0; i < 4; i++)
univ.party.creature_save[i].which_town = 200;
break;
case 5: // damage
case eMenu::HEAL_DAMAGE:
display_strings(1,15);
for(i = 0; i < 6; i++)
univ.party[i].cur_health = univ.party[i].max_health;
break;
case 6: // spell pts
case eMenu::RESTORE_MANA:
display_strings(2,15);
for(i = 0; i < 6; i++)
univ.party[i].cur_sp = univ.party[i].max_sp;
break;
case 7: // raise dead
case eMenu::RAISE_DEAD:
display_strings(3,15);
for(i = 0; i < 6; i++)
if(univ.party[i].main_status == eMainStatus::DEAD || univ.party[i].main_status == eMainStatus::DUST ||
univ.party[i].main_status == eMainStatus::STONE)
univ.party[i].main_status = eMainStatus::ALIVE;
break;
case 8: // conditions
case eMenu::CURE_CONDITIONS:
display_strings(4,15);
for(i = 0; i < 6; i++) {
univ.party[i].status[eStatus::POISON] = 0;
@@ -323,7 +293,7 @@ void handle_edit_menus(int item_hit) {
}
break;
case 108:
case eMenu::LEAVE_SCENARIO:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -332,20 +302,20 @@ void handle_edit_menus(int item_hit) {
break;
remove_party_from_scen();
break;
case 3:
case eMenu::EDIT_ALCHEMY:
display_alchemy(true);
break;
case 17: // all property
case eMenu::OWN_VEHICLES:
display_strings(6,7);
for(i = 0; i < 30; i++) {
univ.party.boats[i].property = false;
univ.party.horses[i].property = false;
}
break;
case 101: // edit day
case eMenu::EDIT_DAY:
edit_day();
break;
case 105: // out maps
case eMenu::ADD_OUT_MAPS:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -356,7 +326,7 @@ void handle_edit_menus(int item_hit) {
for(k = 0; k < 48; k++)
univ.out_maps[i][j][k] = 255;
break;
case 106: // town maps
case eMenu::ADD_TOWN_MAPS:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -367,24 +337,21 @@ void handle_edit_menus(int item_hit) {
for(k = 0; k < 64; k++)
univ.town_maps[i][j][k] = 255;
break;
case 10:
case eMenu::EDIT_MAGE:
display_pc(current_active_pc,0,0);
break;
case 11:
case eMenu::EDIT_PRIEST:
display_pc(current_active_pc,1,0);
break;
case 12:
case eMenu::EDIT_TRAITS:
pick_race_abil(&univ.party[current_active_pc],0);
break;
case 13:
case eMenu::EDIT_SKILLS:
spend_xp(current_active_pc,1,0);
break;
case 14:
case eMenu::EDIT_XP:
edit_xp(&univ.party[current_active_pc]);
break;
case 109:
// TODO: Implement "Set SDF"
break;;
}
}
@@ -443,11 +410,6 @@ void handle_edit_menus(int item_hit) {
// TODO: Let this take the item directly instead of the index
void handle_item_menu(int item_hit) {
cItemRec store_i;
if(file_in_mem.empty()) {
display_strings(5,7);
return;
}
store_i = univ.scenario.scen_items[item_hit];
store_i.ident = true;
give_to_pc(current_active_pc,store_i,false);

View File

@@ -13,4 +13,19 @@ void init_menubar();
void update_item_menu();
void menu_activate();
enum class eMenu {
NONE, ABOUT, QUIT,
FILE_OPEN, FILE_CLOSE, FILE_SAVE, FILE_SAVE_AS, FILE_REVERT, HELP_INDEX,
// Edit Party menu
EDIT_GOLD, EDIT_FOOD, EDIT_ALCHEMY,
HEAL_DAMAGE, RESTORE_MANA, RAISE_DEAD, CURE_CONDITIONS,
EDIT_MAGE, EDIT_PRIEST, EDIT_TRAITS, EDIT_SKILLS, EDIT_XP,
REUNITE_PARTY, OWN_VEHICLES,
// Scenario Edit menu
EDIT_DAY, LEAVE_TOWN, RESET_TOWNS, ADD_OUT_MAPS, ADD_TOWN_MAPS, LEAVE_SCENARIO, SET_SDF,
};
void handle_item_menu(int item_hit);
void handle_menu_choice(eMenu item_hit);
#endif

View File

@@ -17,11 +17,6 @@
using MenuHandle = NSMenu*;
extern void handle_help_menu(int item_hit);
extern void handle_file_menu(int item_hit);
extern void handle_edit_menus(int item_hit);
extern void handle_item_menu(int item_hit);
extern cUniverse univ;
extern fs::path file_in_mem;
extern bool scen_items_loaded;
@@ -29,10 +24,8 @@ MenuHandle menu_bar_handle;
MenuHandle apple_menu, file_menu, reg_menu, extra_menu, items_menu[4];
@interface MenuHandler : NSObject
-(void) fileMenu:(id) sender;
-(void) editMenu:(id) sender;
-(void) itemMenu:(id) sender;
-(void) helpMenu:(id) sender;
-(void) menuChoice:(id) sender;
@end
@interface ItemWrapper : NSObject
@@ -65,31 +58,50 @@ void init_menubar() {
items_menu[2] = [[menu_bar_handle itemWithTitle: @"Items 3"] submenu];
items_menu[3] = [[menu_bar_handle itemWithTitle: @"Items 4"] submenu];
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([apple_menu itemWithTitle: @"About BoE Character Editor"], handler, @selector(helpMenu:), 1);
setMenuCallback([apple_menu itemWithTitle: @"Quit BoE Character Editor"], handler, @selector(fileMenu:), 7);
// TODO: Organize the file menu handling function
setMenuCallback([file_menu itemWithTitle: @"Save"], handler, @selector(fileMenu:), 1);
setMenuCallback([file_menu itemWithTitle: @"Save As…"], handler, @selector(fileMenu:), 2);
setMenuCallback([file_menu itemWithTitle: @"Open…"], handler, @selector(fileMenu:), 3);
setMenuCallback([file_menu itemWithTitle: @"Close"], handler, @selector(fileMenu:), 4);
setMenuCallback([file_menu itemWithTitle: @"Revert to Saved"], handler, @selector(fileMenu:), 5);
static const eMenu file_choices[] = {
eMenu::FILE_OPEN, eMenu::FILE_CLOSE, eMenu::NONE, eMenu::FILE_SAVE, eMenu::FILE_SAVE_AS, eMenu::FILE_REVERT,
};
static const eMenu party_choices[] = {
eMenu::EDIT_GOLD, eMenu::EDIT_FOOD, eMenu::EDIT_ALCHEMY, eMenu::NONE,
eMenu::HEAL_DAMAGE, eMenu::RESTORE_MANA, eMenu::RAISE_DEAD, eMenu::CURE_CONDITIONS, eMenu::NONE,
eMenu::EDIT_MAGE, eMenu::EDIT_PRIEST, eMenu::EDIT_TRAITS, eMenu::EDIT_SKILLS, eMenu::EDIT_XP, eMenu::NONE,
eMenu::REUNITE_PARTY, eMenu::OWN_VEHICLES,
};
static const eMenu scen_choices[] = {
eMenu::EDIT_DAY, eMenu::NONE, eMenu::LEAVE_TOWN, eMenu::RESET_TOWNS, eMenu::ADD_OUT_MAPS, eMenu::ADD_TOWN_MAPS,
eMenu::NONE, eMenu::LEAVE_SCENARIO, eMenu::SET_SDF,
};
for(int i = 0; i < [reg_menu numberOfItems]; i++)
setMenuCallback([reg_menu itemAtIndex: i], handler, @selector(editMenu:), i + 1);
for(int i = 0; i < [extra_menu numberOfItems]; i++)
setMenuCallback([extra_menu itemAtIndex: i], handler, @selector(editMenu:), i + 101);
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([apple_menu itemWithTitle: @"About BoE Character Editor"], handler, @selector(menuChoice:), int(eMenu::ABOUT));
setMenuCallback([apple_menu itemWithTitle: @"Quit BoE Character Editor"], handler, @selector(menuChoice:), int(eMenu::QUIT));
int i = 0;
for(eMenu opt : file_choices)
setMenuCallback([file_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : party_choices)
setMenuCallback([reg_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : scen_choices)
setMenuCallback([extra_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
update_item_menu();
menu_activate();
}
void menu_activate() {
if(file_in_mem.empty())
if(file_in_mem.empty()) {
for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: NO];
else for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Edit Party"] setEnabled: NO];
[[menu_bar_handle itemWithTitle: @"Scenario Edit"] setEnabled: NO];
} else {
for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Edit Party"] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Scenario Edit"] setEnabled: YES];
}
}
void update_item_menu() {
@@ -112,14 +124,6 @@ void update_item_menu() {
}
@implementation MenuHandler
-(void) fileMenu:(id) sender {
handle_file_menu([[sender representedObject] shortValue]);
}
-(void) editMenu:(id) sender {
handle_edit_menus([[sender representedObject] shortValue]);
}
-(void) itemMenu:(id) sender {
ItemWrapper* item = [sender representedObject];
cItemRec& theItem = [item item];
@@ -131,12 +135,10 @@ void update_item_menu() {
}
}
-(void) helpMenu:(id) sender {
int i = [[sender representedObject] intValue];
if(i == 0); // TODO: "BoE Character Editor Help"
else if(i == 1) handle_help_menu(i);
-(void) menuChoice:(id) sender {
eMenu opt = eMenu([[sender representedObject] intValue]);
handle_menu_choice(opt);
}
@end
@implementation ItemWrapper {

View File

@@ -1,5 +1,6 @@
#include "pc.menus.h"
#include <map>
#include <SFML/Graphics/RenderWindow.hpp>
#include "Resource.h"
#include "universe.h"
@@ -24,9 +25,19 @@ extern bool scen_items_loaded;
extern fs::path file_in_mem;
LONG_PTR mainProc;
HMENU menuHandle = NULL;
std::map<int,eMenu> menuChoices;
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam);
void setMenuCommand(HMENU& menu, int i, eMenu cmd) {
MENUITEMINFOA item;
item.cbSize = sizeof(MENUITEMINFOA);
item.fMask = MIIM_ID | MIIM_FTYPE;
GetMenuItemInfoA(menu, i++, true, &item);
if(item.fType == MFT_SEPARATOR) return;
menuChoices[item.wID] = cmd;
}
void init_menubar() {
HWND winHandle = mainPtr.getSystemHandle();
if(winHandle == NULL) return;
@@ -42,6 +53,46 @@ void init_menubar() {
double usableHeight = sz.y - menubarHeight;
sf::View view(sf::FloatRect(0, 0, sz.x, usableHeight));
mainPtr.setView(view);
// And now initialize the mapping from Windows menu commands to eMenu constants
static bool inited = false;
if(inited) return;
inited = true;
static const eMenu file_choices[] = {
eMenu::FILE_OPEN, eMenu::FILE_CLOSE, eMenu::NONE, eMenu::FILE_SAVE, eMenu::FILE_SAVE_AS, eMenu::FILE_REVERT, eMenu::NONE, eMenu::QUIT,
};
static const eMenu party_choices[] = {
eMenu::EDIT_GOLD, eMenu::EDIT_FOOD, eMenu::EDIT_ALCHEMY, eMenu::NONE,
eMenu::HEAL_DAMAGE, eMenu::RESTORE_MANA, eMenu::RAISE_DEAD, eMenu::CURE_CONDITIONS, eMenu::NONE,
eMenu::EDIT_MAGE, eMenu::EDIT_PRIEST, eMenu::EDIT_TRAITS, eMenu::EDIT_SKILLS, eMenu::EDIT_XP, eMenu::NONE,
eMenu::REUNITE_PARTY, eMenu::OWN_VEHICLES,
};
static const eMenu scen_choices[] = {
eMenu::EDIT_DAY, eMenu::NONE, eMenu::LEAVE_TOWN, eMenu::RESET_TOWNS, eMenu::ADD_OUT_MAPS, eMenu::ADD_TOWN_MAPS,
eMenu::NONE, eMenu::LEAVE_SCENARIO, eMenu::SET_SDF,
};
static const eMenu help_choices[] = {
eMenu::ABOUT,
};
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
HMENU party_menu = GetSubMenu(menuHandle, PARTY_MENU_POS);
HMENU scen_menu = GetSubMenu(menuHandle, SCEN_MENU_POS);
HMENU help_menu = GetSubMenu(menuHandle, HELP_MENU_POS);
int i = 0;
for(eMenu opt : file_choices)
setMenuCommand(file_menu, i++, opt);
i = 0;
for(eMenu opt : party_choices)
setMenuCommand(party_menu, i++, opt);
i = 0;
for(eMenu opt : scen_choices)
setMenuCommand(scen_menu, i++, opt);
i = 0;
for(eMenu opt : help_choices)
setMenuCommand(help_menu, i++, opt);
}
void update_item_menu() {
@@ -75,11 +126,6 @@ void menu_activate() {
DrawMenuBar(mainPtr.getSystemHandle());
}
void handle_help_menu(int item_hit);
void handle_file_menu(int item_hit);
void handle_edit_menus(int item_hit);
void handle_item_menu(int item_hit);
#include "cursors.h"
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
@@ -87,40 +133,7 @@ LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lPara
int cmd = LOWORD(wParam);
if(cmd >= 1000) { // Item menus
handle_item_menu(cmd - 1000);
} else switch(cmd) {
// File menu
case IDM_FILE_OPEN: handle_file_menu(3); break;
case IDM_FILE_CLOSE: handle_file_menu(4); break;
case IDM_FILE_SAVE: handle_file_menu(1); break;
case IDM_FILE_SAVE_AS: handle_file_menu(2); break;
case IDM_FILE_REVERT: handle_file_menu(5); break;
case IDM_FILE_QUIT: handle_file_menu(7); break;
// Edit Party menu
case IDM_PARTY_GOLD: handle_edit_menus(1); break;
case IDM_PARTY_FOOD: handle_edit_menus(2); break;
case IDM_PARTY_ALCHEMY: handle_edit_menus(3); break;
case IDM_PARTY_DAMAGE: handle_edit_menus(5); break;
case IDM_PARTY_MANA: handle_edit_menus(6); break;
case IDM_PARTY_DEAD: handle_edit_menus(7); break;
case IDM_PARTY_CONDITIONS: handle_edit_menus(8); break;
case IDM_PARTY_REUNITE: handle_edit_menus(10); break;
case IDM_PARTY_VEHICLES: handle_edit_menus(11); break;
case IDM_PARTY_MAGE: handle_edit_menus(13); break;
case IDM_PARTY_PRIEST: handle_edit_menus(14); break;
case IDM_PARTY_TRAITS: handle_edit_menus(15); break;
case IDM_PARTY_SKILLS: handle_edit_menus(16); break;
case IDM_PARTY_XP: handle_edit_menus(17); break;
// Scenario Editing menu
case IDM_SCEN_DAY: handle_edit_menus(101); break;
case IDM_SCEN_LEAVE_TOWN: handle_edit_menus(103); break;
case IDM_SCEN_TOWN_RESET: handle_edit_menus(104); break;
case IDM_SCEN_TOWN_MAP: handle_edit_menus(105); break;
case IDM_SCEN_OUT_MAP: handle_edit_menus(106); break;
case IDM_SCEN_LEAVE: handle_edit_menus(108); break;
case IDM_SCEN_SDF: handle_edit_menus(109); break;
// Help menu
case IDM_HELP: handle_help_menu(1);
}
} else handle_menu_choice(menuChoices[cmd]);
} else if(message == WM_SETCURSOR) {
// Windows resets the cursor to an arrow whenever the mouse moves, unless we do this.
// Note: By handling this message, sf::Window::setMouseCursorVisible() will NOT work.

View File

@@ -211,15 +211,6 @@ void shut_down_menus(short mode) {
DrawMenuBar(mainPtr.getSystemHandle());
}
void handle_file_menu(int item_hit);
void handle_edit_menu(int item_hit);
void handle_scenario_menu(int item_hit);
void handle_town_menu(int item_hit);
void handle_outdoor_menu(int item_hit);
void handle_item_menu(int item_hit);
void handle_monst_menu(int item_hit);
void handle_help_menu(int item_hit);
#include "cursors.h"
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {

View File

@@ -836,6 +836,12 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo
}
if(in_scen) {
fs::path path;
path = progDir/"Blades of Exile Scenarios"/univ.party.scen_name;
if(!load_scenario(path, univ.scenario))
return false;
if(town_restore) {
// Load town data
std::istream& fin = partyIn.getFile("save/town.txt");