Rename osx directory to src since it's now the official source base
This commit is contained in:
45
src/pcedit/Blades of Exile Character Editor-Info.plist
Normal file
45
src/pcedit/Blades of Exile Character Editor-Info.plist
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>.exg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>boesave</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>SavedGame</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>beSV</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
<key>NSPersistentStoreTypeKey</key>
|
||||
<string>Binary</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>BoECharEd</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.spidweb.boepceditor</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>blxe</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
src/pcedit/BoECharEd.icns
Normal file
BIN
src/pcedit/BoECharEd.icns
Normal file
Binary file not shown.
BIN
src/pcedit/Mac-Mainscreen.sav
Normal file
BIN
src/pcedit/Mac-Mainscreen.sav
Normal file
Binary file not shown.
BIN
src/pcedit/Mac-Valleydy-Outdoors.sav
Normal file
BIN
src/pcedit/Mac-Valleydy-Outdoors.sav
Normal file
Binary file not shown.
BIN
src/pcedit/Mac-Valleydy-Town.sav
Normal file
BIN
src/pcedit/Mac-Valleydy-Town.sav
Normal file
Binary file not shown.
BIN
src/pcedit/bladespced.rsrc
Normal file
BIN
src/pcedit/bladespced.rsrc
Normal file
Binary file not shown.
After Width: | Height: | Size: 102 KiB |
286
src/pcedit/pc.action.cpp
Normal file
286
src/pcedit/pc.action.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "pc.graphics.h"
|
||||
#include "pc.global.h"
|
||||
#include "classes.h"
|
||||
#include "pc.editors.h"
|
||||
#include "pc.fileio.h"
|
||||
#include "pc.action.h"
|
||||
#include "graphtool.h"
|
||||
#include "soundtool.h"
|
||||
#include "mathutil.h"
|
||||
#include "dlogutil.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
/* Adventure globals */
|
||||
//extern party_record_type party;
|
||||
//extern outdoor_record_type outdoors[2][2];
|
||||
//extern current_town_type c_town;
|
||||
//extern big_tr_type t_d;
|
||||
//extern town_item_list t_i;
|
||||
//extern unsigned char out[96][96],out_e[96][96];
|
||||
//extern setup_save_type setup_save;
|
||||
//extern stored_items_list_type stored_items[3];
|
||||
//extern stored_town_maps_type town_maps;
|
||||
//extern stored_outdoor_maps_type o_maps;
|
||||
extern cUniverse univ;
|
||||
|
||||
//extern bool ed_reg;
|
||||
//extern long ed_flag,ed_key;
|
||||
|
||||
extern sf::RenderWindow mainPtr;
|
||||
extern bool file_in_mem;
|
||||
//extern long register_flag;
|
||||
|
||||
extern sf::Texture pc_gworld;
|
||||
extern bool diff_depth_ok;
|
||||
|
||||
|
||||
|
||||
short which_pc_displayed,store_pc_trait_mode,store_which_to_edit;
|
||||
extern short current_active_pc;
|
||||
char empty_string[256] = " ";
|
||||
extern rectangle pc_area_buttons[6][4] ; // 0 - whole 1 - pic 2 - name 3 - stat strs 4,5 - later
|
||||
extern rectangle item_string_rects[24][4]; // 0 - name 1 - drop 2 - id 3 -
|
||||
extern rectangle pc_info_rect;
|
||||
extern rectangle name_rect;
|
||||
|
||||
extern rectangle pc_race_rect;
|
||||
extern rectangle edit_rect[5][2];
|
||||
|
||||
|
||||
|
||||
//extern rectangle pc_area_buttons[6][6] ; // 0 - whole 1 - pic 2 - name 3 - stat strs 4,5 - later
|
||||
//extern rectangle item_string_rects[24][4]; // 0 - name 1 - drop 2 - id 3 -
|
||||
//short mode; // ignore,
|
||||
bool handle_action(sf::Event event) {
|
||||
short i;
|
||||
|
||||
location the_point;
|
||||
|
||||
bool to_return = false;
|
||||
|
||||
the_point = {event.mouseButton.x, event.mouseButton.y};
|
||||
|
||||
if(!file_in_mem)
|
||||
return false;
|
||||
|
||||
for(i = 0; i < 6; i++)
|
||||
if((the_point.in(pc_area_buttons[i][0])) &&
|
||||
(univ.party[i].main_status != eMainStatus::ABSENT)) {
|
||||
do_button_action(0,i);
|
||||
current_active_pc = i;
|
||||
redraw_screen();
|
||||
}
|
||||
for(i = 0; i < 5; i++)
|
||||
if((the_point.in(edit_rect[i][0])) &&
|
||||
(univ.party[current_active_pc].main_status != eMainStatus::ABSENT)) {
|
||||
do_button_action(0,i + 10);
|
||||
switch(i) {
|
||||
case 0:
|
||||
display_pc(current_active_pc,0,NULL);
|
||||
break;
|
||||
case 1:
|
||||
display_pc(current_active_pc,1,NULL);
|
||||
break;
|
||||
case 2:
|
||||
pick_race_abil(&univ.party[current_active_pc],0);
|
||||
break;
|
||||
case 3:
|
||||
spend_xp(current_active_pc,1,NULL);
|
||||
break;
|
||||
case 4:
|
||||
edit_xp(&univ.party[current_active_pc]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 24; i++)
|
||||
if((the_point.in(item_string_rects[i][1])) && // drop item
|
||||
univ.party[current_active_pc].items[i].variety != eItemType::NO_ITEM) {
|
||||
flash_rect(item_string_rects[i][1]);
|
||||
take_item(current_active_pc,i);
|
||||
}
|
||||
for(i = 0; i < 24; i++)
|
||||
if((the_point.in(item_string_rects[i][2])) && // identify item
|
||||
univ.party[current_active_pc].items[i].variety != eItemType::NO_ITEM) {
|
||||
flash_rect(item_string_rects[i][2]);
|
||||
univ.party[current_active_pc].items[i].ident = true;
|
||||
}
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void flash_rect(rectangle /*to_flash*/) {
|
||||
|
||||
// TODO: Think of a good way to do this
|
||||
//InvertRect (&to_flash);
|
||||
play_sound(37);
|
||||
sf::sleep(time_in_ticks(5));
|
||||
}
|
||||
|
||||
static bool get_num_event_filter(cDialog& me, std::string id, eKeyMod) {
|
||||
me.toast(id == "okay");
|
||||
me.setResult<long long>(me["number"].getTextAsNum());
|
||||
return true;
|
||||
}
|
||||
|
||||
//0 - gold 1 - food
|
||||
void edit_gold_or_food(short which_to_edit) {
|
||||
|
||||
location view_loc;
|
||||
|
||||
store_which_to_edit = which_to_edit;
|
||||
|
||||
make_cursor_sword();
|
||||
cDialog dlog("get-num");
|
||||
dlog["okay"].attachClickHandler(get_num_event_filter);
|
||||
if(which_to_edit == 0)
|
||||
dlog["prompt"].setText("How much gold do you want?");
|
||||
else dlog["prompt"].setText("How much food do you want?");
|
||||
dlog["number"].setTextToNum((which_to_edit == 0) ? univ.party.gold : univ.party.food);
|
||||
|
||||
dlog.run();
|
||||
int dialog_answer = minmax(0,25000,dlog.getResult<long long>());
|
||||
if(which_to_edit == 0)
|
||||
univ.party.gold = dialog_answer;
|
||||
else
|
||||
univ.party.food = dialog_answer;
|
||||
}
|
||||
|
||||
void edit_day() {
|
||||
|
||||
location view_loc;
|
||||
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
cDialog dlog("edit-day");
|
||||
dlog["okay"].attachClickHandler(get_num_event_filter);
|
||||
|
||||
dlog["number"].setTextToNum(((univ.party.age) / 3700) + 1);
|
||||
|
||||
dlog.run();
|
||||
|
||||
long long dialog_answer = minmax(0,500,dlog.getResult<long long>());
|
||||
|
||||
univ.party.age = (long long) (3700) * (long long) (dialog_answer);
|
||||
}
|
||||
|
||||
void combine_things(short pc_num) {
|
||||
short i,j,test;
|
||||
|
||||
for(i = 0; i < 24; i++) {
|
||||
if(univ.party[pc_num].items[i].variety != eItemType::NO_ITEM &&
|
||||
(univ.party[pc_num].items[i].type_flag > 0) && (univ.party[pc_num].items[i].ident)) {
|
||||
for(j = i + 1; j < 24; j++)
|
||||
if(univ.party[pc_num].items[j].variety != eItemType::NO_ITEM &&
|
||||
(univ.party[pc_num].items[j].type_flag == univ.party[pc_num].items[i].type_flag)
|
||||
&& (univ.party[pc_num].items[j].ident)) {
|
||||
// add_string_to_buf("(items combined)");
|
||||
test = (short) (univ.party[pc_num].items[i].charges) + (short) (univ.party[pc_num].items[j].charges);
|
||||
if(test > 125) {
|
||||
univ.party[pc_num].items[i].charges = 125;
|
||||
// ASB("Can have at most 125 of any item.");
|
||||
}
|
||||
else univ.party[pc_num].items[i].charges += univ.party[pc_num].items[j].charges;
|
||||
if(univ.party[pc_num].equip[j]) {
|
||||
univ.party[pc_num].equip[i] = true;
|
||||
univ.party[pc_num].equip[j] = false;
|
||||
}
|
||||
take_item(pc_num,j);
|
||||
}
|
||||
}
|
||||
if(univ.party[pc_num].items[i].variety != eItemType::NO_ITEM && univ.party[pc_num].items[i].charges < 0)
|
||||
univ.party[pc_num].items[i].charges = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool give_to_pc(short pc_num,cItemRec item, short /*print_result*/) {
|
||||
short free_space;
|
||||
|
||||
if(item.variety == eItemType::NO_ITEM)
|
||||
return true;
|
||||
if((free_space = pc_has_space(pc_num)) == 24 || univ.party[pc_num].main_status != eMainStatus::ALIVE)
|
||||
return false;
|
||||
else {
|
||||
univ.party[pc_num].items[free_space] = item;
|
||||
combine_things(pc_num);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool give_to_party(cItemRec item,short print_result) {
|
||||
short i = 0;
|
||||
|
||||
while(i < 6) {
|
||||
if(give_to_pc(i,item,print_result))
|
||||
return true;
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void give_gold(short amount,bool /*print_result*/) {
|
||||
univ.party.gold = univ.party.gold + amount;
|
||||
}
|
||||
|
||||
bool take_gold(short amount,bool /*print_result*/) {
|
||||
if(univ.party.gold < amount)
|
||||
return false;
|
||||
univ.party.gold = univ.party.gold - amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
short pc_has_space(short pc_num) {
|
||||
short i = 0;
|
||||
|
||||
while(i < 24) {
|
||||
if(univ.party[pc_num].items[i].variety == eItemType::NO_ITEM)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return 24;
|
||||
}
|
||||
|
||||
//short pc_num,which_item; // if which_item > 20, don't update stat win, item is which_item - 20
|
||||
void take_item(short pc_num,short which_item) {
|
||||
short i;
|
||||
|
||||
if(univ.party[pc_num].weap_poisoned == which_item && univ.party[pc_num].status[eStatus::POISONED_WEAPON] > 0) {
|
||||
// add_string_to_buf(" Poison lost. ");
|
||||
univ.party[pc_num].status[eStatus::POISONED_WEAPON] = 0;
|
||||
}
|
||||
if(univ.party[pc_num].weap_poisoned > which_item && univ.party[pc_num].status[eStatus::POISONED_WEAPON] > 0)
|
||||
univ.party[pc_num].weap_poisoned--;
|
||||
|
||||
for(i = which_item; i < 23; i++) {
|
||||
univ.party[pc_num].items[i] = univ.party[pc_num].items[i + 1];
|
||||
univ.party[pc_num].equip[i] = univ.party[pc_num].equip[i + 1];
|
||||
}
|
||||
univ.party[pc_num].items[23].variety = eItemType::NO_ITEM;
|
||||
univ.party[pc_num].equip[23] = false;
|
||||
|
||||
}
|
||||
|
||||
void edit_xp(cPlayer *pc) {
|
||||
location view_loc;
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
cDialog dlog("edit-xp");
|
||||
dlog["okay"].attachClickHandler(get_num_event_filter);
|
||||
|
||||
dlog["number"].setTextToNum(pc->experience);
|
||||
dlog["perlevel"].setTextToNum(pc->get_tnl());
|
||||
|
||||
dlog.run();
|
||||
|
||||
int dialog_answer = minmax(0,10000,abs(dlog.getResult<long long>()));
|
||||
|
||||
pc->experience = dialog_answer;
|
||||
}
|
||||
|
||||
|
12
src/pcedit/pc.action.h
Normal file
12
src/pcedit/pc.action.h
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
#include <SFML/Window/Event.hpp>
|
||||
#include "dialog.hpp"
|
||||
|
||||
bool handle_action(sf::Event event);
|
||||
void flash_rect(rectangle to_flash);
|
||||
void edit_gold_or_food(short which_to_edit);
|
||||
void display_pc(short pc_num,short mode,cDialog* parent);
|
||||
void display_alchemy(bool allowEdit);
|
||||
bool spend_xp(short pc_num, short mode, cDialog* parent);
|
||||
void edit_day();
|
||||
void edit_xp(cPlayer *pc);
|
43
src/pcedit/pc.appleevents.mm
Normal file
43
src/pcedit/pc.appleevents.mm
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// pc.appleevents.mm
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 14-04-16.
|
||||
//
|
||||
//
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
extern bool verify_restore_quit(bool mode);
|
||||
extern bool All_Done;
|
||||
|
||||
typedef NSAppleEventDescriptor AEDescr;
|
||||
|
||||
@interface AppleEventHandler : NSObject
|
||||
-(void)handleOpenDoc:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply;
|
||||
-(void)handleQuit:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply;
|
||||
@end
|
||||
|
||||
void set_up_apple_events(); // Suppress "no prototype" warning
|
||||
void set_up_apple_events() {
|
||||
AppleEventHandler* aeHandler = [[AppleEventHandler alloc] init];
|
||||
NSAppleEventManager* AEmgr = [NSAppleEventManager sharedAppleEventManager];
|
||||
[AEmgr setEventHandler: aeHandler andSelector: @selector(handleOpenDoc:withReply:)
|
||||
forEventClass: kCoreEventClass andEventID: kAEOpenDocuments];
|
||||
[AEmgr setEventHandler: aeHandler andSelector: @selector(handleQuit:withReply:)
|
||||
forEventClass: kCoreEventClass andEventID: kAEQuitApplication];
|
||||
}
|
||||
|
||||
@implementation AppleEventHandler
|
||||
-(void)handleOpenDoc:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply {
|
||||
(void) theAppleEvent; // Suppress "unused parameter" warning
|
||||
(void) reply;
|
||||
// TODO: Handle this
|
||||
}
|
||||
-(void)handleQuit:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply {
|
||||
(void) theAppleEvent; // Suppress "unused parameter" warning
|
||||
(void) reply;
|
||||
All_Done = verify_restore_quit(0);
|
||||
}
|
||||
@end
|
||||
|
631
src/pcedit/pc.editors.cpp
Normal file
631
src/pcedit/pc.editors.cpp
Normal file
@@ -0,0 +1,631 @@
|
||||
|
||||
#include "pc.graphics.h"
|
||||
#include "pc.global.h"
|
||||
#include "classes.h"
|
||||
#include "pc.editors.h"
|
||||
#include "graphtool.h"
|
||||
#include "dialog.hpp"
|
||||
#include "control.hpp"
|
||||
#include "button.hpp"
|
||||
#include "dlogutil.hpp"
|
||||
#include "winutil.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
/*
|
||||
* These three are not declared in any included header.
|
||||
* Instead they are declared in pc.actions.h, which is not
|
||||
* included here because it contains additional functions that
|
||||
* should not be available to the game (which also includes
|
||||
* this file).
|
||||
*
|
||||
* For the game's purposes, these are declared in
|
||||
* boe.infodlg.h and boe.party.h.
|
||||
*/
|
||||
void display_pc(short pc_num,short mode,cDialog* parent);
|
||||
void display_alchemy(bool allowEdit);
|
||||
bool spend_xp(short pc_num, short mode, cDialog* parent);
|
||||
// TODO: There's probably a more logical way of arranging this
|
||||
|
||||
/* Adventure globals */
|
||||
//extern party_record_type party;
|
||||
//extern outdoor_record_type outdoors[2][2];
|
||||
//extern current_town_type c_town;
|
||||
//extern big_tr_type t_d;
|
||||
//extern town_item_list t_i;
|
||||
//extern unsigned char out[96][96],out_e[96][96];
|
||||
//extern setup_save_type setup_save;
|
||||
//extern stored_items_list_type stored_items[3];
|
||||
extern cUniverse univ;
|
||||
|
||||
extern short store_flags[3];
|
||||
|
||||
extern short current_active_pc;
|
||||
|
||||
extern sf::RenderWindow mainPtr;
|
||||
extern rectangle d_rects[80];
|
||||
extern short d_rect_index[80];
|
||||
|
||||
extern bool diff_depth_ok,current_file_has_maps;
|
||||
bool choice_active[6];
|
||||
|
||||
extern short which_pc_displayed;
|
||||
cPlayer *store_pc;
|
||||
sf::Texture button_num_gworld;
|
||||
|
||||
std::map<eSkill,short> skill_cost = {
|
||||
{eSkill::STRENGTH,3}, {eSkill::DEXTERITY,3}, {eSkill::INTELLIGENCE,3},
|
||||
{eSkill::EDGED_WEAPONS,2}, {eSkill::BASHING_WEAPONS,2}, {eSkill::POLE_WEAPONS,2},
|
||||
{eSkill::THROWN_MISSILES,1}, {eSkill::ARCHERY,2}, {eSkill::DEFENSE,2},
|
||||
{eSkill::MAGE_SPELLS,6}, {eSkill::PRIEST_SPELLS,5}, {eSkill::MAGE_LORE,1},
|
||||
{eSkill::ALCHEMY,2}, {eSkill::ITEM_LORE,4}, {eSkill::DISARM_TRAPS,2},
|
||||
{eSkill::LOCKPICKING,1}, {eSkill::ASSASSINATION,4}, {eSkill::POISON,2},
|
||||
{eSkill::LUCK,5},
|
||||
};
|
||||
std::map<eSkill,short> skill_max = {
|
||||
{eSkill::STRENGTH,20}, {eSkill::DEXTERITY,20}, {eSkill::INTELLIGENCE,20},
|
||||
{eSkill::EDGED_WEAPONS,20}, {eSkill::BASHING_WEAPONS,20}, {eSkill::POLE_WEAPONS,20},
|
||||
{eSkill::THROWN_MISSILES,20}, {eSkill::ARCHERY,20}, {eSkill::DEFENSE,20},
|
||||
{eSkill::MAGE_SPELLS,7}, {eSkill::PRIEST_SPELLS,7}, {eSkill::MAGE_LORE,20},
|
||||
{eSkill::ALCHEMY,20}, {eSkill::ITEM_LORE,10}, {eSkill::DISARM_TRAPS,20},
|
||||
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,20}, {eSkill::POISON,20},
|
||||
{eSkill::LUCK,20},
|
||||
};
|
||||
std::map<eSkill,short> skill_g_cost = {
|
||||
{eSkill::STRENGTH,50}, {eSkill::DEXTERITY,503}, {eSkill::INTELLIGENCE,50},
|
||||
{eSkill::EDGED_WEAPONS,40}, {eSkill::BASHING_WEAPONS,40}, {eSkill::POLE_WEAPONS,40},
|
||||
{eSkill::THROWN_MISSILES,30}, {eSkill::ARCHERY,50}, {eSkill::DEFENSE,40},
|
||||
{eSkill::MAGE_SPELLS,250}, {eSkill::PRIEST_SPELLS,250}, {eSkill::MAGE_LORE,25},
|
||||
{eSkill::ALCHEMY,100}, {eSkill::ITEM_LORE,200}, {eSkill::DISARM_TRAPS,30},
|
||||
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,100}, {eSkill::POISON,80},
|
||||
{eSkill::LUCK,0},
|
||||
};
|
||||
// The index here is the skill's level, not the skill itself; thus 20 is the max index since no spell can go above 20.
|
||||
short skill_bonus[21] = {
|
||||
-3,-3,-2,-1,0,0,1,1,1,2,
|
||||
2,2,3,3,3,3,4,4,4,5,5};
|
||||
|
||||
// These are the IDs used to refer to the skills in the dialog
|
||||
const char* skill_ids[19] = {
|
||||
"str","dex","int",
|
||||
"edge","bash","pole","thrown","bow","def",
|
||||
"mage","priest","lore","alch","item",
|
||||
"trap","lock","assassin","poison","luck"
|
||||
};
|
||||
|
||||
// Variables for spending xp
|
||||
bool talk_done = false;
|
||||
long val_for_text;
|
||||
bool keep_change = false;
|
||||
short store_h,store_sp,i,store_skp;
|
||||
long store_g;
|
||||
short store_train_mode,store_train_pc;
|
||||
|
||||
static bool select_pc_event_filter (cDialog& me, std::string item_hit, eKeyMod) {
|
||||
me.toast(true);
|
||||
if(item_hit != "cancel") {
|
||||
short which_pc = item_hit[item_hit.length() - 1] - '1';
|
||||
me.setResult<short>(which_pc);
|
||||
} else me.setResult<short>(6);
|
||||
return true;
|
||||
}
|
||||
|
||||
//active_only; // 0 - no 1 - yes 2 - disarm trap
|
||||
short char_select_pc(short active_only,short free_inv_only,const char *title) {
|
||||
short item_hit,i;
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
cDialog selectPc("select-pc");
|
||||
selectPc.attachClickHandlers(select_pc_event_filter, {"cancel", "pick1", "pick2", "pick3", "pick4", "pick5", "pick6"});
|
||||
|
||||
selectPc["title"].setText(title);
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
std::string n = boost::lexical_cast<std::string>(i + 1);
|
||||
if(univ.party[i].main_status == eMainStatus::ABSENT ||
|
||||
(active_only && univ.party[i].main_status > eMainStatus::ALIVE) ||
|
||||
(free_inv_only == 1 && pc_has_space(i) == 24) || univ.party[i].main_status == eMainStatus::FLED) {
|
||||
selectPc["pick" + n].hide();
|
||||
}
|
||||
// TODO: Wouldn't this lead to blank name fields for non-active characters if those characters are allowed?
|
||||
if(univ.party[i].main_status != eMainStatus::ABSENT) {
|
||||
selectPc["pc" + n].setText(univ.party[i].name);
|
||||
}
|
||||
else selectPc["pc" + n].hide();
|
||||
}
|
||||
|
||||
selectPc.run();
|
||||
item_hit = selectPc.getResult<short>();
|
||||
|
||||
return item_hit;
|
||||
}
|
||||
|
||||
//active_only; // 0 - no 1 - yes 2 - disarm trap
|
||||
short select_pc(short active_only,short free_inv_only) {
|
||||
if(active_only == 2)
|
||||
return char_select_pc(active_only,free_inv_only,"Trap! Who will disarm?");
|
||||
else return char_select_pc(active_only,free_inv_only,"Select a character:");
|
||||
}
|
||||
|
||||
static short party_total_level() {
|
||||
short i,j = 0;
|
||||
|
||||
for(i = 0; i < 6; i++)
|
||||
if(univ.party[i].main_status == eMainStatus::ALIVE)
|
||||
j += univ.party[i].level;
|
||||
return j;
|
||||
}
|
||||
|
||||
static void put_pc_spells(cDialog& me, const short store_trait_mode) {
|
||||
short i;
|
||||
|
||||
for(i = 0; i < 62; i++) {
|
||||
std::string id = "spell" + boost::lexical_cast<std::string>(i + 1);
|
||||
cLed& cur = dynamic_cast<cLed&>(me[id]);
|
||||
if(((store_trait_mode == 0) && univ.party[which_pc_displayed].mage_spells[i]) ||
|
||||
((store_trait_mode == 1) && univ.party[which_pc_displayed].priest_spells[i]))
|
||||
cur.setState(led_red);
|
||||
else cur.setState(led_off);
|
||||
}
|
||||
|
||||
me["who"].setText(univ.party[which_pc_displayed].name.c_str());
|
||||
}
|
||||
|
||||
static bool display_pc_event_filter(cDialog& me, std::string item_hit, const short trait_mode) {
|
||||
short pc_num;
|
||||
|
||||
pc_num = which_pc_displayed;
|
||||
if(item_hit == "done") {
|
||||
me.toast(true);
|
||||
} else if(item_hit == "left") {
|
||||
do {
|
||||
pc_num = (pc_num == 0) ? 5 : pc_num - 1;
|
||||
} while(univ.party[pc_num].main_status == eMainStatus::ABSENT);
|
||||
which_pc_displayed = pc_num;
|
||||
put_pc_spells(me, trait_mode);
|
||||
} else if(item_hit == "right") {
|
||||
do {
|
||||
pc_num = (pc_num == 5) ? 0 : pc_num + 1;
|
||||
} while(univ.party[pc_num].main_status == eMainStatus::ABSENT);
|
||||
which_pc_displayed = pc_num;
|
||||
put_pc_spells(me, trait_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void display_pc(short pc_num,short mode, cDialog* parent) {
|
||||
using namespace std::placeholders;
|
||||
short i;
|
||||
std::string label_str;
|
||||
|
||||
if(univ.party[pc_num].main_status == eMainStatus::ABSENT) {
|
||||
for(pc_num = 0; pc_num < 6; pc_num++)
|
||||
if(univ.party[pc_num].main_status == eMainStatus::ALIVE)
|
||||
break;
|
||||
}
|
||||
which_pc_displayed = pc_num;
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
cDialog pcInfo("pc-spell-info", parent);
|
||||
pcInfo.attachClickHandlers(std::bind(display_pc_event_filter, _1, _2, mode),{"done","left","right"});
|
||||
|
||||
for(i = 0; i < 62; i++) {
|
||||
std::string id = "spell" + boost::lexical_cast<std::string>(i + 1);
|
||||
label_str = get_str("magic-names", i + (mode == 0 ? 1 : 101));
|
||||
pcInfo[id].setText(label_str);
|
||||
}
|
||||
put_pc_spells(pcInfo, mode);
|
||||
|
||||
dynamic_cast<cPict&>(pcInfo["pic"]).setPict(14 + mode,PIC_DLOG);
|
||||
|
||||
pcInfo.run();
|
||||
}
|
||||
|
||||
static void display_traits_graphics(cDialog& me) {
|
||||
short i,store;
|
||||
|
||||
std::string race = "race" + boost::lexical_cast<std::string>(int(store_pc->race) + 1);
|
||||
dynamic_cast<cLedGroup&>(me["race"]).setSelected(race);
|
||||
for(i = 0; i < 10; i++) {
|
||||
std::string id = "good" + boost::lexical_cast<std::string>(i + 1);
|
||||
eTrait trait = eTrait(i);
|
||||
dynamic_cast<cLed&>(me[id]).setState((store_pc->traits[trait] > 0) ? led_red : led_off);
|
||||
}
|
||||
for(i = 0; i < 5; i++) {
|
||||
// TODO: Pacifist
|
||||
std::string id = "bad" + boost::lexical_cast<std::string>(i + 1);
|
||||
eTrait trait = eTrait(i + 10);
|
||||
dynamic_cast<cLed&>(me[id]).setState((store_pc->traits[trait] > 0) ? led_red : led_off);
|
||||
}
|
||||
|
||||
store = store_pc->get_tnl();
|
||||
me["xp"].setTextToNum(store);
|
||||
}
|
||||
|
||||
static bool pick_race_select_led(cDialog& me, std::string item_hit, bool losing, const short store_trait_mode) {
|
||||
int abil_str = 0;
|
||||
cPlayer *pc;
|
||||
|
||||
pc = store_pc;
|
||||
if(item_hit == "race") {
|
||||
item_hit = dynamic_cast<cLedGroup&>(me["race"]).getSelected();
|
||||
eRace race;
|
||||
switch(item_hit[4] - '1') {
|
||||
case 0: race = eRace::HUMAN; break;
|
||||
case 1: race = eRace::NEPHIL; break;
|
||||
case 2: race = eRace::SLITH; break;
|
||||
case 3: race = eRace::VAHNATAI; break;
|
||||
}
|
||||
if(store_trait_mode == 0)
|
||||
pc->race = race;
|
||||
display_traits_graphics(me);
|
||||
abil_str = 34 + int(race) * 2;
|
||||
} else if(item_hit.substr(0,3) == "bad") {
|
||||
int hit = item_hit[3] - '1';
|
||||
eTrait trait = eTrait(hit + 10);
|
||||
if(store_trait_mode != 1)
|
||||
pc->traits[trait] = !pc->traits[trait];
|
||||
display_traits_graphics(me);
|
||||
abil_str = 22 + hit * 2;
|
||||
} else if(item_hit.substr(0,4) == "good") {
|
||||
int hit = item_hit[4] - '1';
|
||||
eTrait trait = eTrait(hit);
|
||||
if(store_trait_mode != 1)
|
||||
pc->traits[trait] = !pc->traits[trait];
|
||||
display_traits_graphics(me);
|
||||
abil_str = 2 + hit * 2;
|
||||
}
|
||||
if(abil_str > 0)
|
||||
me["info"].setText(get_str("traits", abil_str));
|
||||
return store_trait_mode == 0;
|
||||
}
|
||||
|
||||
//mode; // 0 - edit 1 - just display 2 - can't change race
|
||||
void pick_race_abil(cPlayer *pc,short mode) {
|
||||
using namespace std::placeholders;
|
||||
static const char*const start_str1 = "Click on button by name for description.";
|
||||
static const char*const start_str2 = "Click on advantage button to add/remove.";
|
||||
|
||||
store_pc = pc;
|
||||
make_cursor_sword();
|
||||
|
||||
cDialog pickAbil("pick-race-abil");
|
||||
pickAbil["done"].attachClickHandler(std::bind(&cDialog::toast, &pickAbil, true));
|
||||
auto led_selector = std::bind(pick_race_select_led, _1, _2, _3, mode);
|
||||
pickAbil.attachFocusHandlers(led_selector, {"race", "bad1", "bad2", "bad3", "bad4", "bad5"});
|
||||
pickAbil.attachFocusHandlers(led_selector, {"good1", "good2", "good3", "good4", "good5"});
|
||||
pickAbil.attachFocusHandlers(led_selector, {"good6", "good7", "good8", "good9", "good10"});
|
||||
|
||||
display_traits_graphics(pickAbil);
|
||||
if(mode == 1)
|
||||
pickAbil["info"].setText(start_str1);
|
||||
else pickAbil["info"].setText(start_str2);
|
||||
|
||||
pickAbil.run();
|
||||
}
|
||||
|
||||
short alch_difficulty[20] = {
|
||||
1,1,1,3,3,
|
||||
4,5,5,7,9,
|
||||
9,10,12,12,9,
|
||||
14,19,10,16,20
|
||||
};
|
||||
|
||||
void display_alchemy(bool allowEdit) {
|
||||
short i;
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
cChoiceDlog showAlch("pc-alchemy-info", {"done"});
|
||||
|
||||
for(i = 0; i < 20; i++) {
|
||||
std::string id = "potion" + boost::lexical_cast<std::string>(i + 1);
|
||||
std::string name = get_str("magic-names", i + 200) + " (";
|
||||
name += std::to_string(alch_difficulty[i]);
|
||||
name += ')';
|
||||
showAlch->addLabelFor(id, name, LABEL_LEFT, 83, true);
|
||||
if(!allowEdit)
|
||||
showAlch->getControl(id).attachClickHandler(&cLed::noAction);
|
||||
cLed& led = dynamic_cast<cLed&>(showAlch->getControl(id));
|
||||
if(univ.party.alchemy[i] > 0)
|
||||
led.setState(led_red);
|
||||
else led.setState(led_off);
|
||||
}
|
||||
|
||||
showAlch.show();
|
||||
if(!allowEdit) return;
|
||||
|
||||
for(i = 0; i < 20; i++) {
|
||||
std::string id = "potion" + boost::lexical_cast<std::string>(i + 1);
|
||||
cLed& led = dynamic_cast<cLed&>(showAlch->getControl(id));
|
||||
if(led.getState() == led_red) univ.party.alchemy[i] = true;
|
||||
else univ.party.alchemy[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This dialog needs some kind of context system really badly to avoid the rampant globals
|
||||
// MARK: Start spend XP dialog
|
||||
static void do_xp_keep(short pc_num,short mode,std::map<eSkill,short>& store_skills) {
|
||||
for(i = 0; i < 19; i++) {
|
||||
eSkill skill = eSkill(i);
|
||||
univ.party[pc_num].skills[skill] = store_skills[skill];
|
||||
}
|
||||
univ.party[pc_num].cur_health += store_h - univ.party[pc_num].max_health;
|
||||
univ.party[pc_num].max_health = store_h;
|
||||
univ.party[pc_num].cur_sp += store_sp - univ.party[pc_num].max_sp;
|
||||
univ.party[pc_num].max_sp = store_sp;
|
||||
if(mode == 1)
|
||||
univ.party.gold = store_g;
|
||||
univ.party[pc_num].skill_pts = store_skp;
|
||||
|
||||
}
|
||||
|
||||
static void draw_xp_skills(cDialog& me,std::map<eSkill,short>& store_skills) {
|
||||
short i;
|
||||
// TODO: Wouldn't it make more sense for it to be red when you can't buy the skill rather than red when you can?
|
||||
for(i = 0; i < 19; i++) {
|
||||
cControl& cur = me[skill_ids[i]];
|
||||
eSkill skill = eSkill(i);
|
||||
if((store_skp >= skill_cost[skill]) && (store_g >= skill_g_cost[skill]))
|
||||
cur.setColour(sf::Color::Red);
|
||||
else cur.setColour(me.getDefTextClr());
|
||||
cur.setTextToNum(store_skills[skill]);
|
||||
}
|
||||
|
||||
cControl& sp = me["sp"];
|
||||
cControl& hp = me["hp"];
|
||||
if((store_skp >= 1) && (store_g >= 10))
|
||||
hp.setColour(sf::Color::Red);
|
||||
else hp.setColour(me.getDefTextClr());
|
||||
hp.setTextToNum(store_h);
|
||||
if((store_skp >= 1) && (store_g >= 15))
|
||||
sp.setColour(sf::Color::Red);
|
||||
else sp.setColour(me.getDefTextClr());
|
||||
sp.setTextToNum(store_sp);
|
||||
}
|
||||
|
||||
static void update_gold_skills(cDialog& me) {
|
||||
me["gold"].setTextToNum(((store_train_mode == 0) ? 0 : store_g));
|
||||
me["skp"].setTextToNum(store_skp);
|
||||
}
|
||||
|
||||
|
||||
static void do_xp_draw(cDialog& me,std::map<eSkill,short>& store_skills) {
|
||||
|
||||
char get_text[256];
|
||||
short mode,pc_num;
|
||||
|
||||
mode = store_train_mode;
|
||||
pc_num = store_train_pc;
|
||||
if(mode == 0) {
|
||||
if(univ.party[pc_num].main_status == eMainStatus::ALIVE)
|
||||
sprintf((char *) get_text, "%s",(char *) univ.party[pc_num].name.c_str());
|
||||
else sprintf((char *) get_text, "New PC");
|
||||
}
|
||||
else sprintf((char *) get_text, "%s",(char *) univ.party[pc_num].name.c_str());
|
||||
|
||||
me["recipient"].setText(get_text);
|
||||
|
||||
for(i = 0; i < 19; i++) {
|
||||
eSkill skill = eSkill(i);
|
||||
store_skills[skill] = univ.party[pc_num].skills[skill];
|
||||
}
|
||||
store_h = univ.party[pc_num].max_health;
|
||||
store_sp = univ.party[pc_num].max_sp;
|
||||
store_g = (mode == 0) ? 20000 : univ.party.gold;
|
||||
store_skp = univ.party[pc_num].skill_pts;
|
||||
|
||||
draw_xp_skills(me,store_skills);
|
||||
|
||||
|
||||
update_gold_skills(me);
|
||||
}
|
||||
|
||||
static bool spend_xp_navigate_filter(cDialog& me, std::string item_hit,std::map<eSkill,short>& store_skills) {
|
||||
short mode,pc_num;
|
||||
bool talk_done = false;
|
||||
|
||||
mode = store_train_mode;
|
||||
pc_num = store_train_pc;
|
||||
|
||||
if(item_hit == "cancel") {
|
||||
// TODO: Um, I'm pretty sure this can never happen.
|
||||
if(mode == 0 && univ.party[pc_num].main_status < eMainStatus::ABSENT)
|
||||
univ.party[pc_num].main_status = eMainStatus::ABSENT;
|
||||
me.setResult(false);
|
||||
talk_done = true;
|
||||
} else if(item_hit == "help") {
|
||||
univ.party.help_received[10] = 0;
|
||||
// give_help(210,11,me);
|
||||
} else if(item_hit == "keep") {
|
||||
do_xp_keep(pc_num,mode,store_skills);
|
||||
me.setResult(true);
|
||||
talk_done = true;
|
||||
} else if(item_hit == "left") {
|
||||
// TODO: Try not forcing a commit when using the arrows?
|
||||
if(mode != 0) {
|
||||
do_xp_keep(pc_num,mode,store_skills);
|
||||
do {
|
||||
pc_num = (pc_num == 0) ? 5 : pc_num - 1;
|
||||
} while(univ.party[pc_num].main_status != eMainStatus::ALIVE);
|
||||
store_train_pc = pc_num;
|
||||
do_xp_draw(me,store_skills);
|
||||
} else
|
||||
beep(); // TODO: This is a game event, so it should have a game sound, not a system alert.
|
||||
} else if(item_hit == "right") {
|
||||
// TODO: If they don't work in mode 0, why are they visible?
|
||||
if(mode != 0) {
|
||||
do_xp_keep(pc_num,mode,store_skills);
|
||||
do {
|
||||
pc_num = (pc_num == 5) ? 0 : pc_num + 1;
|
||||
} while(univ.party[pc_num].main_status != eMainStatus::ALIVE);
|
||||
store_train_pc = pc_num;
|
||||
do_xp_draw(me,store_skills);
|
||||
} else
|
||||
beep(); // TODO: This is a game event, so it should have a game sound, not a system alert.
|
||||
}
|
||||
store_train_pc = pc_num;
|
||||
if(talk_done) {
|
||||
me.toast(item_hit == "keep");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool spend_xp_event_filter(cDialog& me, std::string item_hit, eKeyMod mods,std::map<eSkill,short>& store_skills) {
|
||||
short mode = store_train_mode, pc_num = store_train_pc;
|
||||
if(item_hit.substr(0,2) == "hp") {
|
||||
if(mod_contains(mods, mod_alt)) {
|
||||
cStrDlog aboutHP(get_str("help",63),"","About Health",24,PIC_DLOG,&me);
|
||||
aboutHP.setSound(57);
|
||||
aboutHP.show();
|
||||
} else if(((store_h >= 250) && (item_hit[3] == 'p')) ||
|
||||
((store_h == univ.party[pc_num].max_health) && (item_hit[3] == 'm') && (mode == 1)) ||
|
||||
((store_h == 6) && (item_hit[3] == 'm') && (mode == 0)))
|
||||
beep(); // TODO: This is a game event, so it should have a game sound, not a system alert.
|
||||
else if(item_hit == "hp-m") {
|
||||
store_g += 10;
|
||||
store_h -= 2;
|
||||
store_skp += 1;
|
||||
}
|
||||
else {
|
||||
if((store_g < 10) || (store_skp < 1)) {
|
||||
// if(store_g < 10)
|
||||
// give_help(24,0,me);
|
||||
// else give_help(25,0,me);
|
||||
}
|
||||
else {
|
||||
store_g -= 10;
|
||||
store_h += 2;
|
||||
store_skp -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
update_gold_skills(me);
|
||||
me["hp"].setTextToNum(store_h);
|
||||
draw_xp_skills(me,store_skills);
|
||||
|
||||
} else if(item_hit.substr(0,2) == "sp") {
|
||||
if(mod_contains(mods, mod_alt)) {
|
||||
cStrDlog aboutSP(get_str("help",64),"","About Spell Points",24,PIC_DLOG,&me);
|
||||
aboutSP.setSound(57);
|
||||
aboutSP.show();
|
||||
} else if(((store_sp >= 150) && (item_hit[3] == 'p')) ||
|
||||
((store_sp == univ.party[pc_num].max_sp) && (item_hit[3] == 'm') && (mode == 1)) ||
|
||||
((store_sp == 0) && (item_hit[3] == 'm') && (mode == 0)))
|
||||
beep(); // TODO: This is a game event, so it should have a game sound, not a system alert.
|
||||
else if(item_hit == "sp-m") {
|
||||
store_g += 15;
|
||||
store_sp -= 1;
|
||||
store_skp += 1;
|
||||
}
|
||||
else {
|
||||
if((store_g < 15) || (store_skp < 1)) {
|
||||
// if(store_g < 15)
|
||||
// give_help(24,0,me);
|
||||
// else give_help(25,0,me);
|
||||
}
|
||||
else {
|
||||
store_sp += 1;
|
||||
store_g -= 15;
|
||||
store_skp -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
update_gold_skills(me);
|
||||
me["sp"].setTextToNum(store_sp);
|
||||
draw_xp_skills(me,store_skills);
|
||||
} else {
|
||||
eSkill which_skill = eSkill::INVALID;
|
||||
for(int i = 0; i < 19; i++) {
|
||||
size_t n = strlen(skill_ids[i]);
|
||||
if(item_hit.length() < n + 2) continue;
|
||||
if(item_hit.substr(0, item_hit.length() - 2) == skill_ids[i]) {
|
||||
which_skill = eSkill(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(which_skill == eSkill::INVALID) return true;
|
||||
/* if(mod_contains(mods, mod_alt)) display_skills(which_skill,&me);
|
||||
else */{
|
||||
char dir = item_hit[item_hit.length() - 1];
|
||||
|
||||
// TODO: This is a game event, so it should have a game sound, not a system alert.
|
||||
if(store_skills[which_skill] >= skill_max[which_skill] && dir == 'p')
|
||||
beep();
|
||||
else if(store_skills[which_skill] == univ.party[pc_num].skills[which_skill] && dir == 'm' && mode == 1)
|
||||
beep();
|
||||
else if(store_skills[which_skill] == 0 && dir == 'm' && mode == 0 &&
|
||||
which_skill != eSkill::STRENGTH && which_skill != eSkill::DEXTERITY && which_skill != eSkill::INTELLIGENCE)
|
||||
beep();
|
||||
else if(store_skills[which_skill] == 1 && dir == 'm' && mode == 0 &&
|
||||
(which_skill == eSkill::STRENGTH || which_skill == eSkill::DEXTERITY || which_skill == eSkill::INTELLIGENCE))
|
||||
beep();
|
||||
else {
|
||||
if(dir == 'm') {
|
||||
store_g += skill_g_cost[which_skill];
|
||||
store_skills[which_skill] -= 1;
|
||||
store_skp += skill_cost[which_skill];
|
||||
}
|
||||
else {
|
||||
if((store_g < skill_g_cost[which_skill]) || (store_skp < skill_cost[which_skill])) {
|
||||
// if(store_g < skill_g_cost[which_skill])
|
||||
// give_help(24,0,me);
|
||||
// else give_help(25,0,me);
|
||||
}
|
||||
else {
|
||||
store_skills[which_skill] += 1;
|
||||
store_g -= skill_g_cost[which_skill];
|
||||
store_skp -= skill_cost[which_skill];
|
||||
}
|
||||
}
|
||||
|
||||
update_gold_skills(me);
|
||||
me[skill_ids[int(which_skill)]].setTextToNum(store_skills[which_skill]);
|
||||
draw_xp_skills(me,store_skills);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//short mode; // 0 - create 1 - train
|
||||
// returns 1 if cancelled
|
||||
bool spend_xp(short pc_num, short mode, cDialog* parent) {
|
||||
using namespace std::placeholders;
|
||||
store_train_pc = pc_num;
|
||||
store_train_mode = mode;
|
||||
|
||||
make_cursor_sword();
|
||||
|
||||
std::map<eSkill,short> skills = univ.party[pc_num].skills;
|
||||
|
||||
cDialog xpDlog("spend-xp",parent);
|
||||
xpDlog.addLabelFor("hp","Health (1/10)",LABEL_LEFT,75,true);
|
||||
xpDlog.addLabelFor("sp","Spell Pts. (1/15)",LABEL_LEFT,75,true);
|
||||
auto spend_xp_filter = std::bind(spend_xp_event_filter,_1,_2,_3,std::ref(skills));
|
||||
std::string minus = "-m", plus = "-p";
|
||||
for(i = 54; i < 73; i++) {
|
||||
std::ostringstream sout;
|
||||
eSkill skill = eSkill(i - 54);
|
||||
sout << get_str("skills",1 + 2 * (i - 54)) << ' ' << '(';
|
||||
sout << skill_cost[skill] << '/' << skill_g_cost[skill] << ')';
|
||||
xpDlog.addLabelFor(skill_ids[i - 54],sout.str(),LABEL_LEFT,(i < 63) ? 75 : 69,true);
|
||||
xpDlog[skill_ids[i - 54] + minus].attachClickHandler(spend_xp_filter);
|
||||
xpDlog[skill_ids[i - 54] + plus].attachClickHandler(spend_xp_filter);
|
||||
}
|
||||
do_xp_draw(xpDlog,skills);
|
||||
|
||||
xpDlog.attachClickHandlers(std::bind(spend_xp_navigate_filter,_1,_2,std::ref(skills)),{"keep","cancel","left","right","help"});
|
||||
xpDlog.attachClickHandlers(spend_xp_filter,{"sp-m","sp-p","hp-m","hp-p"});
|
||||
|
||||
if(univ.party.help_received[10] == 0) {
|
||||
// TODO: Is an initial draw even needed?
|
||||
// cd_initial_draw(1010);
|
||||
// give_help(10,11,xpDlog);
|
||||
}
|
||||
|
||||
xpDlog.run();
|
||||
|
||||
return xpDlog.getResult<bool>();
|
||||
}
|
14
src/pcedit/pc.editors.h
Normal file
14
src/pcedit/pc.editors.h
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
bool give_to_pc(short pc_num,cItemRec item, short print_result);
|
||||
bool give_to_party(cItemRec item,short print_result);
|
||||
void give_gold(short amount,bool print_result);
|
||||
bool take_gold(short amount,bool print_result);
|
||||
short pc_has_space(short pc_num);
|
||||
void take_item(short pc_num,short which_item);
|
||||
short char_select_pc(short active_only,short free_inv_only,const char *title);
|
||||
short select_pc(short active_only,short free_inv_only);
|
||||
void give_spec_items();
|
||||
void pick_race_abil(cPlayer *pc,short mode);
|
||||
void reset_boats();
|
||||
void combine_things(short pc_num);
|
88
src/pcedit/pc.fileio.cpp
Normal file
88
src/pcedit/pc.fileio.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include "pc.global.h"
|
||||
#include "classes.h"
|
||||
#include "pc.fileio.h"
|
||||
#include "pc.graphics.h"
|
||||
#include "graphtool.h"
|
||||
#include "soundtool.h"
|
||||
#include "pc.editors.h"
|
||||
#include "mathutil.h"
|
||||
#include "dlogutil.hpp"
|
||||
#include "restypes.hpp"
|
||||
#include "fileio.h"
|
||||
|
||||
#define DONE_BUTTON_ITEM 1
|
||||
|
||||
extern bool play_sounds;
|
||||
extern short current_active_pc;
|
||||
extern long stored_key;
|
||||
extern sf::RenderWindow mainPtr;
|
||||
|
||||
extern cItemRec item_list[400];
|
||||
extern cUniverse univ;
|
||||
|
||||
extern bool file_in_mem,party_in_scen,scen_items_loaded;
|
||||
|
||||
bool ae_loading = false;
|
||||
|
||||
typedef struct {
|
||||
char expl[96][96];
|
||||
} out_info_type;
|
||||
|
||||
char *party_encryptor;
|
||||
|
||||
std::string last_load_file = "Blades of Exile Save";
|
||||
|
||||
extern void update_item_menu();
|
||||
|
||||
extern short store_flags[3];
|
||||
fs::path store_file_reply;
|
||||
|
||||
short give_intro_hint,display_mode;
|
||||
short jl;
|
||||
fs::path file_to_load;
|
||||
|
||||
void load_base_item_defs();
|
||||
bool load_scen_item_defs(char scen_name[256]);
|
||||
|
||||
extern fs::path progDir;
|
||||
|
||||
void leave_town() {
|
||||
store_flags[0] = 5790;
|
||||
}
|
||||
|
||||
void remove_party_from_scen() {
|
||||
store_flags[1] = 200;
|
||||
party_in_scen = false;
|
||||
load_base_item_defs();
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX This was referenced but not defined, so I copied the implementation
|
||||
* from blxfileio.c. Need to check that it's OK.
|
||||
*/
|
||||
short init_data(short flag) {
|
||||
long k = 0;
|
||||
|
||||
k = (long) flag;
|
||||
k = k * k;
|
||||
jl = jl * jl + 84 + k;
|
||||
k = k + 51;
|
||||
jl = jl * 2 + 1234 + k;
|
||||
k = k % 3000;
|
||||
jl = jl * 54;
|
||||
jl = jl * 2 + 1234 + k;
|
||||
k = k * 82;
|
||||
k = k % 10000;
|
||||
k = k + 10000;
|
||||
|
||||
return (short) k;
|
||||
}
|
||||
|
||||
void load_base_item_defs(){
|
||||
fs::path basePath = progDir/"Scenario Editor"/"Blades of Exile Base"/"bladbase.exs";
|
||||
scen_items_loaded = load_scenario(basePath, univ.scenario);
|
||||
}
|
11
src/pcedit/pc.fileio.h
Normal file
11
src/pcedit/pc.fileio.h
Normal file
@@ -0,0 +1,11 @@
|
||||
//bool select_save_location(FSSpec* to_save_ptr);
|
||||
//void save_file(FSSpec to_save);
|
||||
//void load_file();
|
||||
void leave_town();
|
||||
//long do_waterfall(long flag);
|
||||
short init_data(short flag);
|
||||
//long open_pref_file();
|
||||
//void make_pref_file(FSSpec pref);
|
||||
//void save_prefs();
|
||||
void remove_party_from_scen();
|
||||
void load_base_item_defs();
|
85
src/pcedit/pc.global.cpp
Normal file
85
src/pcedit/pc.global.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
//#include <OSUtils.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include "ed.global.h"
|
||||
#include "math.h"
|
||||
|
||||
extern short give_delays;
|
||||
|
||||
short get_ran (short times,short min,short max)
|
||||
{
|
||||
long int store;
|
||||
short i, to_ret = 0;
|
||||
|
||||
for (i = 1; i < times + 1; i++) {
|
||||
store = Random();
|
||||
to_ret = to_ret + min + (((store + 32767) * (max - min + 1)) / 65536);
|
||||
}
|
||||
return to_ret;
|
||||
}
|
||||
|
||||
Boolean same_point(location p1,location p2)
|
||||
{
|
||||
if ((p1.x == p2.x) & (p1.y == p2.y))
|
||||
return TRUE;
|
||||
else return FALSE;
|
||||
}
|
||||
|
||||
short move_to_zero(short val)
|
||||
{
|
||||
if (val < 0)
|
||||
return val + 1;
|
||||
if (val > 0)
|
||||
return val - 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
short max(short a,short b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else return b;
|
||||
}
|
||||
|
||||
short min(short a,short b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else return b;
|
||||
}
|
||||
|
||||
short minmax(short min,short max,short k)
|
||||
{
|
||||
if (k < min)
|
||||
return min;
|
||||
if (k > max)
|
||||
return max;
|
||||
return k;
|
||||
}
|
||||
|
||||
short s_pow(short x,short y)
|
||||
{
|
||||
return (short) pow((double) x, (double) y);
|
||||
}
|
||||
|
||||
short a_v(short x)
|
||||
{
|
||||
if (x < 0)
|
||||
return (-1 * x);
|
||||
else return x;
|
||||
}
|
||||
short ex_abs(short x)
|
||||
{
|
||||
if (x < 0)
|
||||
return (-1 * x);
|
||||
else return x;
|
||||
}
|
||||
|
||||
void BoEpause(short length)
|
||||
{
|
||||
unsigned long dummy,len;
|
||||
|
||||
len = (unsigned long)length;
|
||||
|
||||
if (give_delays == 0)
|
||||
Delay(len, &dummy);
|
||||
}
|
427
src/pcedit/pc.global.h
Normal file
427
src/pcedit/pc.global.h
Normal file
@@ -0,0 +1,427 @@
|
||||
//#define EXILE_BIG_GUNS 1
|
||||
|
||||
#define DRAG_EDGE 15
|
||||
|
||||
#define T_M 60
|
||||
|
||||
#define NUM_TOWN_ITEMS 115
|
||||
|
||||
#define DRAG_EDGE 15
|
||||
|
||||
#define DISPLAY_LEFT 23
|
||||
#define DISPLAY_TOP 23
|
||||
#define BITMAP_WIDTH 28
|
||||
#define BITMAP_HEIGHT 36
|
||||
|
||||
//#define STORED_GRAPHICS 240
|
||||
|
||||
#define PC_WIN_UL_X 291
|
||||
#define PC_WIN_UL_Y 5
|
||||
#define ITEM_WIN_UL_X 291
|
||||
#define ITEM_WIN_UL_Y 130
|
||||
#define TEXT_WIN_UL_X 291
|
||||
#define TEXT_WIN_UL_Y 283
|
||||
#define NUM_BUTTONS 15
|
||||
#define ASB add_string_to_buf
|
||||
#define PSD univ.party.stuff_done
|
||||
#define DES display_enc_string
|
||||
#define D2ES display_2_enc_string
|
||||
|
||||
#define DOOR_LIGHT can_enter = run_trap(7,&PSD[c_town.town_num][which],4220,0); break;
|
||||
#define DOOR_HEAVY can_enter = run_trap(7,&PSD[c_town.town_num][which],4220,20); break;
|
||||
#define DOOR_ALARM can_enter = run_trap(7,&PSD[c_town.town_num][which],4220,11); break;
|
||||
#define DRESSER_LIGHT can_enter = run_trap(7,&PSD[c_town.town_num][which],4221,0); break;
|
||||
#define DRESSER_HEAVY can_enter = run_trap(7,&PSD[c_town.town_num][which],4221,20); break;
|
||||
#define DRESSER_ALARM can_enter = run_trap(7,&PSD[c_town.town_num][which],4221,11); break;
|
||||
#define FLOOR_LIGHT can_enter = run_trap(7,&PSD[c_town.town_num][which],4222,0); break;
|
||||
#define FLOOR_HEAVY can_enter = run_trap(7,&PSD[c_town.town_num][which],4222,20); break;
|
||||
#define FLOOR_ALARM can_enter = run_trap(7,&PSD[c_town.town_num][which],4222,11); break;
|
||||
#define CHEST_LIGHT can_enter = run_trap(7,&PSD[c_town.town_num][which],3450,0); break;
|
||||
#define CHEST_HEAVY can_enter = run_trap(7,&PSD[c_town.town_num][which],3450,20); break;
|
||||
#define CHEST_ALARM can_enter = run_trap(7,&PSD[c_town.town_num][which],3450,11); break;
|
||||
|
||||
#define printFlag() printf("%s %i\n",__FILE__,__LINE__)
|
||||
|
||||
//typedef struct {
|
||||
// char x,y;
|
||||
// } location;
|
||||
//typedef struct {
|
||||
// short x,y;} shortloc;
|
||||
|
||||
//typedef struct {
|
||||
// short type,sd1,sd2,pic,m1,m2,ex1a,ex1b,ex2a,ex2b,jumpto;
|
||||
// } special_node_type;
|
||||
|
||||
//typedef struct {
|
||||
// short personality,type;
|
||||
// char link1[4],link2[4];
|
||||
// short extras[4];
|
||||
// } talking_node_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char strlens[200];
|
||||
// talking_node_type talk_nodes[60];
|
||||
// } talking_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// short picture;
|
||||
// unsigned char blockage,flag1,flag2,special,trans_to_what,fly_over,boat_over;
|
||||
// unsigned char block_horse,light_radius,step_sound,shortcut_key,res1,res2,res3;
|
||||
// } terrain_type_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char monst[4];
|
||||
// } wandering_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char monst[7];
|
||||
// unsigned char friendly[3];
|
||||
// short spec_on_meet,spec_on_win,spec_on_flee,cant_flee;
|
||||
// short end_spec1,end_spec2;
|
||||
//} out_wandering_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char terrain[48][48];
|
||||
// location special_locs[18];
|
||||
// unsigned char special_id[18];
|
||||
// location exit_locs[8];
|
||||
// char exit_dests[8];
|
||||
// location sign_locs[8];
|
||||
// out_wandering_type wandering[4],special_enc[4];
|
||||
// location wandering_locs[4];
|
||||
// RECT info_rect[8];
|
||||
// unsigned char strlens[180];
|
||||
// special_node_type specials[60];
|
||||
// } outdoor_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char number;
|
||||
// unsigned char start_attitude;
|
||||
// location start_loc;
|
||||
// unsigned char mobile;
|
||||
// unsigned char time_flag;
|
||||
// unsigned char extra1,extra2;
|
||||
// short spec1, spec2;
|
||||
// char spec_enc_code,time_code;
|
||||
// short monster_time,personality;
|
||||
// short special_on_kill,facial_pic;
|
||||
//
|
||||
// } creature_start_type;
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// short variety, item_level;
|
||||
// char awkward, bonus, protection, charges, type;
|
||||
// unsigned char graphic_num,ability, type_flag, is_special;
|
||||
// short value;
|
||||
// bool identified, magic;
|
||||
// unsigned char weight, description_flag;
|
||||
// char full_name[25], name[15];
|
||||
// unsigned char reserved1,reserved2;
|
||||
// unsigned char magic_use_type, ability_strength, treas_class, real_abil;
|
||||
//
|
||||
//} short_item_record_type;
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// short variety, item_level;
|
||||
// char awkward, bonus, protection, charges, type, magic_use_type;
|
||||
// unsigned char graphic_num,ability, ability_strength,type_flag, is_special;
|
||||
// short value;
|
||||
// unsigned char weight, special_class;
|
||||
// location item_loc;
|
||||
// char full_name[25], name[15];
|
||||
// unsigned char treas_class,item_properties,reserved1,reserved2;
|
||||
//} item_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// location item_loc;
|
||||
// short item_code,ability;
|
||||
// unsigned char charges,always_there,property,contained;
|
||||
// } preset_item_type;
|
||||
|
||||
//typedef struct {
|
||||
// location field_loc;
|
||||
// short field_type;
|
||||
// } preset_field_type;
|
||||
|
||||
//typedef struct {
|
||||
// short town_chop_time,town_chop_key;
|
||||
// wandering_type wandering[4];
|
||||
// location wandering_locs[4];
|
||||
// location special_locs[50];
|
||||
// unsigned char spec_id[50];
|
||||
// location sign_locs[15];
|
||||
// short lighting;
|
||||
// location start_locs[4];
|
||||
// location exit_locs[4];
|
||||
// short exit_specs[4];
|
||||
// RECT in_town_rect;
|
||||
// preset_item_type preset_items[64];
|
||||
// short max_num_monst;
|
||||
// preset_field_type preset_fields[50];
|
||||
// short spec_on_entry,spec_on_entry_if_dead;
|
||||
// short timer_spec_times[8];
|
||||
// short timer_specs[8];
|
||||
// unsigned char strlens[180];
|
||||
// special_node_type specials[100];
|
||||
// unsigned char specials1,specials2,res1,res2;
|
||||
// short difficulty;
|
||||
// } town_record_type;
|
||||
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char terrain[64][64];
|
||||
// RECT room_rect[16];
|
||||
// creature_start_type creatures[60];
|
||||
// unsigned char lighting[8][64];
|
||||
// } big_tr_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char terrain[48][48];
|
||||
// RECT room_rect[16];
|
||||
// creature_start_type creatures[40];
|
||||
// unsigned char lighting[6][48];
|
||||
// } ave_tr_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char terrain[32][32];
|
||||
// RECT room_rect[16];
|
||||
// creature_start_type creatures[30];
|
||||
// unsigned char lighting[4][32];
|
||||
// } tiny_tr_type;
|
||||
|
||||
//typedef struct {
|
||||
// short block_type;
|
||||
// short block_destroy_time;
|
||||
// char block_alignment;
|
||||
// char block_key_time;
|
||||
// location block_loc;
|
||||
// } city_block_type;
|
||||
|
||||
//typedef struct {
|
||||
// RECT what_rect;
|
||||
// unsigned char ter_type;
|
||||
// unsigned char hollow;
|
||||
// } city_ter_rect_type;
|
||||
|
||||
//typedef struct {
|
||||
// creature_start_type creatures[30];
|
||||
// city_block_type city_block[15];
|
||||
// city_ter_rect_type city_ter_rect[10];
|
||||
// } template_town_type;
|
||||
|
||||
//typedef struct {
|
||||
// item_record_type scen_items[400];
|
||||
// char monst_names[256][20];
|
||||
// char ter_names[256][30];
|
||||
// } scen_item_data_type;
|
||||
|
||||
//typedef struct {
|
||||
// short ter_type,item_num[10],item_odds[10],property;
|
||||
// } item_storage_shortcut_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char m_num,level,m_name[26];
|
||||
// short health,m_health,mp,max_mp;
|
||||
// unsigned char armor,skill;
|
||||
// short a[3];
|
||||
// unsigned char a1_type,a23_type,m_type,speed,ap,mu,cl,breath,breath_type,treasure,spec_skill,poison;
|
||||
// short morale,m_morale;
|
||||
// short corpse_item,corpse_item_chance;
|
||||
// short status[15];
|
||||
// unsigned char direction,immunities,x_width,y_width,radiate_1,radiate_2;
|
||||
// unsigned char default_attitude,summon_type,default_facial_pic,res1,res2,res3;
|
||||
// short picture_num;
|
||||
//
|
||||
// } monster_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// short active,attitude;
|
||||
// unsigned char number;
|
||||
// location m_loc;
|
||||
// monster_record_type m_d;
|
||||
// bool mobile;
|
||||
// short summoned;
|
||||
// creature_start_type monst_start;
|
||||
// } creature_data_type;
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// location horse_loc,horse_loc_in_sec,horse_sector;
|
||||
// short which_town;
|
||||
// bool exists,property;
|
||||
// } horse_record_type;
|
||||
//typedef struct {
|
||||
// location boat_loc,boat_loc_in_sec,boat_sector;
|
||||
// short which_town;
|
||||
// bool exists,property;
|
||||
//} boat_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char flag1, flag2, flag3, flag4;
|
||||
// unsigned char ver[3],min_run_ver,prog_make_ver[3],num_towns;
|
||||
// unsigned char out_width,out_height,difficulty,intro_pic,default_ground;
|
||||
// } scen_header_type;
|
||||
|
||||
// typedef struct {
|
||||
// unsigned char flag1, flag2, flag3, flag4;
|
||||
// unsigned char ver[3],min_run_ver,prog_make_ver[3],num_towns;
|
||||
// unsigned char out_width,out_height,difficulty,intro_pic,default_ground;
|
||||
// unsigned char town_size[200];
|
||||
// unsigned char town_hidden[200];
|
||||
// short flag_a;
|
||||
// short intro_mess_pic,intro_mess_len;
|
||||
// location where_start,out_sec_start,out_start;
|
||||
// short which_town_start;
|
||||
// short flag_b;
|
||||
// short town_data_size[200][5];
|
||||
// short town_to_add_to[10];
|
||||
// short flag_to_add_to_town[10][2];
|
||||
// short flag_c;
|
||||
// short out_data_size[100][2];
|
||||
// RECT store_item_rects[3];
|
||||
// short store_item_towns[3];
|
||||
// short flag_e;
|
||||
// short special_items[50];
|
||||
// short special_item_special[50];
|
||||
// short rating,uses_custom_graphics;
|
||||
// short flag_f;
|
||||
// monster_record_type scen_monsters[256];
|
||||
// boat_record_type scen_boats[30];
|
||||
// horse_record_type scen_horses[30];
|
||||
// short flag_g;
|
||||
// terrain_type_type ter_types[256];
|
||||
// short scenario_timer_times[20];
|
||||
// short scenario_timer_specs[20];
|
||||
// short flag_h;
|
||||
// special_node_type scen_specials[256];
|
||||
// item_storage_shortcut_type storage_shortcuts[10];
|
||||
// short flag_d;
|
||||
// unsigned char scen_str_len[300];
|
||||
// short flag_i;
|
||||
// location last_out_edited;
|
||||
// short last_town_edited;
|
||||
//
|
||||
// } scenario_data_type;
|
||||
|
||||
// for game
|
||||
//typedef struct {
|
||||
// short personality;
|
||||
// short town_num;
|
||||
// short str1,str2;
|
||||
// } talk_save_type;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// creature_data_type dudes[60];
|
||||
// short which_town;
|
||||
// short friendly;
|
||||
// } creature_list_type;
|
||||
|
||||
//typedef struct {
|
||||
// short town_num, difficulty;
|
||||
// town_record_type town;
|
||||
// char explored[64][64];
|
||||
// bool hostile;
|
||||
// creature_list_type monst;
|
||||
// bool in_boat;
|
||||
// location p_loc;
|
||||
// } current_town_type;
|
||||
|
||||
//typedef struct {
|
||||
// bool exists;
|
||||
// short direction;
|
||||
// out_wandering_type what_monst;
|
||||
// location which_sector,m_loc;
|
||||
// } outdoor_creature_type;
|
||||
|
||||
//typedef struct {
|
||||
// long age;
|
||||
// short gold,food;
|
||||
// unsigned char stuff_done[310][10],item_taken[200][8];
|
||||
// short light_level;
|
||||
// location outdoor_corner,i_w_c,p_loc,loc_in_sec;
|
||||
// boat_record_type boats[30];
|
||||
// horse_record_type horses[30];
|
||||
// creature_list_type creature_save[4];
|
||||
// short in_boat,in_horse;
|
||||
// outdoor_creature_type out_c[10];
|
||||
// item_record_type magic_store_items[5][10];
|
||||
// short imprisoned_monst[4];
|
||||
// char m_seen[256];
|
||||
// char journal_str[50];
|
||||
// short journal_day[50];
|
||||
// short special_notes_str[140][2];
|
||||
// talk_save_type talk_save[120];
|
||||
// short direction,at_which_save_slot;
|
||||
// char alchemy[20];
|
||||
// bool can_find_town[200];
|
||||
// short key_times[100];
|
||||
// short party_event_timers[30];
|
||||
// short global_or_town[30];
|
||||
// short node_to_call[30];
|
||||
// char spec_items[50],help_received[120];
|
||||
// short m_killed[200];
|
||||
// long total_m_killed,total_dam_done,total_xp_gained,total_dam_taken;
|
||||
// char scen_name[256];
|
||||
// } party_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// char town_maps[200][8][64];
|
||||
// } stored_town_maps_type;
|
||||
//typedef struct {
|
||||
// char town_strs[180][256];
|
||||
// //char out_strs[120][256];
|
||||
// char scen_strs[270][256];
|
||||
// char talk_strs[170][256];
|
||||
// char scen_header_strs[25][3][80];
|
||||
// Str255 scen_names[25];
|
||||
// scen_item_data_type scen_item_list;
|
||||
// stored_town_maps_type town_maps;
|
||||
// } piles_of_stuff_dumping_type;
|
||||
//typedef struct {
|
||||
// char out_strs[9][256];
|
||||
// } outdoor_strs_type;
|
||||
//typedef struct {
|
||||
// short main_status;
|
||||
// char name[20];
|
||||
// short skills[30];
|
||||
// short max_health,cur_health,max_sp,cur_sp,experience,skill_pts,level;
|
||||
// short status[15];
|
||||
// item_record_type items[24];
|
||||
// bool equip[24];
|
||||
// bool priest_spells[62],mage_spells[62];
|
||||
// short which_graphic,weap_poisoned;
|
||||
// bool advan[15],traits[15];
|
||||
// short race,exp_adj,direction;
|
||||
// } pc_record_type;
|
||||
|
||||
//typedef struct {
|
||||
// unsigned char setup[4][64][64];
|
||||
// } setup_save_type;
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// item_record_type items[NUM_TOWN_ITEMS];
|
||||
// } town_item_list;
|
||||
|
||||
//typedef struct {short i;} flag_type;
|
||||
|
||||
typedef struct {unsigned char pattern[9][9];} effect_pat_type;
|
||||
|
||||
//typedef struct {
|
||||
// item_record_type items[NUM_TOWN_ITEMS];
|
||||
// } stored_items_list_type;
|
||||
|
||||
//typedef struct {
|
||||
// char outdoor_maps[100][6][48];
|
||||
// } stored_outdoor_maps_type;
|
||||
|
||||
typedef struct {
|
||||
long l[10];
|
||||
} PrefRecord,*PrefPtr,**PrefHandle;
|
1044
src/pcedit/pc.graphics.cpp
Normal file
1044
src/pcedit/pc.graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
6
src/pcedit/pc.graphics.h
Normal file
6
src/pcedit/pc.graphics.h
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
void init_main_buttons();
|
||||
void Set_up_win ();
|
||||
void redraw_screen();
|
||||
void do_button_action(short which_pc,short which_button);
|
||||
void make_cursor_sword();
|
553
src/pcedit/pc.main.cpp
Normal file
553
src/pcedit/pc.main.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
|
||||
//#include <cMemory>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include "pc.global.h"
|
||||
#include "classes.h"
|
||||
#include "pc.graphics.h"
|
||||
#include "pc.editors.h"
|
||||
#include "pc.action.h"
|
||||
#include "pc.fileio.h"
|
||||
#include "soundtool.h"
|
||||
#include "graphtool.h"
|
||||
#include "boe.consts.h"
|
||||
#include "dlogutil.hpp"
|
||||
#include "fileio.h"
|
||||
#include "pc.menus.h"
|
||||
#include "winutil.h"
|
||||
#include "cursors.h"
|
||||
|
||||
cUniverse univ;
|
||||
|
||||
rectangle pc_area_buttons[6][4] ; // 0 - whole 1 - pic 2 - name 3 - stat strs 4,5 - later
|
||||
rectangle item_string_rects[24][4]; // 0 - name 1 - drop 2 - id 3 -
|
||||
rectangle pc_info_rect; // Frame that holds a pc's basic info and items
|
||||
rectangle name_rect; //Holds pc name inside pc_info_rect
|
||||
rectangle info_area_rect;
|
||||
rectangle hp_sp_rect; // Holds hit points and spells points for pc
|
||||
rectangle skill_rect; // Holds "Skills:" string
|
||||
rectangle pc_skills_rect[19]; //Holds current pc's skill levels
|
||||
rectangle status_rect; //Holds the string "Status:"
|
||||
rectangle pc_status_rect[10]; //Holds first 8 effects on pc
|
||||
rectangle traits_rect; //Holds the string "Traits:"
|
||||
rectangle pc_traits_rect[16]; //Holds pc traits
|
||||
rectangle pc_race_rect; //Holds current pc's race
|
||||
rectangle edit_rect[5][2]; //Buttons that bring up pc edit dialog boxs
|
||||
|
||||
short current_active_pc = 0;
|
||||
//short dialog_answer;
|
||||
|
||||
/* Mac stuff globals */
|
||||
bool All_Done = false,diff_depth_ok = false;
|
||||
sf::Event event;
|
||||
sf::RenderWindow mainPtr;
|
||||
bool gInBackground = false;
|
||||
fs::path file_in_mem;
|
||||
bool party_in_scen = false;
|
||||
bool scen_items_loaded = false;
|
||||
|
||||
/* Adventure globals */
|
||||
//party_record_type party;
|
||||
//outdoor_record_type outdoors[2][2];
|
||||
//current_town_type c_town;
|
||||
//big_tr_type t_d;
|
||||
//town_item_list t_i;
|
||||
//unsigned char out[96][96],out_e[96][96];
|
||||
//setup_save_type setup_save;
|
||||
//unsigned char misc_i[64][64],sfx[64][64];
|
||||
//unsigned char template_terrain[64][64];
|
||||
|
||||
short store_flags[3];
|
||||
|
||||
//town_record_type anim_town;
|
||||
//tiny_tr_type anim_t_d;
|
||||
|
||||
//stored_items_list_type stored_items[3];
|
||||
//stored_town_maps_type maps;
|
||||
//stored_town_maps_type town_maps;
|
||||
//stored_outdoor_maps_type o_maps;
|
||||
|
||||
/* Display globals */
|
||||
short give_delays = 0; /* XXX this wasn't defined anywhere, is this right? -jmr */
|
||||
|
||||
/* Prototypes */
|
||||
int main(int argc, char* argv[]);
|
||||
void Initialize(void);
|
||||
void Handle_One_Event();
|
||||
void Handle_Activate();
|
||||
void Handle_Update();
|
||||
void Mouse_Pressed();
|
||||
void handle_apple_menu(int item_hit);
|
||||
void handle_file_menu(int item_hit);
|
||||
void handle_reg_menu(int item_hit);
|
||||
void handle_extra_menu(int item_hit);
|
||||
void handle_edit_menu(int item_hit);
|
||||
void update_item_menu();
|
||||
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;
|
||||
// File io
|
||||
short specials_res_id;
|
||||
char start_name[256];
|
||||
|
||||
//
|
||||
// Main body of program Exile
|
||||
//
|
||||
|
||||
//MW specified return type was 'void', changed to ISO C style for Carbonisation -jmr
|
||||
int main(int /*argc*/, char* argv[]) {
|
||||
try {
|
||||
init_menubar();
|
||||
init_directories(argv[0]);
|
||||
Initialize();
|
||||
init_fileio();
|
||||
init_main_buttons();
|
||||
Set_up_win();
|
||||
init_graph_tool();
|
||||
init_snd_tool();
|
||||
|
||||
set_up_apple_events();
|
||||
|
||||
cDialog::init();
|
||||
redraw_screen();
|
||||
|
||||
while(!All_Done)
|
||||
Handle_One_Event();
|
||||
return 0;
|
||||
} catch(std::exception& x) {
|
||||
giveError(x.what());
|
||||
throw;
|
||||
} catch(std::string& x) {
|
||||
giveError(x);
|
||||
throw;
|
||||
} catch(...) {
|
||||
giveError("An unknown error occurred!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Initialize everything for the program, make sure we can run
|
||||
//
|
||||
|
||||
//MW specified argument and return type.
|
||||
void Initialize(void) {
|
||||
|
||||
check_for_intel();
|
||||
|
||||
//
|
||||
// To make the Random sequences truly random, we need to make the seed start
|
||||
// at a different number. An easy way to do this is to put the current time
|
||||
// and date into the seed. Since it is always incrementing the starting seed
|
||||
// will always be different. Don’t for each call of Random, or the sequence
|
||||
// will no longer be random. Only needed once, here in the init.
|
||||
//
|
||||
//GetDateTime(&randSeed);
|
||||
// SetQDGlobalsRandomSeed((long)randSeed);
|
||||
srand(time(NULL));
|
||||
|
||||
//
|
||||
// Make a new window for drawing in, and it must be a color window.
|
||||
// The window is full screen size, made smaller to make it more visible.
|
||||
//
|
||||
// Size and style obtained from WIND resource #128
|
||||
mainPtr.create(sf::VideoMode(590, 440), "Blades of Exile Character Editor", sf::Style::Titlebar | sf::Style::Close);
|
||||
}
|
||||
|
||||
void Handle_One_Event() {
|
||||
if(!mainPtr.pollEvent(event)) return;
|
||||
|
||||
init_main_buttons();
|
||||
redraw_screen();
|
||||
|
||||
switch(event.type){
|
||||
case sf::Event::KeyPressed:
|
||||
break;
|
||||
|
||||
case sf::Event::MouseButtonPressed:
|
||||
Mouse_Pressed();
|
||||
break;
|
||||
|
||||
case sf::Event::GainedFocus:
|
||||
set_cursor(sword_curs);
|
||||
break;
|
||||
|
||||
case sf::Event::Closed:
|
||||
All_Done = verify_restore_quit(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse_Pressed() {
|
||||
bool try_to_end;
|
||||
|
||||
try_to_end = handle_action(event);
|
||||
if(try_to_end)
|
||||
All_Done = verify_restore_quit(false);
|
||||
}
|
||||
|
||||
void handle_apple_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;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_file_menu(int item_hit) {
|
||||
fs::path file;
|
||||
|
||||
switch(item_hit) {
|
||||
case 1://save
|
||||
save_party(file_in_mem, univ);
|
||||
break;
|
||||
case 2://save as
|
||||
file = nav_put_party();
|
||||
if(!file.empty()) save_party(file, univ);
|
||||
break;
|
||||
case 3://open
|
||||
if(verify_restore_quit(true)){
|
||||
file = nav_get_party();
|
||||
if(!file.empty()) {
|
||||
if(load_party(file, univ)) {
|
||||
file_in_mem = file;
|
||||
party_in_scen = !univ.party.scen_name.empty();
|
||||
if(!party_in_scen) load_base_item_defs();
|
||||
update_item_menu();
|
||||
}
|
||||
}
|
||||
menu_activate();
|
||||
}
|
||||
break;
|
||||
case 7://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_extra_menu(int item_hit) {
|
||||
short i;
|
||||
//cVehicle v_boat = {{12,17},{0,0},{0,0},80,true,false};
|
||||
|
||||
if(file_in_mem.empty()) {
|
||||
display_strings(5, 7);
|
||||
return;
|
||||
}
|
||||
switch(item_hit) {
|
||||
case 1:
|
||||
edit_gold_or_food(0);
|
||||
break;
|
||||
case 2:
|
||||
edit_gold_or_food(1);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if(univ.party.is_split() > 0) {
|
||||
cChoiceDlog("reunite-first").show();
|
||||
break;
|
||||
}
|
||||
cChoiceDlog("leave-town").show();
|
||||
leave_town();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if(univ.party.is_split() == 0) {
|
||||
cChoiceDlog("not-split").show();
|
||||
break;
|
||||
}
|
||||
cChoiceDlog("reunited").show();
|
||||
univ.town.p_loc = univ.party.left_at();
|
||||
for(i = 0; i < 6; i++)
|
||||
if(univ.party[i].main_status >= eMainStatus::SPLIT)
|
||||
univ.party[i].main_status -= eMainStatus::SPLIT;
|
||||
break;
|
||||
|
||||
|
||||
case 6:
|
||||
display_strings(20,7);
|
||||
for(i = 0; i < 4; i++)
|
||||
univ.party.creature_save[i].which_town = 200;
|
||||
break;
|
||||
case 8: // damage
|
||||
display_strings(1,15);
|
||||
for(i = 0; i < 6; i++)
|
||||
univ.party[i].cur_health = univ.party[i].max_health;
|
||||
break;
|
||||
case 9: // spell pts
|
||||
display_strings(2,15);
|
||||
for(i = 0; i < 6; i++)
|
||||
univ.party[i].cur_sp = univ.party[i].max_sp;
|
||||
break;
|
||||
case 10: // 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 11: // conditions
|
||||
display_strings(4,15);
|
||||
for(i = 0; i < 6; i++) {
|
||||
univ.party[i].status[eStatus::POISON] = 0;
|
||||
if(univ.party[i].status[eStatus::HASTE_SLOW] < 0)
|
||||
univ.party[i].status[eStatus::HASTE_SLOW] = 0;
|
||||
univ.party[i].status[eStatus::WEBS] = 0;
|
||||
univ.party[i].status[eStatus::DISEASE] = 0;
|
||||
univ.party[i].status[eStatus::DUMB] = 0;
|
||||
univ.party[i].status[eStatus::ASLEEP] = 0;
|
||||
univ.party[i].status[eStatus::PARALYZED] = 0;
|
||||
univ.party[i].status[eStatus::ACID] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
if(!party_in_scen) {
|
||||
display_strings(25,15);
|
||||
break;
|
||||
}
|
||||
if(cChoiceDlog("leave-scenario",{"okay","cancel"}).show() != "okay")
|
||||
break;
|
||||
remove_party_from_scen();
|
||||
break;
|
||||
}
|
||||
redraw_screen();
|
||||
}
|
||||
|
||||
void handle_edit_menu(int item_hit) {
|
||||
short i,j,k;
|
||||
|
||||
if(file_in_mem.empty()) {
|
||||
display_strings(5,7);
|
||||
return;
|
||||
}
|
||||
switch(item_hit) {
|
||||
case 1:
|
||||
display_alchemy(true);
|
||||
break;
|
||||
case 2: // all property
|
||||
display_strings(6,7);
|
||||
for(i = 0; i < 30; i++) {
|
||||
univ.party.boats[i].property = false;
|
||||
univ.party.horses[i].property = false;
|
||||
}
|
||||
break;
|
||||
case 4: // edit day
|
||||
edit_day();
|
||||
break;
|
||||
case 6: // ouit maps
|
||||
if(!party_in_scen) {
|
||||
display_strings(25,15);
|
||||
break;
|
||||
}
|
||||
display_strings(13,15);
|
||||
for(i = 0; i < 100; i++)
|
||||
for(j = 0; j < 6; j++)
|
||||
for(k = 0; k < 48; k++)
|
||||
univ.out_maps[i][j][k] = 255;
|
||||
break;
|
||||
case 7: // town maps
|
||||
if(!party_in_scen) {
|
||||
display_strings(25,15);
|
||||
break;
|
||||
}
|
||||
display_strings(14,15);
|
||||
for(i = 0; i < 200; i++)
|
||||
for(j = 0; j < 8; j++)
|
||||
for(k = 0; k < 64; k++)
|
||||
univ.town_maps[i][j][k] = 255;
|
||||
break;
|
||||
case 9:
|
||||
display_pc(current_active_pc,0,0);
|
||||
break;
|
||||
case 10:
|
||||
display_pc(current_active_pc,1,0);
|
||||
break;
|
||||
case 11:
|
||||
pick_race_abil(&univ.party[current_active_pc],0);
|
||||
break;
|
||||
case 12:
|
||||
spend_xp(current_active_pc,1,0);
|
||||
break;
|
||||
case 13:
|
||||
edit_xp(&univ.party[current_active_pc]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//item_record_type convert_item (short_item_record_type s_item) {
|
||||
// item_record_type i;
|
||||
// location l = {0,0};
|
||||
// short temp_val;
|
||||
//
|
||||
// i.variety = (short) s_item.variety;
|
||||
// i.item_level = (short) s_item.item_level;
|
||||
// i.awkward = (short) s_item.awkward;
|
||||
// i.bonus = (short) s_item.bonus;
|
||||
// i.protection = (short) s_item.protection;
|
||||
// i.charges = (short) s_item.charges;
|
||||
// i.type = (short) s_item.type;
|
||||
// i.graphic_num = (short) s_item.graphic_num;
|
||||
// if(i.graphic_num >= 25)
|
||||
// i.graphic_num += 20;
|
||||
// i.ability = (short) s_item.real_abil;
|
||||
// i.type_flag = (short) s_item.type_flag;
|
||||
// i.is_special = (short) s_item.is_special;
|
||||
// i.value = (short) s_item.value;
|
||||
// i.weight = s_item.weight;
|
||||
// i.special_class = 0;
|
||||
// i.item_loc = l;
|
||||
// strcpy((char *)i.full_name,(char *)s_item.full_name);
|
||||
// strcpy((char *)i.name,(char *)s_item.name);
|
||||
//
|
||||
// if(i.charges > 0)
|
||||
// temp_val = i.value * i.charges;
|
||||
// else temp_val = i.value;
|
||||
// if(temp_val >= 15)
|
||||
// i.treas_class = 1;
|
||||
// if(temp_val >= 100)
|
||||
// i.treas_class = 2;
|
||||
// if(temp_val >= 900)
|
||||
// i.treas_class = 3;
|
||||
// if(temp_val >= 2400)
|
||||
// i.treas_class = 4;
|
||||
//
|
||||
// i.magic_use_type = s_item.magic_use_type;
|
||||
// i.ability_strength = s_item.ability_strength;
|
||||
// i.reserved1 = 0;
|
||||
// i.reserved2 = 0;
|
||||
// i.item_properties = 0;
|
||||
// if(s_item.identified)
|
||||
// i.item_properties = i.item_properties | 1;
|
||||
// if((s_item.ability == 14) || (s_item.ability == 129) || (s_item.ability == 95))
|
||||
// i.item_properties = i.item_properties | 16;
|
||||
// if(s_item.magic)
|
||||
// i.item_properties = i.item_properties | 4;
|
||||
//
|
||||
// return i;
|
||||
//}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
//void set_cursor(CursHandle which_curs) {
|
||||
// HLock ((Handle) which_curs);
|
||||
// SetCursor (*which_curs);
|
||||
// HUnlock((Handle) which_curs);
|
||||
//}
|
||||
|
||||
//short mode; // 0 - quit 1- restore
|
||||
bool verify_restore_quit(bool mode) {
|
||||
std::string choice;
|
||||
|
||||
if(file_in_mem.empty())
|
||||
return true;
|
||||
cChoiceDlog verify(mode ? "save-open" : "save-quit", {"save", "quit", "cancel"});
|
||||
choice = verify.show();
|
||||
if(choice == "cancel")
|
||||
return false;
|
||||
if(choice == "quit")
|
||||
return true;
|
||||
save_party(file_in_mem, univ);
|
||||
return true;
|
||||
}
|
||||
|
||||
//pascal bool cd_event_filter (DialogPtr hDlg, EventRecord *event, short *dummy_item_hit) {
|
||||
// char chr,chr2;
|
||||
// short the_type,wind_hit,item_hit;
|
||||
// Handle the_handle = NULL;
|
||||
// rectangle the_rect,button_rect;
|
||||
// location the_point;
|
||||
// CWindowPtr w;
|
||||
// RgnHandle updateRgn;
|
||||
//
|
||||
// dummy_item_hit = 0;
|
||||
//
|
||||
// switch(event->what) {
|
||||
// case updateEvt:
|
||||
// w = GetDialogWindow(hDlg);
|
||||
// updateRgn = NewRgn();
|
||||
// GetWindowRegion(w, kWindowUpdateRgn, updateRgn);
|
||||
// if(EmptyRgn(updateRgn)) {
|
||||
// return true;
|
||||
// }
|
||||
// BeginUpdate(GetDialogWindow(hDlg));
|
||||
// cd_redraw(hDlg);
|
||||
// EndUpdate(GetDialogWindow(hDlg));
|
||||
// DrawDialog(hDlg);
|
||||
// return true;
|
||||
// break;
|
||||
//
|
||||
// case keyDown:
|
||||
// chr = event->message & charCodeMask;
|
||||
// chr2 = (char) ((event->message & keyCodeMask) >> 8);
|
||||
// switch(chr2) {
|
||||
// case 126: chr = 22; break;
|
||||
// case 124: chr = 21; break;
|
||||
// case 123: chr = 20; break;
|
||||
// case 125: chr = 23; break;
|
||||
// case 53: chr = 24; break;
|
||||
// case 36: chr = 31; break;
|
||||
// case 76: chr = 31; break;
|
||||
// }
|
||||
// // specials ... 20 - <- 21 - -> 22 up 23 down 24 esc
|
||||
// // 25-30 ctrl 1-6 31 - return
|
||||
//
|
||||
// wind_hit = cd_process_keystroke(hDlg,chr,&item_hit);
|
||||
// break;
|
||||
//
|
||||
// case mouseDown:
|
||||
// the_point = event->where;
|
||||
// GlobalToLocal(&the_point);
|
||||
// wind_hit = cd_process_click(hDlg,the_point, event->modifiers,&item_hit);
|
||||
// break;
|
||||
//
|
||||
// default: wind_hit = -1; break;
|
||||
// }
|
||||
// switch(wind_hit) {
|
||||
// case -1: break;
|
||||
//
|
||||
// case 917: edit_day_event_filter(item_hit); break;
|
||||
// case 970: case 971: case 972: case 973: display_strings_event_filter(item_hit); break;
|
||||
// case 991: display_pc_event_filter(item_hit); break;
|
||||
// case 996: display_alchemy_event_filter(item_hit); break;
|
||||
// case 1010: spend_xp_event_filter (item_hit); break;
|
||||
// case 1012: case 947: edit_gold_or_food_event_filter (item_hit); break;
|
||||
// case 1013: pick_race_abil_event_filter (item_hit); break;
|
||||
// case 1018: select_pc_event_filter (item_hit); break;
|
||||
// case 1024: edit_xp_event_filter (item_hit); break;
|
||||
// case 1073: give_reg_info_event_filter (item_hit); break;
|
||||
// default: fancy_choice_dialog_event_filter (item_hit); break;
|
||||
// }
|
||||
// return(wind_hit != -1);
|
||||
//}
|
1177
src/pcedit/pc.menu.xib
Normal file
1177
src/pcedit/pc.menu.xib
Normal file
File diff suppressed because it is too large
Load Diff
16
src/pcedit/pc.menus.h
Normal file
16
src/pcedit/pc.menus.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// pc.menus.h
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 14-04-15.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef BoE_pc_menus_h
|
||||
#define BoE_pc_menus_h
|
||||
|
||||
void init_menubar();
|
||||
void update_item_menu();
|
||||
void menu_activate();
|
||||
|
||||
#endif
|
160
src/pcedit/pc.menus.mac.mm
Normal file
160
src/pcedit/pc.menus.mac.mm
Normal file
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// pc.menus.mac.mm
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 14-04-15.
|
||||
//
|
||||
//
|
||||
|
||||
#include "pc.menus.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "item.h"
|
||||
#include "universe.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error pc.menus.mm is Mac-specific code; try compiling pc.menus.win.cpp instead
|
||||
#endif
|
||||
|
||||
using MenuHandle = NSMenu*;
|
||||
|
||||
extern void handle_apple_menu(int item_hit);
|
||||
extern void handle_file_menu(int item_hit);
|
||||
extern void handle_extra_menu(int item_hit);
|
||||
extern void handle_edit_menu(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;
|
||||
MenuHandle menu_bar_handle;
|
||||
MenuHandle apple_menu, file_menu, reg_menu, extra_menu, items_menu[4];
|
||||
|
||||
@interface MenuHandler : NSObject
|
||||
-(void) fileMenu:(id) sender;
|
||||
-(void) freeMenu:(id) sender;
|
||||
-(void) specMenu:(id) sender;
|
||||
-(void) itemMenu:(id) sender;
|
||||
-(void) helpMenu:(id) sender;
|
||||
@end
|
||||
|
||||
@interface ItemWrapper : NSObject
|
||||
+(id) withItem:(int) theItem;
|
||||
-(cItemRec&) item;
|
||||
-(void) setItem:(int) theItem;
|
||||
@end
|
||||
|
||||
static void setMenuCallback(NSMenuItem* item, id targ, SEL selector, int num) {
|
||||
[item setTarget: targ];
|
||||
[item setAction: selector];
|
||||
[item setRepresentedObject: [[NSNumber numberWithInt: num] retain]];
|
||||
}
|
||||
|
||||
void init_menubar() {
|
||||
NSApplication* app = [NSApplication sharedApplication];
|
||||
[NSBundle loadNibNamed: @"pc.menu" owner: app];
|
||||
menu_bar_handle = [app mainMenu];
|
||||
|
||||
apple_menu = [[menu_bar_handle itemWithTitle: @"BoE Character Editor"] submenu];
|
||||
file_menu = [[menu_bar_handle itemWithTitle: @"File"] submenu];
|
||||
reg_menu = [[menu_bar_handle itemWithTitle: @"Free Extras"] submenu];
|
||||
extra_menu = [[menu_bar_handle itemWithTitle: @"Special Edit"] submenu];
|
||||
items_menu[0] = [[menu_bar_handle itemWithTitle: @"Items 1"] submenu];
|
||||
items_menu[1] = [[menu_bar_handle itemWithTitle: @"Items 2"] submenu];
|
||||
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);
|
||||
|
||||
for(int i = 0; i < [reg_menu numberOfItems]; i++)
|
||||
setMenuCallback([reg_menu itemAtIndex: i], handler, @selector(freeMenu:), i + 1);
|
||||
for(int i = 0; i < [extra_menu numberOfItems]; i++)
|
||||
setMenuCallback([extra_menu itemAtIndex: i], handler, @selector(specMenu:), i + 1);
|
||||
|
||||
update_item_menu();
|
||||
menu_activate();
|
||||
}
|
||||
|
||||
void menu_activate() {
|
||||
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];
|
||||
}
|
||||
|
||||
void update_item_menu() {
|
||||
id targ = [[file_menu itemAtIndex: 0] target];
|
||||
cItemRec(& item_list)[400] = univ.scenario.scen_items;
|
||||
for(int j = 0; j < 4; j++){
|
||||
[items_menu[j] removeAllItems];
|
||||
if(!scen_items_loaded) {
|
||||
[[items_menu[j] addItemWithTitle: @"Items Not Loaded" action: @selector(itemMenu:) keyEquivalent: @""] setEnabled: NO];
|
||||
} else for(int i = 0; i < 100; i++) {
|
||||
ItemWrapper* item = [ItemWrapper withItem: i + 100 * j];
|
||||
NSString* item_name = [NSString stringWithCString: item_list[i + j * 100].full_name.c_str() encoding: NSASCIIStringEncoding];
|
||||
NSMenuItem* choice = [items_menu[j] addItemWithTitle: item_name action: @selector(itemMenu:) keyEquivalent: @""];
|
||||
[choice setTarget: targ];
|
||||
// TODO: Also disable gold or food
|
||||
[choice setEnabled: [item item].variety != eItemType::NO_ITEM];
|
||||
[choice setRepresentedObject: item];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@implementation MenuHandler
|
||||
-(void) fileMenu:(id) sender {
|
||||
handle_file_menu([[sender representedObject] shortValue]);
|
||||
}
|
||||
|
||||
-(void) freeMenu:(id) sender {
|
||||
handle_extra_menu([[sender representedObject] shortValue]);
|
||||
}
|
||||
|
||||
-(void) specMenu:(id) sender {
|
||||
handle_edit_menu([[sender representedObject] shortValue]);
|
||||
}
|
||||
|
||||
-(void) itemMenu:(id) sender {
|
||||
ItemWrapper* item = [sender representedObject];
|
||||
cItemRec& theItem = [item item];
|
||||
(void) theItem; // Suppress "unused parameter" warning
|
||||
for(int i = 0; i < 4; i++) {
|
||||
int whichItem = [items_menu[i] indexOfItem: sender];
|
||||
if(whichItem >= 0)
|
||||
handle_item_menu(whichItem + 100 * i);
|
||||
}
|
||||
}
|
||||
|
||||
-(void) helpMenu:(id) sender {
|
||||
int i = [[sender representedObject] intValue];
|
||||
if(i == 0); // TODO: "BoE Character Editor Help"
|
||||
else if(i == 1) handle_apple_menu(i);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ItemWrapper {
|
||||
int itemID;
|
||||
}
|
||||
|
||||
+(id) withItem:(int) theItem {
|
||||
ItemWrapper* item = [[ItemWrapper alloc] init];
|
||||
[item setItem: theItem];
|
||||
return item;
|
||||
}
|
||||
|
||||
-(void) setItem:(int) theItem {
|
||||
self->itemID = theItem;
|
||||
}
|
||||
|
||||
-(cItemRec&) item {
|
||||
return univ.scenario.scen_items[self->itemID];
|
||||
}
|
||||
|
||||
@end
|
Reference in New Issue
Block a user