1952 lines
69 KiB
C++
1952 lines
69 KiB
C++
#include <cstdio>
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <boost/lexical_cast.hpp>
|
|
#include "scen.global.h"
|
|
#include "classes.h"
|
|
#include "graphtool.h"
|
|
#include "scen.graphics.h"
|
|
//#include "itemlist.h"
|
|
#include "scen.core.h"
|
|
#include "scen.keydlgs.h"
|
|
#include "scen.townout.h"
|
|
#include "scen.fileio.h"
|
|
#include "scen.actions.h"
|
|
#include "dialog.h"
|
|
#include "dlogutil.h"
|
|
#include "fileio.h"
|
|
#include "field.h"
|
|
#include "restypes.hpp"
|
|
|
|
extern std::string get_str(std::string list, short j);
|
|
extern short cen_x, cen_y,/* overall_mode,*/cur_town;
|
|
extern bool mouse_button_held;
|
|
extern short cur_viewing_mode;
|
|
extern cTown* town;
|
|
//extern short town_type; // 0 - big 1 - ave 2 - small
|
|
extern short max_dim[3];
|
|
extern short mode_count,to_create;
|
|
extern ter_num_t template_terrain[64][64];
|
|
extern cScenario scenario;
|
|
extern cSpecial null_spec_node;
|
|
extern cSpeech null_talk_node;
|
|
//extern piles_of_stuff_dumping_type *data_store;
|
|
extern location cur_out;
|
|
extern short start_volume, start_dir;
|
|
|
|
void init_scenario() {
|
|
short i;
|
|
rectangle dummy_rect;
|
|
std::string temp_str;
|
|
cVehicle null_boat;// = {{0,0},{0,0},{0,0},-1,false,false};
|
|
cVehicle null_horse;// = {{0,0},{0,0},{0,0},-1,false,false};
|
|
cScenario::cItemStorage null_item_s;// ={-1,{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{0,0,0,0,0,0,0,0,0,0},0};
|
|
short j;
|
|
|
|
scenario.format.ver[0] = 1;
|
|
scenario.format.ver[1] = 0;
|
|
scenario.format.ver[2] = 0;
|
|
scenario.format.min_run_ver = 1;
|
|
scenario.format.prog_make_ver[0] = 1;
|
|
scenario.format.prog_make_ver[1] = 0;
|
|
scenario.format.prog_make_ver[2] = 0;
|
|
scenario.num_towns = 1;
|
|
scenario.out_width = 1;
|
|
scenario.out_height = 1;
|
|
scenario.difficulty = 0;
|
|
scenario.intro_pic = 0;
|
|
scenario.default_ground = 1;
|
|
for (i = 0; i < 200; i++) {
|
|
scenario.town_size[i] = 1;
|
|
scenario.town_hidden[i] = 0;
|
|
scenario.town_data_size[i][0] = 0;
|
|
scenario.town_data_size[i][1] = 0;
|
|
scenario.town_data_size[i][2] = 0;
|
|
scenario.town_data_size[i][3] = 0;
|
|
scenario.town_data_size[i][4] = 0;
|
|
}
|
|
scenario.intro_mess_len = 0;
|
|
scenario.where_start.x = 24;
|
|
scenario.where_start.y = 24;
|
|
scenario.out_sec_start.x = 0;
|
|
scenario.out_sec_start.y = 0;
|
|
scenario.out_start = scenario.where_start;
|
|
scenario.which_town_start = 0;
|
|
for (i = 0; i < 10; i++) {
|
|
scenario.town_to_add_to[i] = -1;
|
|
scenario.flag_to_add_to_town[i][0] = 0;
|
|
scenario.flag_to_add_to_town[i][1] = 0;
|
|
}
|
|
for (i = 0; i < 100; i++) {
|
|
scenario.out_data_size[i][0] = 0;
|
|
scenario.out_data_size[i][1] = 0;
|
|
}
|
|
for (i = 0; i < 3; i++) {
|
|
scenario.store_item_rects[i] = dummy_rect;
|
|
scenario.store_item_towns[i] = -1;
|
|
}
|
|
for (i = 0; i < 50; i++) {
|
|
scenario.special_items[i].flags = 0;
|
|
scenario.special_items[i].special = -1;
|
|
}
|
|
scenario.rating = 0;
|
|
scenario.uses_custom_graphics = 0;
|
|
for (i = 0; i < 256; i++) {
|
|
scenario.scen_monsters[i] = cMonster();
|
|
}
|
|
for (i = 0; i < 30; i++) {
|
|
scenario.boats[i] = null_boat;
|
|
scenario.horses[i] = null_horse;
|
|
}
|
|
for (i = 0; i < 256; i++) {
|
|
scenario.ter_types[i] = cTerrain();
|
|
|
|
scenario.scen_specials[i] = null_spec_node;
|
|
}
|
|
for (i = 0; i < 20; i++) {
|
|
scenario.scenario_timer_times[i] = 0;
|
|
scenario.scenario_timer_specs[i] = -1;
|
|
}
|
|
for (i = 0; i < 10; i++) {
|
|
scenario.storage_shortcuts[i] = null_item_s;
|
|
}
|
|
scenario.last_out_edited.x = 0;
|
|
scenario.last_out_edited.y = 0;
|
|
scenario.last_town_edited = 0;
|
|
for (i = 0; i < 400; i++) {
|
|
scenario.scen_items[i] = cItemRec();
|
|
}
|
|
for (i = 0; i < 270; i++) {
|
|
temp_str = get_str("scen-default",i + 1);
|
|
sprintf((char *)scenario.scen_strs(i), "%s", temp_str.c_str());
|
|
scenario.scen_str_len[i] = strlen(scenario.scen_strs(i));
|
|
}
|
|
}
|
|
|
|
bool save_ter_info(cDialog& me, cTerrain& store_ter) {
|
|
char str[256];
|
|
short i;
|
|
|
|
store_ter.picture = me["pict"].getTextAsNum();
|
|
// TODO: Should somehow verify the pict number is valid
|
|
|
|
std::string blockage = dynamic_cast<cLedGroup&>(me["blockage"]).getSelected();
|
|
if(blockage == "clear") store_ter.blockage = eTerObstruct::CLEAR;
|
|
else if(blockage == "curtain") store_ter.blockage = eTerObstruct::BLOCK_SIGHT;
|
|
else if(blockage == "special") store_ter.blockage = eTerObstruct::BLOCK_MONSTERS;
|
|
else if(blockage == "window") store_ter.blockage = eTerObstruct::BLOCK_MOVE;
|
|
else if(blockage == "obstructed") store_ter.blockage = eTerObstruct::BLOCK_MOVE_AND_SHOOT;
|
|
else if(blockage == "opaque") store_ter.blockage = eTerObstruct::BLOCK_MOVE_AND_SIGHT;
|
|
store_ter.special = (eTerSpec) boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["prop"]).getSelected().substr(4));
|
|
/*
|
|
i = CDGN(813,6);
|
|
if ((store_ter.special < 2) || (store_ter.special > 6)) {
|
|
if (cre(i,0,256,"First special flag must be from 0 to 255.","",813) == true) return false;
|
|
}
|
|
else if (store_ter.special == TER_SPEC_DAMAGING) {
|
|
if (cre(i,0,256,"First special flag must be from 0 to 100.","",813) == true) return false;
|
|
}
|
|
else if (store_ter.special == TER_SPEC_DANGEROUS) {
|
|
if (cre(i,0,256,"First special flag must be from 0 to 8.","",813) == true) return false;
|
|
}
|
|
*/
|
|
if(store_ter.special == TER_SPEC_NONE)
|
|
store_ter.flag1.s = me["flag1"].getTextAsNum();
|
|
else store_ter.flag1.u = me["flag1"].getTextAsNum();
|
|
if(false) // flag2 is never signed, apparently; but that could change?
|
|
store_ter.flag2.s = me["flag2"].getTextAsNum();
|
|
else store_ter.flag2.u = me["flag2"].getTextAsNum();
|
|
if(store_ter.special == TER_SPEC_CALL_SPECIAL || store_ter.special == TER_SPEC_CALL_SPECIAL_WHEN_USED)
|
|
store_ter.flag3.s = me["flag3"].getTextAsNum();
|
|
else store_ter.flag3.u = me["flag3"].getTextAsNum();
|
|
|
|
/*
|
|
if (store_ter.special == TER_SPEC_TOWN_ENTRANCE) {
|
|
if (cre(i,0,256,"Second special flag must be from 0 to 200.","",813) == true) return false;
|
|
}
|
|
else if ((store_ter.special == TER_SPEC_DAMAGING) || (store_ter.special == TER_SPEC_DANGEROUS)) {
|
|
if (cre(i,0,256,"Second special flag must be from 0 to 100.","",813) == true) return false;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
if (cre(i,0,255,"Transform To What must be from 0 to 255.","",813) == true) return false;
|
|
*/
|
|
store_ter.trans_to_what = me["trans"].getTextAsNum();
|
|
store_ter.fly_over = dynamic_cast<cLed&>(me["flight"]).getState() == led_red;
|
|
store_ter.boat_over = dynamic_cast<cLed&>(me["boat"]).getState() == led_red;
|
|
store_ter.block_horse = dynamic_cast<cLed&>(me["horse"]).getState();
|
|
store_ter.light_radius = me["light"].getTextAsNum();
|
|
/*
|
|
if (cre(store_ter.light_radius,0,8,"Light radius must be from 0 to 8.","",813) == true) return false;
|
|
*/
|
|
|
|
std::string sound = dynamic_cast<cLedGroup&>(me["sound"]).getSelected();
|
|
// TODO: Uh, why not use an actual sound number instead of 0...4?
|
|
if(sound == "step") store_ter.step_sound = 0;
|
|
else if(sound == "squish") store_ter.step_sound = 1;
|
|
else if(sound == "crunch") store_ter.step_sound = 2;
|
|
else if(sound == "nosound") store_ter.step_sound = 3;
|
|
else if(sound == "splash") store_ter.step_sound = 4;
|
|
|
|
std::string shortcut = me["key"].getText();
|
|
if(shortcut.length() > 0) store_ter.shortcut_key = shortcut[0];
|
|
else store_ter.shortcut_key = 0;
|
|
|
|
store_ter.name = me["name"].getText();
|
|
|
|
store_ter.ground_type = me["ground"].getTextAsNum();
|
|
store_ter.trim_ter = me["trimter"].getTextAsNum();
|
|
store_ter.trim_type = (eTrimType) me["trim"].getTextAsNum();
|
|
store_ter.combat_arena = me["arena"].getTextAsNum();
|
|
store_ter.map_pic = me["map"].getTextAsNum();
|
|
|
|
return true;
|
|
}
|
|
|
|
// TODO: It would probably be good to use these for other dialogs, instead of the monolithic event filters
|
|
bool check_range_msg(cDialog& me,std::string id,bool losing,long min_val,long max_val,std::string fld_name,std::string xtra){
|
|
if(!losing) return true;
|
|
cTextField& fld_ctrl = dynamic_cast<cTextField&>(me[id]);
|
|
long n = fld_ctrl.getTextAsNum();
|
|
if(n < min_val || n > max_val){
|
|
std::ostringstream sout;
|
|
sout << fld_name << " must be from " << min_val << " to " << max_val;
|
|
if(!xtra.empty()) sout << ' ' << '(' << xtra << ')';
|
|
giveError(sout.str(), "", &me);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool check_range(cDialog& me,std::string id,bool losing,long min_val,long max_val,std::string fld_name) {
|
|
return check_range_msg(me, id, losing, min_val, max_val, fld_name, "");
|
|
}
|
|
|
|
bool pick_picture(ePicType type, cDialog& parent, std::string result_fld, std::string pic_fld, pic_num_t modifier){
|
|
pic_num_t cur_sel = 0;
|
|
if(result_fld != ""){
|
|
cControl& fld_ctrl = parent[result_fld];
|
|
cur_sel = fld_ctrl.getTextAsNum();
|
|
cur_sel -= modifier;
|
|
}else if(pic_fld != ""){
|
|
cPict& pic_ctrl = dynamic_cast<cPict&>(parent[pic_fld]);
|
|
if(pic_ctrl.getPicType() == type)
|
|
cur_sel = pic_ctrl.getPicNum();
|
|
}
|
|
pic_num_t pic = choose_graphic(cur_sel, type, &parent);
|
|
if(pic < NO_PIC){
|
|
if(result_fld != ""){
|
|
cTextField& fld_ctrl = dynamic_cast<cTextField&>(parent[result_fld]);
|
|
fld_ctrl.setTextToNum(pic + modifier);
|
|
}
|
|
if(pic_fld != ""){
|
|
cPict& pic_ctrl = dynamic_cast<cPict&>(parent[pic_fld]);
|
|
pic_ctrl.setPict(pic,type);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool pick_string(std::string from_file, cDialog& parent, std::string result_fld, std::string str_fld){
|
|
size_t cur_sel = 0;
|
|
if(result_fld != ""){
|
|
cTextField& fld_ctrl = dynamic_cast<cTextField&>(parent[result_fld]);
|
|
cur_sel = fld_ctrl.getTextAsNum();
|
|
}
|
|
StringRsrc strings = *ResMgr::get<StringRsrc>(from_file);
|
|
// TODO: Does it need a title?
|
|
cStringChoice str_dlg(strings, "", &parent);
|
|
size_t result = str_dlg.show(strings[cur_sel]);
|
|
if(result < strings.size()){
|
|
if(result_fld != ""){
|
|
cTextField& fld_ctrl = dynamic_cast<cTextField&>(parent[result_fld]);
|
|
fld_ctrl.setTextToNum(result);
|
|
}
|
|
if(str_fld != ""){
|
|
parent[str_fld].setText(strings[result]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool show_help(std::string from_file, cDialog& parent, pic_num_t pic){
|
|
StringRsrc strings = *ResMgr::get<StringRsrc>(from_file);
|
|
cThreeChoice help(strings,basic_buttons[63],pic,PIC_DLOG,&parent);
|
|
help.show();
|
|
return true;
|
|
}
|
|
|
|
bool fill_ter_flag_info(cDialog& me, std::string id, bool dummy){
|
|
eTerSpec prop;
|
|
cLedGroup& led_ctrl = dynamic_cast<cLedGroup&>(me[id]);
|
|
std::istringstream sel(led_ctrl.getSelected().substr(4));
|
|
sel >> prop;
|
|
me["flag1text"].setText(get_str("ter-flag1",prop + 1));
|
|
me["flag2text"].setText(get_str("ter-flag2",prop + 1));
|
|
me["flag3text"].setText(get_str("ter-flag3",prop + 1));
|
|
me["pickflag1"].hide();
|
|
me["pickflag2"].hide();
|
|
me["pickflag3"].hide();
|
|
switch(prop) {
|
|
case TER_SPEC_NONE:
|
|
me["pickflag1"].hide(); // TODO: Could have a pick graphic dialog for the editor icon, but that requires adding a new graphic type
|
|
break;
|
|
}
|
|
// TODO: Click handlers for the "choose" buttons as necessary, plus hide/show them as needed
|
|
return true;
|
|
}
|
|
|
|
void fill_ter_info(cDialog& me, short ter){
|
|
cTerrain& ter_type = scenario.ter_types[ter];
|
|
{
|
|
cPict& pic_ctrl = dynamic_cast<cPict&>(me["graphic"]);
|
|
pic_num_t pic = ter_type.picture;
|
|
if(pic < 400)
|
|
pic_ctrl.setPict(pic, PIC_TER);
|
|
else if(pic < 1000)
|
|
pic_ctrl.setPict(pic % 400, PIC_TER_ANIM);
|
|
else if(pic < 2000)
|
|
pic_ctrl.setPict(pic % 1000, PIC_CUSTOM_TER);
|
|
else
|
|
pic_ctrl.setPict(pic % 2000, PIC_CUSTOM_TER_ANIM);
|
|
me["pict"].setTextToNum(pic);
|
|
}{
|
|
cPict& pic_ctrl = dynamic_cast<cPict&>(me["seemap"]);
|
|
pic_num_t pic = ter_type.map_pic;
|
|
if(pic < 1000)
|
|
pic_ctrl.setPict(pic, PIC_TER_MAP);
|
|
else pic_ctrl.setPict(pic, PIC_CUSTOM_TER_MAP);
|
|
me["map"].setTextToNum(pic);
|
|
}
|
|
me["number"].setTextToNum(ter);
|
|
me["name"].setText(ter_type.name);
|
|
me["key"].setTextToNum(ter_type.shortcut_key);
|
|
me["light"].setTextToNum(ter_type.light_radius);
|
|
me["trans"].setTextToNum(ter_type.trans_to_what);
|
|
me["ground"].setTextToNum(ter_type.ground_type);
|
|
me["trimter"].setTextToNum(ter_type.trim_ter);
|
|
// TODO: Replace edit text box for trim with a framed name and Select button
|
|
me["trim"].setTextToNum((int)ter_type.trim_type);
|
|
std::string propid = "prop" + std::to_string(ter_type.special);
|
|
dynamic_cast<cLedGroup&>(me["prop"]).setSelected(propid);
|
|
fill_ter_flag_info(me, "prop", false);
|
|
{
|
|
cLedGroup& led_ctrl = dynamic_cast<cLedGroup&>(me["blockage"]);
|
|
switch(ter_type.blockage){
|
|
case eTerObstruct::CLEAR:
|
|
led_ctrl.setSelected("clear");
|
|
break;
|
|
case eTerObstruct::BLOCK_SIGHT:
|
|
led_ctrl.setSelected("curtain");
|
|
break;
|
|
case eTerObstruct::BLOCK_MONSTERS:
|
|
led_ctrl.setSelected("special");
|
|
break;
|
|
case eTerObstruct::BLOCK_MOVE:
|
|
led_ctrl.setSelected("window");
|
|
break;
|
|
case eTerObstruct::BLOCK_MOVE_AND_SHOOT:
|
|
led_ctrl.setSelected("obstructed");
|
|
break;
|
|
case eTerObstruct::BLOCK_MOVE_AND_SIGHT:
|
|
led_ctrl.setSelected("opaque");
|
|
break;
|
|
}
|
|
}{
|
|
cLedGroup& led_ctrl = dynamic_cast<cLedGroup&>(me["sound"]);
|
|
switch(ter_type.step_sound){
|
|
case 0:
|
|
led_ctrl.setSelected("step");
|
|
break;
|
|
case 1:
|
|
led_ctrl.setSelected("squish");
|
|
break;
|
|
case 2:
|
|
led_ctrl.setSelected("crunch");
|
|
break;
|
|
case 3:
|
|
led_ctrl.setSelected("nosound");
|
|
break;
|
|
case 4:
|
|
led_ctrl.setSelected("splash");
|
|
break;
|
|
}
|
|
}
|
|
if(ter_type.fly_over){
|
|
cLed& led_ctrl = dynamic_cast<cLed&>(me["flight"]);
|
|
led_ctrl.setState(led_red);
|
|
}
|
|
if(ter_type.boat_over){
|
|
cLed& led_ctrl = dynamic_cast<cLed&>(me["boat"]);
|
|
led_ctrl.setState(led_red);
|
|
}
|
|
if(ter_type.block_horse){
|
|
cLed& led_ctrl = dynamic_cast<cLed&>(me["horse"]);
|
|
led_ctrl.setState(led_red);
|
|
}
|
|
if(ter_type.special == TER_SPEC_NONE)
|
|
me["flag1"].setTextToNum(ter_type.flag1.s);
|
|
else me["flag1"].setTextToNum(ter_type.flag1.u);
|
|
if(false) // flag2 is never signed, apparently; but that could change?
|
|
me["flag2"].setTextToNum(ter_type.flag2.s);
|
|
else me["flag2"].setTextToNum(ter_type.flag2.u);
|
|
if(ter_type.special == TER_SPEC_CALL_SPECIAL || ter_type.special == TER_SPEC_CALL_SPECIAL_WHEN_USED)
|
|
me["flag3"].setTextToNum(ter_type.flag3.s);
|
|
else me["flag3"].setTextToNum(ter_type.flag3.u);
|
|
me["arena"].setTextToNum(ter_type.combat_arena);
|
|
}
|
|
|
|
bool finish_editing_ter(cDialog& me, std::string id, ter_num_t& which_ter) {
|
|
if(!save_ter_info(me, scenario.ter_types[which_ter])) return true;
|
|
|
|
if(id == "done") me.toast();
|
|
else if(id == "left") {
|
|
// TODO: Use size() once ter_types becomes a vector
|
|
if(which_ter == 0) which_ter = 255;
|
|
else which_ter--;
|
|
fill_ter_info(me, which_ter);
|
|
} else if(id == "right") {
|
|
which_ter++;
|
|
if(which_ter > 255) which_ter = 0;
|
|
fill_ter_info(me, which_ter);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
short edit_ter_type(ter_num_t which_ter) {
|
|
using namespace std::placeholders;
|
|
cDialog ter_dlg("edit-terrain.xml");
|
|
// Attach handlers
|
|
ter_dlg["pict"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,2999,"terrain graphic"));
|
|
ter_dlg["pickpict"].attachClickHandler(std::bind(pick_picture,PIC_TER,_1,"pict","graphic",0));
|
|
ter_dlg["pickanim"].attachClickHandler(std::bind(pick_picture,PIC_TER_ANIM,_1,"pict","graphic",400));
|
|
ter_dlg["light"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,255,"light radius"));
|
|
ter_dlg["trans"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,65535,"\"transform to what?\""));
|
|
ter_dlg["ground"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,255,"ground type"));
|
|
ter_dlg["trimter"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,255,"trim terrain"));
|
|
ter_dlg["trim"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,18,"trim type"));
|
|
ter_dlg["prop"].attachFocusHandler(fill_ter_flag_info);
|
|
ter_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, &ter_dlg));
|
|
ter_dlg["arena"].attachFocusHandler(std::bind(check_range,_1,_2,_3,0,299,"ground type"));
|
|
// TODO: Add focus handler for key
|
|
// TODO: Add click handler for object
|
|
ter_dlg.attachClickHandlers(std::bind(finish_editing_ter,_1,_2,std::ref(which_ter)), {"left", "right", "done"});
|
|
ter_dlg["picktrim"].attachClickHandler(std::bind(pick_string,"trim-names", _1, "trim", ""));
|
|
ter_dlg["pickarena"].attachClickHandler(std::bind(pick_string,"arena-names", _1, "arena", ""));
|
|
ter_dlg["help"].attachClickHandler(std::bind(show_help, "ter-type-help", _1, 16));
|
|
fill_ter_info(ter_dlg,which_ter);
|
|
ter_dlg.run();
|
|
// TODO: What should be returned?
|
|
return 0;
|
|
}
|
|
|
|
void put_monst_info_in_dlog(cDialog& me, m_num_t which_monst) {
|
|
char str[256];
|
|
cMonster& store_monst = scenario.scen_monsters[which_monst];
|
|
|
|
if (store_monst.picture_num < 1000)
|
|
dynamic_cast<cPict&>(me["icon"]).setPict(store_monst.picture_num,PIC_MONST);
|
|
else {
|
|
ePicType type_g = PIC_CUSTOM_MONST;
|
|
short size_g = store_monst.picture_num / 1000;
|
|
switch(size_g){
|
|
case 2:
|
|
type_g += PIC_WIDE;
|
|
break;
|
|
case 3:
|
|
type_g += PIC_TALL;
|
|
break;
|
|
case 4:
|
|
type_g += PIC_LARGE;
|
|
break;
|
|
}
|
|
dynamic_cast<cPict&>(me["icon"]).setPict(store_monst.picture_num,type_g);
|
|
}
|
|
me["num"].setTextToNum(which_monst);
|
|
me["name"].setText(store_monst.m_name);
|
|
me["pic"].setTextToNum(store_monst.picture_num);
|
|
sprintf((char *) str,"Width = %d",store_monst.x_width);
|
|
me["w"].setText(str);
|
|
sprintf((char *) str,"Height = %d",store_monst.y_width);
|
|
me["h"].setText(str);
|
|
me["level"].setTextToNum(store_monst.level);
|
|
me["health"].setTextToNum(store_monst.m_health);
|
|
me["armor"].setTextToNum(store_monst.armor);
|
|
me["skill"].setTextToNum(store_monst.skill);
|
|
me["speed"].setTextToNum(store_monst.speed);
|
|
me["mage"].setTextToNum(store_monst.mu);
|
|
me["priest"].setTextToNum(store_monst.cl);
|
|
me["dice1"].setTextToNum(store_monst.a[0].dice);
|
|
me["sides1"].setTextToNum(store_monst.a[0].sides);
|
|
me["dice2"].setTextToNum(store_monst.a[1].dice);
|
|
me["sides2"].setTextToNum(store_monst.a[1].sides);
|
|
me["dice3"].setTextToNum(store_monst.a[2].dice);
|
|
me["sides3"].setTextToNum(store_monst.a[2].sides);
|
|
me["talk"].setTextToNum(store_monst.default_facial_pic);
|
|
me["treas"].setTextToNum(store_monst.treasure);
|
|
|
|
cLedGroup& attitude = dynamic_cast<cLedGroup&>(me["attitude"]);
|
|
switch(store_monst.default_attitude) {
|
|
case 0:
|
|
attitude.setSelected("docile");
|
|
break;
|
|
case 1:
|
|
attitude.setSelected("A");
|
|
break;
|
|
case 2:
|
|
attitude.setSelected("friendly");
|
|
break;
|
|
case 3:
|
|
attitude.setSelected("B");
|
|
break;
|
|
}
|
|
|
|
me["type"].setText(get_str("monster-abilities",150 + store_monst.m_type));
|
|
me["type1"].setText(get_str("monster-abilities",130 + store_monst.a[0].type));
|
|
me["type2"].setText(get_str("monster-abilities",130 + store_monst.a[1].type));
|
|
// TODO: Attack 3 type
|
|
// me["type3"].setText(get_str("monster-abilities",130 + store_monst.a[2].type));
|
|
}
|
|
|
|
bool check_monst_pic(cDialog& me, std::string id, bool losing, cMonster& store_monst) {
|
|
if(!losing) return true;
|
|
if(check_range(me, id, losing, 0, 4999, "Monster pic")) {
|
|
// later check pic num for error, and assign widths if custom
|
|
if (store_monst.picture_num >= 1000) {
|
|
if ((store_monst.picture_num >= 1000) && (store_monst.picture_num < 2000)) {
|
|
store_monst.x_width = 1;
|
|
store_monst.y_width = 1;
|
|
}
|
|
if ((store_monst.picture_num >= 2000) && (store_monst.picture_num < 3000)) {
|
|
store_monst.x_width = 2;
|
|
store_monst.y_width = 1;
|
|
}
|
|
if ((store_monst.picture_num >= 3000) && (store_monst.picture_num < 4000)) {
|
|
store_monst.x_width = 1;
|
|
store_monst.y_width = 2;
|
|
}
|
|
if ((store_monst.picture_num >= 4000) && (store_monst.picture_num < 5000)) {
|
|
store_monst.x_width = 2;
|
|
store_monst.y_width = 2;
|
|
}
|
|
}
|
|
else {
|
|
// TODO: Update this with new value if more monster pictures are added later
|
|
if (cre(store_monst.picture_num,0,200,"Non-customized monster pic must be from 0 to 200.","",&me) > 0) return false;
|
|
store_monst.x_width = m_pic_index[store_monst.picture_num].x;
|
|
store_monst.y_width = m_pic_index[store_monst.picture_num].y;
|
|
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool save_monst_info(cDialog& me, cMonster& store_monst) {
|
|
char str[256];
|
|
short i;
|
|
|
|
store_monst.m_name = me["name"].getText();
|
|
store_monst.picture_num = me["pic"].getTextAsNum();
|
|
store_monst.level = me["level"].getTextAsNum();
|
|
store_monst.m_health = me["health"].getTextAsNum();
|
|
store_monst.armor = me["armor"].getTextAsNum();
|
|
store_monst.skill = me["skill"].getTextAsNum();
|
|
store_monst.speed = me["speed"].getTextAsNum();
|
|
store_monst.mu = me["mage"].getTextAsNum();
|
|
store_monst.cl = me["priest"].getTextAsNum();
|
|
|
|
store_monst.a[0].dice = me["dice1"].getTextAsNum();
|
|
store_monst.a[1].dice = me["dice2"].getTextAsNum();
|
|
store_monst.a[2].dice = me["dice3"].getTextAsNum();
|
|
store_monst.a[0].sides = me["sides1"].getTextAsNum();
|
|
store_monst.a[1].sides = me["sides2"].getTextAsNum();
|
|
store_monst.a[2].sides = me["sides3"].getTextAsNum();
|
|
|
|
store_monst.default_facial_pic = me["talk"].getTextAsNum();
|
|
store_monst.treasure = me["treas"].getTextAsNum();
|
|
std::string def_att = dynamic_cast<cLedGroup&>(me["attitude"]).getSelected();
|
|
if(def_att == "docile") store_monst.default_attitude = 0;
|
|
else if(def_att == "friendly") store_monst.default_attitude = 2;
|
|
else if(def_att == "A") store_monst.default_attitude = 1;
|
|
else if(def_att == "B") store_monst.default_attitude = 3;
|
|
return true;
|
|
}
|
|
|
|
static bool edit_monst_type_event_filter(cDialog& me,std::string item_hit,cMonster& store_monst,short which_monst) {
|
|
short i;
|
|
cMonster temp_monst;
|
|
|
|
if(item_hit == "okay") {
|
|
if(save_monst_info(me,store_monst)) {
|
|
scenario.scen_monsters[which_monst] = store_monst;
|
|
me.toast();
|
|
}
|
|
} else if(item_hit == "abils") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
temp_monst = edit_monst_abil(store_monst,which_monst);
|
|
if (temp_monst.level < 255)
|
|
store_monst = temp_monst;
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
} else if(item_hit == "left") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
scenario.scen_monsters[which_monst] = store_monst;
|
|
which_monst--;
|
|
// TODO: Use size() once scen_monsters becomes a vector
|
|
if(which_monst < 1) which_monst = 255;
|
|
store_monst = scenario.scen_monsters[which_monst];
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
} else if(item_hit == "right") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
scenario.scen_monsters[which_monst] = store_monst;
|
|
which_monst++;
|
|
if(which_monst > 255) which_monst = 1;
|
|
store_monst = scenario.scen_monsters[which_monst];
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
} else if(item_hit == "picktype") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
i = choose_text_res("monster-abilities",150,164,store_monst.m_type + 150,&me,"Choose Monster Type:");
|
|
if (i >= 0) {
|
|
i -= 150;
|
|
store_monst.m_type = (eMonsterType) i;
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
}
|
|
} else if(item_hit == "picktype1") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
i = choose_text_res("monster-abilities",130,139,store_monst.a[0].type + 130,&me,"Choose Attack 1 Type:");
|
|
if (i >= 0) {
|
|
store_monst.a[0].type = i - 130;
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
}
|
|
} else if(item_hit == "picktype2") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
i = choose_text_res("monster-abilities",130,139,store_monst.a[1].type + 130,&me,"Choose Attack 2 & 3 Type:");
|
|
if (i >= 0) {
|
|
store_monst.a[1].type = store_monst.a[2].type = i - 130;
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
}
|
|
} else if(item_hit == "picktype3") {
|
|
if(!save_monst_info(me,store_monst)) return false;
|
|
i = choose_text_res("monster-abilities",130,139,store_monst.a[2].type + 130,&me,"Choose Attack 3 Type:");
|
|
if (i >= 0) {
|
|
store_monst.a[2].type = i - 130;
|
|
put_monst_info_in_dlog(me,which_monst);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
short edit_monst_type(short which_monst) {
|
|
using namespace std::placeholders;
|
|
cMonster store_monst = scenario.scen_monsters[which_monst];
|
|
|
|
cDialog monst_dlg("edit-monster.xml");
|
|
monst_dlg["pickicon"].attachClickHandler(std::bind(pick_picture,PIC_MONST,_1,"pic","icon",0));
|
|
monst_dlg["picktalk"].attachClickHandler(std::bind(pick_picture,PIC_TALK,_1,"talk","",0));
|
|
monst_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, &monst_dlg));
|
|
monst_dlg["pic"].attachFocusHandler(std::bind(check_monst_pic, _1, _2, _3, std::ref(store_monst)));
|
|
monst_dlg["level"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 40, "level"));
|
|
monst_dlg["health"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 2500, "health"));
|
|
monst_dlg["armor"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 50, "armor"));
|
|
monst_dlg["skill"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 40, "skill"));
|
|
monst_dlg["speed"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 2, 12, "speed"));
|
|
monst_dlg["mage"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 7, "magic spells"));
|
|
monst_dlg["priest"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 7, "priest spells"));
|
|
monst_dlg["treas"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 4, "treasure"));
|
|
monst_dlg.attachFocusHandlers(std::bind(check_range_msg,_1,_2,_3,0,20,"attack number of dice","0 means no attack"),{"dice1","dice2","dice3"});
|
|
monst_dlg.attachFocusHandlers(std::bind(check_range,_1,_2,_3,1,50,"attack damage per die"),{"sides1","sides2","sides3"});
|
|
monst_dlg.attachClickHandlers(std::bind(edit_monst_type_event_filter,_1,_2,std::ref(store_monst),which_monst),{"okay","abils","left","right","picktype","picktype1","picktype2"});
|
|
|
|
put_monst_info_in_dlog(monst_dlg, which_monst);
|
|
|
|
monst_dlg.run();
|
|
return 0;
|
|
}
|
|
|
|
static const std::string resist_field_names[8] = {
|
|
"magic-res", "fire-res", "cold-res", "poison-res",
|
|
"magic-imm", "fire-imm", "cold-imm", "poison-imm",
|
|
};
|
|
|
|
void put_monst_abils_in_dlog(cDialog& me, cMonster& store_monst, short which_monst) {
|
|
me["num"].setTextToNum(which_monst);
|
|
|
|
me["poison"].setTextToNum(store_monst.poison);
|
|
me["breath-str"].setTextToNum(store_monst.breath);
|
|
|
|
me["abil-name"].setText(get_str("monster-abilities", store_monst.spec_skill + 1));
|
|
me["radiate-name"].setText(get_str("monster-abilities", store_monst.radiate_1 + 50));
|
|
me["radiate-param"].setText(get_str("monster-abilities", store_monst.radiate_1 + 80));
|
|
me["abil-xtra"].setTextToNum(store_monst.radiate_2);
|
|
me["loot-item"].setTextToNum(store_monst.corpse_item);
|
|
me["loot-chance"].setTextToNum(store_monst.corpse_item_chance);
|
|
|
|
cLedGroup& breathType = dynamic_cast<cLedGroup&>(me["breath-type"]);
|
|
switch(store_monst.breath_type) {
|
|
case 0:
|
|
breathType.setSelected("fire");
|
|
break;
|
|
case 1:
|
|
breathType.setSelected("cold");
|
|
break;
|
|
case 2:
|
|
breathType.setSelected("shock");
|
|
break;
|
|
case 3:
|
|
breathType.setSelected("dark");
|
|
break;
|
|
}
|
|
|
|
dynamic_cast<cLedGroup&>(me["summon"]).setSelected("s" + boost::lexical_cast<std::string,short>(store_monst.summon_type));
|
|
|
|
for(short i = 0; i < 8; i++) {
|
|
cLed& resistLed = dynamic_cast<cLed&>(me[resist_field_names[i]]);
|
|
if(store_monst.immunities & (1 << i))
|
|
resistLed.setState(led_red);
|
|
else resistLed.setState(led_off);
|
|
}
|
|
}
|
|
|
|
bool save_monst_abils(cDialog& me, cMonster& store_monst) {
|
|
store_monst.poison = me["poison"].getTextAsNum();
|
|
store_monst.breath = me["breath-str"].getTextAsNum();
|
|
std::string breathType = dynamic_cast<cLedGroup&>(me["breath-type"]).getSelected();
|
|
if(breathType == "fire")
|
|
store_monst.breath_type = 0;
|
|
else if(breathType == "cold")
|
|
store_monst.breath_type = 1;
|
|
else if(breathType == "shock")
|
|
store_monst.breath_type = 2;
|
|
else if(breathType == "dark")
|
|
store_monst.breath_type = 3;
|
|
store_monst.summon_type = boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["summon"]).getSelected().substr(1));
|
|
store_monst.radiate_2 = me["abil-xtra"].getTextAsNum();
|
|
|
|
store_monst.corpse_item = me["loot-item"].getTextAsNum();
|
|
store_monst.corpse_item_chance = me["loot-chance"].getTextAsNum();
|
|
store_monst.immunities = 0;
|
|
for(short i = 0; i < 8; i++) {
|
|
if(dynamic_cast<cLed&>(me[resist_field_names[i]]).getState() != led_off)
|
|
store_monst.immunities |= 1 << i;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool edit_monst_abil_event_filter(cDialog& me,std::string item_hit,cMonster& store_monst,short which_monst) {
|
|
using namespace std::placeholders;
|
|
short i;
|
|
|
|
if(item_hit == "cancel") {
|
|
store_monst.level = 255;
|
|
me.toast();
|
|
} else if(item_hit == "okay") {
|
|
if(save_monst_abils(me, store_monst))
|
|
me.toast();
|
|
} else if(item_hit == "abils") {
|
|
if(!save_monst_abils(me, store_monst)) return true;
|
|
i = choose_text_res("monster-abilities", 1, 38, store_monst.spec_skill + 1, &me, "Choose Monster Ability:");
|
|
if (i >= 0) {
|
|
store_monst.spec_skill = i - 1;
|
|
put_monst_abils_in_dlog(me, store_monst, which_monst);
|
|
}
|
|
} else if(item_hit == "radiate") {
|
|
if(!save_monst_abils(me, store_monst)) return true;
|
|
i = choose_text_res("monster-abilities", 50, 65, store_monst.radiate_1 + 50, &me, "Choose Radiation Ability:");
|
|
if (i >= 0) {
|
|
store_monst.radiate_1 = i - 50;
|
|
put_monst_abils_in_dlog(me, store_monst, which_monst);
|
|
}
|
|
if(i >= 1 && i <= 6)
|
|
me["abil-xtra"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 100, "Radiation Chance"));
|
|
else if(i >= 10 && i <= 12)
|
|
me["abil-xtra"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 255, "Summoned Monster"));
|
|
else me["abil-xtra"].attachFocusHandler(nullptr);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
cMonster edit_monst_abil(cMonster starting_record,short which_monst) {
|
|
using namespace std::placeholders;
|
|
cMonster store_monst = starting_record;
|
|
|
|
cDialog monst_dlg("edit-monster-abils.xml");
|
|
monst_dlg["poison"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 8, "Poison"));
|
|
monst_dlg["breath-str"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 4, "Breath Damage"));
|
|
monst_dlg["loot-item"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, 399, "Item To Drop", "-1 for no item"));
|
|
monst_dlg["loot-chance"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, 100, "Dropping Chance", "-1 for no item"));
|
|
monst_dlg.attachClickHandlers(std::bind(edit_monst_abil_event_filter, _1, _2, std::ref(store_monst),which_monst), {"okay", "cancel", "abils", "radiate"});
|
|
|
|
put_monst_abils_in_dlog(monst_dlg, store_monst, which_monst);
|
|
|
|
monst_dlg.run();
|
|
return store_monst;
|
|
}
|
|
|
|
void put_item_info_in_dlog(cDialog& me, cItemRec& store_item, short which_item) {
|
|
me["num"].setTextToNum(which_item);
|
|
me["full"].setText(store_item.full_name);
|
|
me["short"].setText(store_item.name);
|
|
if(store_item.graphic_num >= 1000) // was 150
|
|
dynamic_cast<cPict&>(me["pic"]).setPict(store_item.graphic_num, PIC_CUSTOM_ITEM);
|
|
else dynamic_cast<cPict&>(me["pic"]).setPict(store_item.graphic_num, PIC_ITEM);
|
|
me["picnum"].setTextToNum(store_item.graphic_num);
|
|
|
|
cLedGroup& variety = dynamic_cast<cLedGroup&>(me["variety"]);
|
|
switch(store_item.variety) {
|
|
case eItemType::NO_ITEM:
|
|
variety.setSelected("none");
|
|
break;
|
|
case eItemType::ONE_HANDED:
|
|
variety.setSelected("weap1");
|
|
break;
|
|
case eItemType::TWO_HANDED:
|
|
variety.setSelected("weap2");
|
|
break;
|
|
case eItemType::GOLD:
|
|
variety.setSelected("gold");
|
|
break;
|
|
case eItemType::BOW:
|
|
variety.setSelected("bow");
|
|
break;
|
|
case eItemType::ARROW:
|
|
variety.setSelected("arrow");
|
|
break;
|
|
case eItemType::THROWN_MISSILE:
|
|
variety.setSelected("thrown");
|
|
break;
|
|
case eItemType::POTION:
|
|
variety.setSelected("potion");
|
|
break;
|
|
case eItemType::SCROLL:
|
|
variety.setSelected("scroll");
|
|
break;
|
|
case eItemType::WAND:
|
|
variety.setSelected("wand");
|
|
break;
|
|
case eItemType::TOOL:
|
|
variety.setSelected("tool");
|
|
break;
|
|
case eItemType::FOOD:
|
|
variety.setSelected("food");
|
|
break;
|
|
case eItemType::SHIELD:
|
|
variety.setSelected("shield");
|
|
break;
|
|
case eItemType::ARMOR:
|
|
variety.setSelected("armor");
|
|
break;
|
|
case eItemType::HELM:
|
|
variety.setSelected("helm");
|
|
break;
|
|
case eItemType::GLOVES:
|
|
variety.setSelected("gloves");
|
|
break;
|
|
case eItemType::SHIELD_2:
|
|
variety.setSelected("shield2");
|
|
break;
|
|
case eItemType::BOOTS:
|
|
variety.setSelected("boots");
|
|
break;
|
|
case eItemType::RING:
|
|
variety.setSelected("ring");
|
|
break;
|
|
case eItemType::NECKLACE:
|
|
variety.setSelected("necklace");
|
|
break;
|
|
case eItemType::WEAPON_POISON:
|
|
variety.setSelected("poison");
|
|
break;
|
|
case eItemType::NON_USE_OBJECT:
|
|
variety.setSelected("nonuse");
|
|
break;
|
|
case eItemType::PANTS:
|
|
variety.setSelected("pants");
|
|
break;
|
|
case eItemType::CROSSBOW:
|
|
variety.setSelected("xbow");
|
|
break;
|
|
case eItemType::BOLTS:
|
|
variety.setSelected("bolt");
|
|
break;
|
|
case eItemType::MISSILE_NO_AMMO:
|
|
variety.setSelected("missile");
|
|
break;
|
|
case eItemType::UNUSED1:
|
|
variety.setSelected("unused1");
|
|
break;
|
|
case eItemType::UNUSED2:
|
|
variety.setSelected("unused2");
|
|
break;
|
|
}
|
|
|
|
cLedGroup& weapType = dynamic_cast<cLedGroup&>(me["melee-type"]);
|
|
switch(store_item.type) {
|
|
case eWeapType::NOT_MELEE:
|
|
case eWeapType::EDGED:
|
|
weapType.setSelected("edge");
|
|
break;
|
|
case eWeapType::BASHING:
|
|
weapType.setSelected("bash");
|
|
break;
|
|
case eWeapType::POLE:
|
|
weapType.setSelected("pole");
|
|
break;
|
|
}
|
|
|
|
me["level"].setTextToNum(store_item.item_level);
|
|
me["awkward"].setTextToNum(store_item.awkward);
|
|
me["bonus"].setTextToNum(store_item.bonus);
|
|
me["prot"].setTextToNum(store_item.protection);
|
|
me["charges"].setTextToNum(store_item.charges);
|
|
me["flag"].setTextToNum(store_item.type_flag);
|
|
me["value"].setTextToNum(store_item.value);
|
|
me["weight"].setTextToNum(store_item.weight);
|
|
me["class"].setTextToNum(store_item.special_class);
|
|
}
|
|
|
|
bool save_item_info(cDialog& me, cItemRec& store_item, short which_item) {
|
|
store_item.full_name = me["full"].getText();
|
|
store_item.name = me["short"].getText();
|
|
store_item.graphic_num = me["picnum"].getTextAsNum();
|
|
|
|
std::string variety = dynamic_cast<cLedGroup&>(me["variety"]).getSelected();
|
|
if(variety == "none") store_item.variety = eItemType::NO_ITEM;
|
|
else if(variety == "weap1") store_item.variety = eItemType::ONE_HANDED;
|
|
else if(variety == "weap2") store_item.variety = eItemType::TWO_HANDED;
|
|
else if(variety == "gold") store_item.variety = eItemType::GOLD;
|
|
else if(variety == "bow") store_item.variety = eItemType::BOW;
|
|
else if(variety == "arrow") store_item.variety = eItemType::ARROW;
|
|
else if(variety == "thrown") store_item.variety = eItemType::THROWN_MISSILE;
|
|
else if(variety == "potion") store_item.variety = eItemType::POTION;
|
|
else if(variety == "scroll") store_item.variety = eItemType::SCROLL;
|
|
else if(variety == "wand") store_item.variety = eItemType::WAND;
|
|
else if(variety == "tool") store_item.variety = eItemType::TOOL;
|
|
else if(variety == "food") store_item.variety = eItemType::FOOD;
|
|
else if(variety == "shield") store_item.variety = eItemType::SHIELD;
|
|
else if(variety == "armor") store_item.variety = eItemType::ARMOR;
|
|
else if(variety == "helm") store_item.variety = eItemType::HELM;
|
|
else if(variety == "gloves") store_item.variety = eItemType::GLOVES;
|
|
else if(variety == "shield2") store_item.variety = eItemType::SHIELD_2;
|
|
else if(variety == "boots") store_item.variety = eItemType::BOOTS;
|
|
else if(variety == "ring") store_item.variety = eItemType::RING;
|
|
else if(variety == "necklace") store_item.variety = eItemType::NECKLACE;
|
|
else if(variety == "poison") store_item.variety = eItemType::WEAPON_POISON;
|
|
else if(variety == "nonuse") store_item.variety = eItemType::NON_USE_OBJECT;
|
|
else if(variety == "pants") store_item.variety = eItemType::PANTS;
|
|
else if(variety == "xbow") store_item.variety = eItemType::CROSSBOW;
|
|
else if(variety == "bolt") store_item.variety = eItemType::BOLTS;
|
|
else if(variety == "missile") store_item.variety = eItemType::MISSILE_NO_AMMO;
|
|
else if(variety == "unused1") store_item.variety = eItemType::UNUSED1;
|
|
else if(variety == "unused2") store_item.variety = eItemType::UNUSED2;
|
|
store_item.type = eWeapType::NOT_MELEE;
|
|
if(store_item.variety == eItemType::ONE_HANDED || store_item.variety == eItemType::TWO_HANDED) {
|
|
std::string weapType = dynamic_cast<cLedGroup&>(me["melee-type"]).getSelected();
|
|
if(weapType == "edge") store_item.type = eWeapType::EDGED;
|
|
else if(weapType == "bash") store_item.type = eWeapType::BASHING;
|
|
else if(weapType == "pole") store_item.type = eWeapType::POLE;
|
|
}
|
|
|
|
store_item.item_level = me["level"].getTextAsNum();
|
|
if((store_item.variety == eItemType::GOLD || store_item.variety == eItemType::FOOD) && store_item.item_level == 0)
|
|
store_item.item_level = 1;
|
|
|
|
store_item.awkward = me["awkward"].getTextAsNum();
|
|
store_item.bonus = me["bonus"].getTextAsNum();;
|
|
store_item.protection = me["prot"].getTextAsNum();
|
|
store_item.charges = me["charges"].getTextAsNum();
|
|
store_item.type_flag = me["flag"].getTextAsNum();
|
|
store_item.value = me["value"].getTextAsNum();
|
|
store_item.weight = me["weight"].getTextAsNum();
|
|
store_item.special_class = me["class"].getTextAsNum();
|
|
|
|
if ((store_item.type_flag > 0) && (store_item.charges == 0)) {
|
|
giveError("If the Type Flag is greater than 0, the Charges must also be greater than 0.","",&me);
|
|
return false;
|
|
}
|
|
if (store_item.variety == eItemType::UNUSED1 || store_item.variety == eItemType::UNUSED2) {
|
|
giveError("The Unused item varieties are reserved for later expansions, and can't be used now.","",&me);
|
|
return false;
|
|
}
|
|
if ((store_item.ability >= 70) && (store_item.ability < 170) && (store_item.charges == 0)) {
|
|
giveError("An item with the special ability selected must have at least 1 charge.","",&me);
|
|
return false;
|
|
}
|
|
scenario.scen_items[which_item] = store_item;
|
|
return true;
|
|
}
|
|
|
|
bool edit_item_type_event_filter(cDialog& me, std::string item_hit, cItemRec& store_item, short store_which_item) {
|
|
short i;
|
|
cItemRec temp_item;
|
|
|
|
if(item_hit == "cancel") {
|
|
me.toast();
|
|
} else if(item_hit == "okay") {
|
|
if(save_item_info(me, store_item, store_which_item)) me.toast();
|
|
} else if(item_hit == "prev") {
|
|
if(!save_item_info(me, store_item, store_which_item)) return true;
|
|
store_which_item--;
|
|
if (store_which_item < 0) store_which_item = 399;
|
|
store_item = scenario.scen_items[store_which_item];
|
|
put_item_info_in_dlog(me, store_item, store_which_item);
|
|
} else if(item_hit == "next") {
|
|
if(!save_item_info(me, store_item, store_which_item)) return true;
|
|
store_which_item++;
|
|
if (store_which_item > 399) store_which_item = 0;
|
|
store_item = scenario.scen_items[store_which_item];
|
|
put_item_info_in_dlog(me, store_item, store_which_item);
|
|
} else if(item_hit == "choospic") {
|
|
if(!save_item_info(me, store_item, store_which_item)) return true;
|
|
i = pick_picture(PIC_ITEM, me, "picnum", "pic", 0);
|
|
if(i < 0) return true;
|
|
store_item.graphic_num = i;
|
|
} else if(item_hit == "abils") {
|
|
if(store_item.variety == eItemType::NO_ITEM) {
|
|
giveError("You must give the item a type (weapon, armor, etc.) before you can choose its abilities.","",&me);
|
|
return true;
|
|
}
|
|
if(store_item.variety == eItemType::GOLD || store_item.variety == eItemType::FOOD) {
|
|
giveError("Gold and Food cannot be given special abilities.","",&me);
|
|
return true;
|
|
}
|
|
temp_item = edit_item_abil(store_item,store_which_item);
|
|
if(temp_item.variety != eItemType::NO_ITEM)
|
|
store_item = temp_item;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
short edit_item_type(short which_item) {
|
|
using namespace std::placeholders;
|
|
cItemRec store_item = scenario.scen_items[which_item];
|
|
|
|
cDialog item_dlg("edit-item.xml");
|
|
item_dlg["level"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 50, "Item Level"));
|
|
item_dlg["awkward"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 20, "Awkward"));
|
|
item_dlg["bonus"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 60, "Bonus"));
|
|
item_dlg["prot"].attachFocusHandler(std::bind(check_range, _1, _2, _3, -10, 20, "Protection"));
|
|
item_dlg["charges"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 100, "Charges"));
|
|
item_dlg["flag"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 1000, "Type Flag"));
|
|
item_dlg["value"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10000, "Value"));
|
|
item_dlg["weight"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 250, "Weight"));
|
|
item_dlg["class"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 100, "Special Class"));
|
|
item_dlg.attachClickHandlers(std::bind(edit_item_type_event_filter, _1, _2, std::ref(store_item), which_item), {"okay", "cancel", "prev", "next", "abils", "choosepic"});
|
|
|
|
put_item_info_in_dlog(item_dlg, store_item, which_item);
|
|
|
|
item_dlg.run();
|
|
return 0;
|
|
}
|
|
|
|
void put_item_abils_in_dlog(cDialog& me, cItemRec& store_item, short which_item) {
|
|
char str[256];
|
|
|
|
me["num"].setTextToNum(which_item);
|
|
me["name"].setText(store_item.full_name.c_str());
|
|
me["variety"].setText(get_str("item-types", (int)store_item.variety));
|
|
me["abilname"].setText(get_str("item-abilities", store_item.ability + 1));
|
|
|
|
dynamic_cast<cLedGroup&>(me["use-type"]).setSelected("use" + std::to_string(store_item.magic_use_type));
|
|
dynamic_cast<cLedGroup&>(me["treasure"]).setSelected("type" + std::to_string(store_item.treas_class));
|
|
me["str"].setTextToNum(store_item.ability_strength);
|
|
|
|
dynamic_cast<cLed&>(me["always-id"]).setState(store_item.ident ? led_red : led_off);
|
|
dynamic_cast<cLed&>(me["magic"]).setState(store_item.magic ? led_red : led_off);
|
|
dynamic_cast<cLed&>(me["cursed"]).setState(store_item.cursed ? led_red : led_off);
|
|
dynamic_cast<cLed&>(me["conceal"]).setState(store_item.concealed ? led_red : led_off);
|
|
}
|
|
|
|
bool save_item_abils(cDialog& me, cItemRec& store_item) {
|
|
store_item.magic_use_type = boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["use-type"]).getSelected().substr(3));
|
|
store_item.treas_class = boost::lexical_cast<short>(dynamic_cast<cLedGroup&>(me["treasure"]).getSelected().substr(4));
|
|
store_item.ability_strength = me["str"].getTextAsNum();
|
|
|
|
store_item.property = store_item.enchanted = store_item.contained = false;
|
|
store_item.ident = dynamic_cast<cLed&>(me["always-id"]).getState() != led_off;
|
|
store_item.magic = dynamic_cast<cLed&>(me["magic"]).getState() != led_off;
|
|
store_item.cursed = store_item.unsellable = dynamic_cast<cLed&>(me["cursed"]).getState() != led_off;
|
|
store_item.concealed = dynamic_cast<cLed&>(me["conceal"]).getState() != led_off;
|
|
return true;
|
|
}
|
|
|
|
bool edit_item_abil_event_filter(cDialog& me, std::string item_hit, cItemRec& store_item, short which_item) {
|
|
short i;
|
|
|
|
if(item_hit == "cancel") {
|
|
store_item.ability = ITEM_NO_ABILITY;
|
|
me.toast();
|
|
return true;
|
|
} else if(item_hit == "okay") {
|
|
if(save_item_abils(me, store_item)) {
|
|
me.toast();
|
|
return true;
|
|
}
|
|
} else if(item_hit == "weapon") {
|
|
if(!save_item_abils(me, store_item)) return true;
|
|
if(store_item.variety != eItemType::ONE_HANDED && store_item.variety != eItemType::TWO_HANDED) {
|
|
giveError("You can only give an ability of this sort to a melee weapon.","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 1, 15, store_item.ability + 1, &me, "Choose Weapon Ability (inherent)");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "general") {
|
|
if(save_item_abils(me, store_item)) return true;
|
|
if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE)|| (store_item.variety == eItemType::POTION) || (store_item.variety == eItemType::SCROLL) ||
|
|
(store_item.variety == eItemType::WAND) || (store_item.variety == eItemType::TOOL) || (store_item.variety == eItemType::WEAPON_POISON) ||
|
|
(store_item.variety == eItemType::NON_USE_OBJECT) || (store_item.variety == eItemType::BOLTS)){
|
|
giveError("You can only give an ability of this sort to an non-missile item which can be equipped (like armor, or a ring).","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 31, 63, store_item.ability + 1, &me, "Choose General Ability (inherent)");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "usable") {
|
|
if(save_item_abils(me, store_item)) return true;
|
|
if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
|
|
giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 71, 95, store_item.ability + 1, &me, "Choose Usable Ability (Not spell)");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "spell") {
|
|
if(!save_item_abils(me,store_item)) return true;
|
|
if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
|
|
giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 111, 136, store_item.ability + 1, &me, "Choose Usable Ability (Spell)");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "reagent") {
|
|
if(!save_item_abils(me, store_item)) return true;
|
|
// TODO: Some of these should also be applicable to tools, as I recall?
|
|
if(store_item.variety != eItemType::NON_USE_OBJECT){
|
|
giveError("You can only give an ability of this sort to an item of type Non-Use Object.","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 151, 162, store_item.ability + 1, &me, "Choose Reagent Ability");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "missile") {
|
|
if(!save_item_abils(me,store_item)) return true;
|
|
if((store_item.variety == eItemType::ARROW) || (store_item.variety == eItemType::THROWN_MISSILE) || (store_item.variety == eItemType::BOLTS)){
|
|
giveError("You can only give an ability of this sort to an item which isn't a missile.","",&me);
|
|
return true;
|
|
}
|
|
i = choose_text_res("item-abilities", 171, 177, store_item.ability + 1, &me, "Choose Missile Ability");
|
|
if(i >= 0) store_item.ability = (eItemAbil) (i - 1);
|
|
else store_item.ability = ITEM_NO_ABILITY;
|
|
put_item_abils_in_dlog(me, store_item, which_item);
|
|
}
|
|
using namespace std::placeholders;
|
|
if(store_item.ability != 119 && store_item.ability != 120) {
|
|
me["str"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10, "Ability Strength"));
|
|
} else {
|
|
me["str"].attachFocusHandler(std::bind(check_range_msg, _1,_2,_3, 0,255, "Ability Strength","the number of the monster to summon"));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
cItemRec edit_item_abil(cItemRec starting_record,short which_item) {
|
|
using namespace std::placeholders;
|
|
|
|
cItemRec store_item = starting_record;
|
|
|
|
cDialog item_dlg("edit-item-abils.xml");
|
|
if(store_item.ability != 119 && store_item.ability != 120) {
|
|
item_dlg["str"].attachFocusHandler(std::bind(check_range, _1, _2, _3, 0, 10, "Ability Strength"));
|
|
} else {
|
|
item_dlg["str"].attachFocusHandler(std::bind(check_range_msg,_1,_2,_3, 0,255, "Ability Strength","the number of the monster to summon"));
|
|
}
|
|
item_dlg.attachClickHandlers(std::bind(edit_item_abil_event_filter, _1, _2, std::ref(store_item), which_item), {"okay", "cancel", "weapon", "general", "usable", "missile", "reagent", "spell"});
|
|
|
|
put_item_abils_in_dlog(item_dlg, store_item, which_item);
|
|
|
|
item_dlg.run();
|
|
|
|
return store_item;
|
|
}
|
|
|
|
void put_spec_item_in_dlog(cDialog& me, cSpecItem& store_item, short which_item) {
|
|
me["num"].setTextToNum(which_item);
|
|
me["name"].setText(store_item.name);
|
|
me["descr"].setText(store_item.descr);
|
|
me["spec"].setTextToNum(store_item.special);
|
|
dynamic_cast<cLed&>(me["start-with"]).setState(store_item.flags >= 10 ? led_red : led_off);
|
|
dynamic_cast<cLed&>(me["usable"]).setState(store_item.flags % 10 > 0 ? led_red : led_off);
|
|
}
|
|
|
|
bool save_spec_item(cDialog& me, cSpecItem& store_item, short which_item) {
|
|
strncpy(store_item.name, me["name"].getText().c_str(),25);
|
|
store_item.name[25] = 0;
|
|
strncpy(store_item.descr, me["descr"].getText().c_str(),255);
|
|
store_item.descr[255] = 0;
|
|
store_item.special = me["spec"].getTextAsNum();
|
|
store_item.flags = 0;
|
|
if(dynamic_cast<cLed&>(me["start-with"]).getState() != led_off)
|
|
store_item.flags += 10;
|
|
if(dynamic_cast<cLed&>(me["usable"]).getState() != led_off)
|
|
store_item.flags += 1;
|
|
scenario.special_items[which_item] = store_item;
|
|
return true;
|
|
}
|
|
|
|
bool edit_spec_item_event_filter(cDialog& me, std::string item_hit, cSpecItem& store_item, short which_item) {
|
|
if(item_hit == "cancel") {
|
|
me.toast();
|
|
} else if(item_hit == "okay") {
|
|
if(save_spec_item(me, store_item, which_item)) me.toast();
|
|
} else if(item_hit == "left") {
|
|
if(!save_spec_item(me, store_item, which_item)) return true;
|
|
which_item--;
|
|
if(which_item < 0) which_item = 49;
|
|
store_item = scenario.special_items[which_item];
|
|
put_spec_item_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "right") {
|
|
if(!save_spec_item(me, store_item, which_item)) return true;
|
|
which_item++;
|
|
if(which_item > 49) which_item = 0;
|
|
store_item = scenario.special_items[which_item];
|
|
put_spec_item_in_dlog(me, store_item, which_item);
|
|
} else if(item_hit == "edit-spec") {
|
|
if(!save_spec_item(me, store_item, which_item)) return true;
|
|
short spec = me["spec"].getTextAsNum();
|
|
if((spec < 0) || (spec >= 256)) {
|
|
spec = get_fresh_spec(0);
|
|
if(spec < 0) {
|
|
giveError("You can't create a new special encounter because there are no more free scenario special nodes.",
|
|
"To free a special node, set its type to No Special and set its Jump To special to -1.",&me);
|
|
return true;
|
|
}
|
|
me["spec"].setTextToNum(spec);
|
|
}
|
|
edit_spec_enc(spec,0,&me);
|
|
if(spec >= 0 && spec < 256 && scenario.scen_specials[spec].pic < 0)
|
|
me["spec"].setTextToNum(-1);
|
|
save_spec_item(me, store_item, which_item);
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void edit_spec_item(short which_item) {
|
|
using namespace std::placeholders;
|
|
cSpecItem store_item = scenario.special_items[which_item];
|
|
|
|
cDialog item_dlg("edit-special-item.xml");
|
|
item_dlg["spec"].attachFocusHandler(std::bind(check_range_msg, _1, _2, _3, -1, 255, "Scenario special node called", "-1 for no special"));
|
|
item_dlg.attachClickHandlers(std::bind(edit_spec_item_event_filter, _1, _2, std::ref(store_item), which_item), {"okay", "cancel", "clear", "edit-spec", "left", "right"});
|
|
|
|
put_spec_item_in_dlog(item_dlg, store_item, which_item);
|
|
item_dlg["clear"].hide();
|
|
|
|
item_dlg.run();
|
|
}
|
|
|
|
void put_save_rects_in_dlog(cDialog& me) {
|
|
short i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
me["top" + id].setTextToNum(scenario.store_item_rects[i].top);
|
|
me["left" + id].setTextToNum(scenario.store_item_rects[i].left);
|
|
me["bottom" + id].setTextToNum(scenario.store_item_rects[i].bottom);
|
|
me["right" + id].setTextToNum(scenario.store_item_rects[i].right);
|
|
me["town" + id].setTextToNum(scenario.store_item_towns[i]);
|
|
|
|
}
|
|
}
|
|
|
|
bool save_save_rects(cDialog& me) {
|
|
short i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
scenario.store_item_rects[i].top = me["top" + id].getTextAsNum();
|
|
scenario.store_item_rects[i].left = me["left" + id].getTextAsNum();
|
|
scenario.store_item_rects[i].bottom = me["bottom" + id].getTextAsNum();
|
|
scenario.store_item_rects[i].right = me["right" + id].getTextAsNum();
|
|
scenario.store_item_towns[i] = me["town" + id].getTextAsNum();
|
|
if ((scenario.store_item_towns[i] < -1) || (scenario.store_item_towns[i] >= 200)) {
|
|
giveError("Towns must be in 0 to 200 range (or -1 for no save items rectangle).","",&me);
|
|
return false;
|
|
}
|
|
}
|
|
if (((scenario.store_item_towns[0] == scenario.store_item_towns[1]) &&
|
|
(scenario.store_item_towns[0] >= 0) && (scenario.store_item_towns[1] >= 0))
|
|
||
|
|
((scenario.store_item_towns[2] == scenario.store_item_towns[1]) &&
|
|
(scenario.store_item_towns[2] >= 0) && (scenario.store_item_towns[1] >= 0))
|
|
||
|
|
((scenario.store_item_towns[2] == scenario.store_item_towns[0]) &&
|
|
(scenario.store_item_towns[2] >= 0) && (scenario.store_item_towns[0] >= 0))
|
|
) {
|
|
giveError("The three towns towns with saved item rectangles must be different.","",&me);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool edit_save_rects_event_filter(cDialog& me, std::string item_hit) {
|
|
if(item_hit == "cancel") {
|
|
me.toast();
|
|
} else if(item_hit == "okay") {
|
|
if(save_save_rects(me))
|
|
me.toast();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void edit_save_rects() {
|
|
using namespace std::placeholders;
|
|
|
|
cDialog save_dlg("edit-save-rects.xml");
|
|
save_dlg.attachClickHandlers(std::bind(edit_save_rects_event_filter, _1, _2), {"okay"});
|
|
|
|
put_save_rects_in_dlog(save_dlg);
|
|
|
|
save_dlg.run();
|
|
}
|
|
|
|
bool save_vehicles(cDialog& me, cVehicle* vehicles, const short page) {
|
|
short i;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
vehicles[6 * page + i].which_town = me["town" + id].getTextAsNum();
|
|
if(cre(vehicles[6 * page + i].which_town,
|
|
-1,199,"Town number must be from 0 to 199 (or -1 for it to not exist).","",&me)) return false;
|
|
vehicles[6 * page + i].loc.x = me["x" + id].getTextAsNum();
|
|
if(cre(vehicles[6 * page + i].loc.x,
|
|
0,63,"coordinates must be from 0 to 63.","",&me)) return false;
|
|
vehicles[6 * page + i].loc.y = me["y" + id].getTextAsNum();
|
|
if(cre(vehicles[6 * page + i].loc.y,
|
|
0,63,"coordinates must be from 0 to 63.","",&me)) return false;
|
|
vehicles[6 * page + i].property = dynamic_cast<cLed&>(me["owned" + id]).getState() != led_off;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void put_vehicles_in_dlog(cDialog& me, cVehicle* vehicles, const short page) {
|
|
short i;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
me["num" + id].setTextToNum(6 * page + i);
|
|
me["town" + id].setTextToNum(vehicles[6 * page + i].which_town);
|
|
me["x" + id].setTextToNum(vehicles[6 * page + i].loc.x);
|
|
me["y" + id].setTextToNum(vehicles[6 * page + i].loc.y);
|
|
dynamic_cast<cLed&>(me["owned" + id]).setState(vehicles[6 * page + i].property ? led_red : led_off);
|
|
}
|
|
}
|
|
|
|
bool edit_vehicles_event_filter(cDialog& me, std::string item_hit, cVehicle* vehicles, size_t nVehicles, short& page) {
|
|
short i;
|
|
|
|
if(item_hit == "okay") {
|
|
if(save_vehicles(me, vehicles, page))
|
|
me.toast();
|
|
} else if(item_hit == "left") {
|
|
if(!save_vehicles(me, vehicles, page)) return true;
|
|
page--;
|
|
if(page < 0) page = (nVehicles - 1) / 6;
|
|
put_vehicles_in_dlog(me, vehicles, page);
|
|
} else if(item_hit == "right") {
|
|
if(!save_vehicles(me, vehicles, page)) return true;
|
|
page++;
|
|
if(page > (nVehicles - 1) / 6) page = 0;
|
|
put_vehicles_in_dlog(me, vehicles, page);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void edit_horses() {
|
|
using namespace std::placeholders;
|
|
short page = 0;
|
|
|
|
cDialog horse_dlg("edit-horses.xml");
|
|
horse_dlg.attachClickHandlers(std::bind(edit_vehicles_event_filter, _1, _2, scenario.horses, 30, std::ref(page)), {"okay", "left", "right"});
|
|
|
|
put_vehicles_in_dlog(horse_dlg, scenario.horses, page);
|
|
|
|
horse_dlg.run();
|
|
}
|
|
|
|
void edit_boats() {
|
|
using namespace std::placeholders;
|
|
short page = 0;
|
|
|
|
cDialog boat_dlg("edit-boats.xml");
|
|
boat_dlg.attachClickHandlers(std::bind(edit_vehicles_event_filter, _1, _2, scenario.boats, 30, std::ref(page)), {"okay", "left", "right"});
|
|
|
|
put_vehicles_in_dlog(boat_dlg, scenario.boats, page);
|
|
|
|
boat_dlg.run();
|
|
}
|
|
|
|
bool save_add_town(cDialog& me) {
|
|
short i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
scenario.town_to_add_to[i] = me["town" + id].getTextAsNum();
|
|
if (cre(scenario.town_to_add_to[i],
|
|
-1,199,"Town number must be from 0 to 199 (or -1 for no effect).","",&me)) return false;
|
|
scenario.flag_to_add_to_town[i][0] = me["flag" + id + "-x"].getTextAsNum();
|
|
if (cre(scenario.flag_to_add_to_town[i][0],
|
|
0,299,"First part of flag must be from 0 to 299.","",&me)) return false;
|
|
scenario.flag_to_add_to_town[i][1] = me["flag" + id + "-y"].getTextAsNum();
|
|
if (cre(scenario.flag_to_add_to_town[i][1],
|
|
0,9,"Second part of flag must be from 0 to 9.","",&me)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void put_add_town_in_dlog(cDialog& me) {
|
|
short i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
me["town" + id].setTextToNum(scenario.town_to_add_to[i]);
|
|
me["flag" + id + "-x"].setTextToNum(scenario.flag_to_add_to_town[i][0]);
|
|
me["flag" + id + "-y"].setTextToNum(scenario.flag_to_add_to_town[i][1]);
|
|
}
|
|
}
|
|
|
|
bool edit_add_town_event_filter(cDialog& me, std::string item_hit) {
|
|
if(item_hit == "okay") {
|
|
if(save_add_town(me))
|
|
me.toast();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void edit_add_town() {
|
|
using namespace std::placeholders;
|
|
|
|
cDialog vary_dlg("edit-town-varying.xml");
|
|
vary_dlg.attachClickHandlers(std::bind(edit_add_town_event_filter, _1, _2), {"okay"});
|
|
|
|
put_add_town_in_dlog(vary_dlg);
|
|
|
|
vary_dlg.run();
|
|
}
|
|
|
|
bool save_item_placement(cDialog& me, cScenario::cItemStorage& store_storage, short cur_shortcut) {
|
|
short i;
|
|
|
|
store_storage.property = dynamic_cast<cLed&>(me["owned"]).getState() != led_off;
|
|
store_storage.ter_type = me["ter"].getTextAsNum();
|
|
if (cre(store_storage.ter_type,
|
|
-1,255,"Terrain Type must be from 0 to 255 (or -1 for No Shortcut).","",&me)) return false;
|
|
for (i = 0; i < 10; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
store_storage.item_num[i] = me["item" + id].getTextAsNum();
|
|
if(cre(store_storage.item_num[i],
|
|
-1,399,"All item numbers must be from 0 to 399 (or -1 for No Item).","",&me) == true) return false;
|
|
store_storage.item_odds[i] = me["odds" + id].getTextAsNum();
|
|
if(cre(store_storage.item_odds[i],
|
|
0,100,"All item chances must bve from 0 to 100.","",&me) == true) return false;
|
|
}
|
|
scenario.storage_shortcuts[cur_shortcut] = store_storage;
|
|
return true;
|
|
}
|
|
|
|
void put_item_placement_in_dlog(cDialog& me, const cScenario::cItemStorage& store_storage, short cur_shortcut) {
|
|
short i;
|
|
|
|
me["num"].setTextToNum(cur_shortcut);
|
|
dynamic_cast<cLed&>(me["owned"]).setState(store_storage.property ? led_red : led_off);
|
|
me["ter"].setTextToNum(store_storage.ter_type);
|
|
for (i = 0; i < 10; i++) {
|
|
std::string id = std::to_string(i + 1);
|
|
me["item" + id].setTextToNum(store_storage.item_num[i]);
|
|
me["odds" + id].setTextToNum(store_storage.item_odds[i]);
|
|
}
|
|
}
|
|
|
|
bool edit_item_placement_event_filter(cDialog& me, std::string item_hit, cScenario::cItemStorage& store_storage, short& cur_shortcut) {
|
|
short i;
|
|
|
|
if(item_hit == "okay") {
|
|
if(save_item_placement(me, store_storage, cur_shortcut))
|
|
me.toast();
|
|
} else if(item_hit == "cancel") {
|
|
me.toast();
|
|
} else if(item_hit == "left") {
|
|
if(!save_item_placement(me, store_storage, cur_shortcut)) return true;
|
|
cur_shortcut--;
|
|
if (cur_shortcut < 0) cur_shortcut = 9;
|
|
store_storage = scenario.storage_shortcuts[cur_shortcut];
|
|
put_item_placement_in_dlog(me, store_storage, cur_shortcut);
|
|
} else if(item_hit == "right") {
|
|
if(!save_item_placement(me, store_storage, cur_shortcut)) return true;
|
|
cur_shortcut++;
|
|
if (cur_shortcut > 9) cur_shortcut = 0;
|
|
store_storage = scenario.storage_shortcuts[cur_shortcut];
|
|
put_item_placement_in_dlog(me, store_storage, cur_shortcut);
|
|
} else if(item_hit == "choose-ter") {
|
|
i = me["ter"].getTextAsNum();
|
|
store_storage.ter_type = i;
|
|
i = choose_text(STRT_TER,i,&me,"Which Terrain?");
|
|
if(i >= 0){
|
|
me["ter"].setTextToNum(i);
|
|
store_storage.ter_type = i;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool edit_item_placement_select_item(cDialog& me, cScenario::cItemStorage& store_storage, short item_hit) {
|
|
std::string id = "item" + std::to_string(item_hit);
|
|
short i = me[id].getTextAsNum();
|
|
store_storage.item_num[item_hit - 1] = i;
|
|
i = choose_text(STRT_ITEM,i,&me,"Place which item?");
|
|
if(i >= 0) {
|
|
me[id].setTextToNum(i);
|
|
store_storage.item_num[item_hit - 1] = i;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void edit_item_placement() {
|
|
using namespace std::placeholders;
|
|
cScenario::cItemStorage store_storage = scenario.storage_shortcuts[0];
|
|
short cur_shortcut = 0;
|
|
|
|
cDialog shortcut_dlg("edit-item-shortcut.xml");
|
|
shortcut_dlg.attachClickHandlers(std::bind(edit_item_placement_event_filter, _1, _2, std::ref(store_storage), std::ref(cur_shortcut)), {"okay", "cancel", "left", "right", "choose-ter"});
|
|
for(int i = 0; i < 10; i++) {
|
|
std::string id = "choose-item" + std::to_string(i + 1);
|
|
shortcut_dlg[id].attachClickHandler(std::bind(edit_item_placement_select_item, _1, std::ref(store_storage), i + 1));
|
|
}
|
|
|
|
put_item_placement_in_dlog(shortcut_dlg, store_storage, cur_shortcut);
|
|
|
|
shortcut_dlg.run();
|
|
}
|
|
|
|
bool save_scen_details() {
|
|
#if 0
|
|
char str[256];
|
|
short i;
|
|
|
|
scenario.difficulty = cd_get_led_range(803,30,33);
|
|
scenario.rating = cd_get_led_range(803,21,24);
|
|
scenario.format.ver[0] = CDGN(803,2);
|
|
scenario.format.ver[1] = CDGN(803,3);
|
|
scenario.format.ver[2] = CDGN(803,4);
|
|
for (i = 0; i < 3; i++)
|
|
if (cre(scenario.format.ver[i],
|
|
0,9,"The digits in the version number must be in the 0 to 9 range.","",803) == true) return false;
|
|
CDGT(803,5,(char *) str);
|
|
str[59] = 0;
|
|
strcpy(scenario.scen_strs(1),(char *) str);
|
|
CDGT(803,6,(char *) str);
|
|
str[59] = 0;
|
|
strcpy(scenario.scen_strs(2),(char *) str);
|
|
CDGT(803,7,scenario.scen_strs(3));
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
void put_scen_details_in_dlog() {
|
|
#if 0
|
|
cd_set_led_range(803,30,33,scenario.difficulty);
|
|
cd_set_led_range(803,21,24,scenario.rating);
|
|
CDSN(803,2,scenario.format.ver[0]);
|
|
CDSN(803,3,scenario.format.ver[1]);
|
|
CDSN(803,4,scenario.format.ver[2]);
|
|
CDST(803,5,scenario.scen_strs(1));
|
|
CDST(803,6,scenario.scen_strs(2));
|
|
CDST(803,7,scenario.scen_strs(3));
|
|
#endif
|
|
}
|
|
|
|
void edit_scen_details_event_filter (short item_hit) {
|
|
#if 0
|
|
switch (item_hit) {
|
|
case 8:
|
|
if (save_scen_details() == true)
|
|
toast_dialog();
|
|
break;
|
|
default:
|
|
cd_hit_led_range(803,21,24,item_hit);
|
|
cd_hit_led_range(803,30,33,item_hit);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void edit_scen_details() {
|
|
#if 0
|
|
// ignore parent in Mac version
|
|
short scen_details_hit;
|
|
|
|
cd_create_dialog_parent_num(803,0);
|
|
|
|
put_scen_details_in_dlog();
|
|
|
|
scen_details_hit = cd_run_dialog();
|
|
cd_kill_dialog(803);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void put_make_scen_1_in_dlog() {
|
|
#if 0
|
|
CDST(800,2,"Scenario name");
|
|
CDST(800,3,"filename");
|
|
#endif
|
|
}
|
|
|
|
void edit_make_scen_1_event_filter (short item_hit) {
|
|
#if 0
|
|
char str[256];
|
|
short i,j;
|
|
|
|
switch (item_hit) {
|
|
case 4:
|
|
CDGT(800,3,(char *) str);
|
|
j = strlen((char *) str);
|
|
if (j == 0) {
|
|
give_error("You've left the file name empty.","",800);
|
|
break;
|
|
}
|
|
if (j > 50) {
|
|
give_error("The file name can be at most 50 characters long.","",800);
|
|
break;
|
|
}
|
|
for (i = 0; i < j; i++)
|
|
if ((str[i] < 97) || (str[i] > 122)) {
|
|
give_error("The file name must consist of only lower case letters.","",800);
|
|
return;
|
|
}
|
|
dialog_answer = 1;
|
|
toast_dialog();
|
|
break;
|
|
case 9:
|
|
dialog_answer = 0;
|
|
toast_dialog();
|
|
break;
|
|
default:
|
|
cd_flip_led(800,11,item_hit);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
short edit_make_scen_1(char *filename,char *title,short *grass) {
|
|
#if 0
|
|
// ignore parent in Mac version
|
|
short make_scen_1_hit;
|
|
|
|
cd_create_dialog_parent_num(800,0);
|
|
|
|
put_make_scen_1_in_dlog();
|
|
|
|
make_scen_1_hit = cd_run_dialog();
|
|
CDGT(800,2,title);
|
|
title[30] = 0;
|
|
CDGT(800,3,filename);
|
|
*grass = cd_get_led(800,11);
|
|
cd_kill_dialog(800);
|
|
#endif
|
|
return 0;//dialog_answer;
|
|
}
|
|
|
|
void put_make_scen_2_in_dlog() {
|
|
#if 0
|
|
CDSN(801,2,1);
|
|
CDSN(801,3,1);
|
|
CDSN(801,4,0);
|
|
CDSN(801,5,1);
|
|
CDSN(801,6,0);
|
|
#endif
|
|
}
|
|
|
|
void edit_make_scen_2_event_filter (short item_hit) {
|
|
#if 0
|
|
short i,j,k;
|
|
|
|
switch (item_hit) {
|
|
case 11:
|
|
i = CDGN(801,2);
|
|
if (cre(i,
|
|
1,50,"Outdoors width must be between 1 and 50.","",801) == true) return ;
|
|
j = CDGN(801,3);
|
|
if (cre(j,
|
|
1,50,"Outdoors height must be between 1 and 50.","",801) == true) return ;
|
|
if (cre(i * j,
|
|
1,100,"The total number of outdoor sections (width times height) must be between 1 and 100.","",801) == true) return ;
|
|
i = CDGN(801,4);
|
|
j = CDGN(801,5);
|
|
k = CDGN(801,6);
|
|
if (cre(i,
|
|
0,200,"Number of small towns must be between 0 and 200.","",801) == true) return ;
|
|
if (cre(j,
|
|
1,200,"Number of medium towns must be between 0 and 200. The first town (Town 0) must always be of medium size.","",801) == true) return ;
|
|
if (cre(k,
|
|
0,200,"Number of large towns must be between 0 and 200.","",801) == true) return ;
|
|
if (cre(i + j + k,
|
|
1,200,"The total number of towns must be from 1 to 200 (you must have at least 1 town).","",801) == true) return ;
|
|
|
|
toast_dialog();
|
|
break;
|
|
case 10:
|
|
dialog_answer = 0;
|
|
toast_dialog();
|
|
break;
|
|
default:
|
|
cd_flip_led(801,26,item_hit);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
short edit_make_scen_2(short *val_array) {
|
|
#if 0
|
|
// ignore parent in Mac version
|
|
short make_scen_2_hit,i;//array[6];
|
|
|
|
//array = val_array;
|
|
cd_create_dialog_parent_num(801,0);
|
|
|
|
put_make_scen_2_in_dlog();
|
|
|
|
make_scen_2_hit = cd_run_dialog();
|
|
|
|
for (i = 0; i < 5; i++)
|
|
val_array[i] = CDGN(801,2 + i);
|
|
val_array[5] = cd_get_led(801,26);
|
|
cd_kill_dialog(801);
|
|
#endif
|
|
return 0;//dialog_answer;
|
|
}
|
|
|
|
bool build_scenario() {
|
|
printf("Building a scenario currently disabled.\n");
|
|
// short two_flags[6]; // width, height, large, med, small, default_town
|
|
// Str255 f_name[256],f_name2[256],title[256];
|
|
// short grass,password,which_town,error;
|
|
// FSSpec temp_file_to_load;
|
|
// short i,j;
|
|
// long dummy;
|
|
//
|
|
// if (edit_make_scen_1((char *) f_name,(char *) title,&grass) == false)
|
|
// return false;
|
|
// sprintf((char *) f_name2,"%s.exs",f_name);
|
|
// if (edit_make_scen_2((short *) two_flags) == false)
|
|
// return false;
|
|
// user_given_password = given_password = get_password();
|
|
// if (fancy_choice_dialog(860,0) == 2)
|
|
// return false;
|
|
// town = new cMedTown;
|
|
// //cMedTown* t_d = (cMedTown*) town;
|
|
// init_out();
|
|
// init_scenario();
|
|
// strcpy((char *) scenario.scen_strs(0),(char *) title);
|
|
// if (two_flags[5] == 0) {
|
|
// init_town(1);
|
|
// if (grass == 0)
|
|
// for (i = 0; i < 48; i++)
|
|
// for (j = 0; j < 48; j++)
|
|
// town->terrain(i,j) = 0;
|
|
// }
|
|
// else {
|
|
// error = FSMakeFSSpec(start_volume,start_dir,"::::Blades of Exile Base",&temp_file_to_load);
|
|
// if (error != 0) {oops_error(40);}
|
|
// import_town(0,temp_file_to_load);
|
|
// }
|
|
// if (two_flags[3] > 0)
|
|
// two_flags[3]--;
|
|
//
|
|
// make_new_scenario(f_name2,two_flags[0],two_flags[1],two_flags[5],grass);
|
|
//
|
|
// // now make sure correct outdoors is in memory, because we're going to be saving scenarios
|
|
// // for a while
|
|
// overall_mode = 60;
|
|
// cur_out.x = 0;
|
|
// cur_out.y = 0;
|
|
// load_outdoors(cur_out,0);
|
|
//
|
|
// for (i = 0; i < two_flags[2]; i++) {
|
|
// which_town = scenario.num_towns;
|
|
// scenario.num_towns++;
|
|
// scenario.town_size[which_town] = 0;
|
|
// scenario.town_hidden[which_town] = 0;
|
|
// cur_town = which_town;
|
|
// init_town(0);
|
|
// strcpy(data_store->town_strs[0],"Large town");
|
|
// town_type = 0;
|
|
// reset_pwd();
|
|
// save_scenario();
|
|
// }
|
|
// for (i = 0; i < two_flags[3]; i++) {
|
|
// which_town = scenario.num_towns;
|
|
// scenario.num_towns++;
|
|
// scenario.town_size[which_town] = 1;
|
|
// scenario.town_hidden[which_town] = 0;
|
|
// cur_town = which_town;
|
|
// init_town(1);
|
|
// strcpy(data_store->town_strs[0],"Medium town");
|
|
// town_type = 1;
|
|
// reset_pwd();
|
|
// save_scenario();
|
|
// }
|
|
// for (i = 0; i < two_flags[4]; i++) {
|
|
// which_town = scenario.num_towns;
|
|
// scenario.num_towns++;
|
|
// scenario.town_size[which_town] = 2;
|
|
// scenario.town_hidden[which_town] = 0;
|
|
// cur_town = which_town;
|
|
// init_town(2);
|
|
// strcpy(data_store->town_strs[0],"Small town");
|
|
// town_type = 2;
|
|
// reset_pwd();
|
|
// save_scenario();
|
|
// }
|
|
// //Delay(200,&dummy);
|
|
// if(load_town(0)) cur_town = 0;
|
|
// cur_town = 0;
|
|
// augment_terrain(cur_out);
|
|
// update_item_menu();
|
|
return false;
|
|
}
|
|
|
|
void set_starting_loc_filter (short item_hit) {
|
|
#if 0
|
|
char str[256];
|
|
short i,j,k;
|
|
|
|
switch (item_hit) {
|
|
case 5:
|
|
i = CDGN(805,2);
|
|
j = CDGN(805,3);
|
|
k = CDGN(805,4);
|
|
if ((i < 0) || (i >= scenario.num_towns)) {
|
|
sprintf((char *) str,"The starting town must be from 0 to %d.",scenario.num_towns - 1);
|
|
give_error((char *) str,"",805);
|
|
break;
|
|
}
|
|
if ((j < 0) || (j >= max_dim[scenario.town_size[i]] - 1) ||
|
|
(k < 0) || (k >= max_dim[scenario.town_size[i]] - 1)) {
|
|
give_error("This coordinate is not inside the bounds of the town.","",805);
|
|
break;
|
|
}
|
|
scenario.which_town_start = i;
|
|
scenario.where_start.x = j;
|
|
scenario.where_start.y = k;
|
|
toast_dialog();
|
|
break;
|
|
case 12:
|
|
toast_dialog();
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void set_starting_loc() {
|
|
#if 0
|
|
// ignore parent in Mac version
|
|
short town_strs_hit;
|
|
|
|
cd_create_dialog_parent_num(805,0);
|
|
|
|
CDSN(805,2,scenario.which_town_start);
|
|
CDSN(805,3,scenario.where_start.x);
|
|
CDSN(805,4,scenario.where_start.y);
|
|
|
|
town_strs_hit = cd_run_dialog();
|
|
|
|
|
|
cd_kill_dialog(805);
|
|
#endif
|
|
}
|
|
|
|
bool save_scenario_events() {
|
|
#if 0
|
|
short i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
scenario.scenario_timer_times[i] = CDGN(811,2 + i);
|
|
if ((scenario.scenario_timer_times[i] > 0) &&
|
|
(scenario.scenario_timer_times[i] % 10 != 0)) {
|
|
give_error("All scenario event times must be multiples of 10 (e.g. 100, 150, 1000, etc.).","",811);
|
|
return false;
|
|
}
|
|
scenario.scenario_timer_specs[i] = CDGN(811,12 + i);
|
|
if (cre(scenario.scenario_timer_specs[i],-1,255,"The scenario special nodes must be between 0 at 255 (or -1 for no special)."
|
|
,"",811) == true) return false;
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
void put_scenario_events_in_dlog() {
|
|
#if 0
|
|
short i;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
CDSN(811,2 + i,scenario.scenario_timer_times[i]);
|
|
CDSN(811,12 + i,scenario.scenario_timer_specs[i]);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void edit_scenario_events_event_filter (short item_hit) {
|
|
#if 0
|
|
short spec;
|
|
|
|
switch (item_hit) {
|
|
case 22:
|
|
if (save_scenario_events() == true)
|
|
toast_dialog();
|
|
break;
|
|
default:
|
|
if ((item_hit >= 30) && (item_hit <= 39)) {
|
|
if (save_scenario_events() == false)
|
|
break;
|
|
spec = CDGN(811,item_hit - 30 + 12);
|
|
if ((spec < 0) || (spec > 255)) {
|
|
spec = get_fresh_spec(0);
|
|
if (spec < 0) {
|
|
give_error("You can't create a new scenario special encounter because there are no more free special nodes.",
|
|
"To free a special node, set its type to No Special and set its Jump To special to -1.",811);
|
|
break;
|
|
}
|
|
CDSN(811,item_hit - 30 + 12,spec);
|
|
}
|
|
edit_spec_enc(spec,0,811);
|
|
if ((spec >= 0) && (spec < 256) && (scenario.scen_specials[spec].pic < 0))
|
|
CDSN(811,item_hit - 30 + 12,-1);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void edit_scenario_events() {
|
|
#if 0
|
|
// ignore parent in Mac version
|
|
short advanced_town_hit;
|
|
|
|
|
|
cd_create_dialog_parent_num(811,0);
|
|
|
|
put_scenario_events_in_dlog();
|
|
|
|
advanced_town_hit = cd_run_dialog();
|
|
|
|
cd_kill_dialog(811);
|
|
#endif
|
|
}
|