Refactor special node properties struct to isolate the magic characters.

Basically what that means is that the magic characters are only parsed at startup – the scenario editor code doesn't need to understand them, instead using an enum.

This is part of the work for #607
This commit is contained in:
2025-02-16 13:16:42 -05:00
committed by Celtic Minstrel
parent 0465923992
commit 89dbe98b2b
4 changed files with 295 additions and 188 deletions

View File

@@ -697,8 +697,15 @@ static eSpecCat getNodeCategory(eSpecType node) {
return eSpecCat::INVALID;
}
static std::map<eSpecType, node_properties_t> loadProps() {
std::map<eSpecType, node_properties_t> allNodeProps;
static std::map<eSpecType, node_properties_t>& nodeProps() {
static std::map<eSpecType, node_properties_t> props;
return props;
}
void node_properties_t::load() {
std::map<eSpecType, node_properties_t>& allNodeProps = nodeProps();
// These are the node types that should not have a Create/Edit button on the JumpTo
static std::set<eSpecType> dead_ends = {eSpecType::ENTER_SHOP, eSpecType::START_TALK, eSpecType::TOWN_GENERIC_STAIR, eSpecType::TOWN_STAIR};
// There's really no need to check all the way to the max of the underlying type.
// It's unlikely we'd go above 255, so unsigned char would be fine, but just in case,
// let's use unsigned short.
@@ -712,35 +719,47 @@ static std::map<eSpecType, node_properties_t> loadProps() {
props.self = check;
props.cat = category;
int j = int(category), k = i - offsets[j];
props.m1_btn = button_dict[j][0][k];
props.m2_btn = button_dict[j][1][k];
props.m3_btn = button_dict[j][2][k];
props.p_btn = button_dict[j][3][k];
props.pt_btn = button_dict[j][4][k];
props.f_m1 = button_dict[j][0][k];
props.f_m2 = button_dict[j][1][k];
props.f_m3 = button_dict[j][2][k];
props.f_pic = button_dict[j][3][k];
props.f_pt = button_dict[j][4][k];
if(category != eSpecCat::RECT) {
props.sd1_btn = ' ';
props.x1a_btn = button_dict[j][5][k];
props.x1b_btn = button_dict[j][6][k];
} else props.sd1_btn = button_dict[j][5][k];
props.x1c_btn = button_dict[j][7][k];
props.f_sd1 = ' ';
props.f_x1a = button_dict[j][5][k];
props.f_x1b = button_dict[j][6][k];
} else props.f_sd1 = button_dict[j][5][k];
props.f_x1c = button_dict[j][7][k];
if(category != eSpecCat::RECT) {
props.sd2_btn = ' ';
props.x2a_btn = button_dict[j][8][k];
props.x2b_btn = button_dict[j][9][k];
} else props.sd2_btn = button_dict[j][8][k];
props.x2c_btn = button_dict[j][10][k];
props.f_sd2 = ' ';
props.f_x2a = button_dict[j][8][k];
props.f_x2b = button_dict[j][9][k];
} else props.f_sd2 = button_dict[j][8][k];
props.f_x2c = button_dict[j][10][k];
if(category == eSpecCat::RECT) {
props.x1a_btn = props.x2a_btn = ' ';
props.x1b_btn = props.x2b_btn = ' ';
props.f_x1a = props.f_x2a = ' ';
props.f_x1b = props.f_x2b = ' ';
}
if(dead_ends.count(check)) {
props.f_jmp = ' ';
} else {
props.f_jmp = check == eSpecType::CALL_GLOBAL ? 'S' : 's';
}
props.f_sd1.lbl_idx = 1; props.f_sd2.lbl_idx = 2;
props.f_m1.lbl_idx = 3; props.f_m2.lbl_idx = 4; props.f_m3.lbl_idx = 5;
props.f_pic.lbl_idx = 6; props.f_pt.lbl_idx = 7;
props.f_x1a.lbl_idx = 8; props.f_x1b.lbl_idx = 9; props.f_x1c.lbl_idx = 10;
props.f_x2a.lbl_idx = 11; props.f_x2b.lbl_idx = 12; props.f_x2c.lbl_idx = 13;
props.f_jmp.lbl_idx = 14;
props.f_sd1.self = props.f_sd2.self = props.f_m1.self = props.f_m2.self = props.f_m3.self = props.f_pic.self = props.f_pt.self = props.f_x1a.self = props.f_x1b.self = props.f_x1c.self = props.f_x2a.self = props.f_x2b.self = props.f_x2c.self = props.f_jmp.self = props.self;
allNodeProps[check] = props;
}
return allNodeProps;
}
const node_properties_t& operator* (eSpecType t) {
static node_properties_t invalid;
static std::map<eSpecType, node_properties_t> allNodeProps = loadProps();
std::map<eSpecType, node_properties_t>& allNodeProps = nodeProps();
if(allNodeProps.empty()) node_properties_t::load();
auto iter = allNodeProps.find(t);
return iter == allNodeProps.end() ? invalid : iter->second;
}
@@ -779,58 +798,128 @@ std::string node_properties_t::name() const {
return get_node_string("specials-text", self, 0);
}
std::string node_properties_t::sdf1_lbl() const {
return get_node_string("specials-text", self, 1);
node_function_t::node_function_t() {}
node_function_t::node_function_t(char c) {
switch(c) {
case ' ': button = eSpecPicker::NONE; break;
case 'm': button = eSpecPicker::MSG_PAIR; force_global = false; break;
case 'M': button = eSpecPicker::MSG_SINGLE; force_global = false; break;
case '$': button = eSpecPicker::MSG_SINGLE; force_global = true; break;
case 'd': button = eSpecPicker::MSG_SEQUENCE; force_global = false; break;
case 'b': button = eSpecPicker::STRING; str_type = STRT_BUTTON; break;
case 'p': button = eSpecPicker::PICTURE; pic_type = PIC_NONE; break;
case '?': button = eSpecPicker::STRING; str_type = STRT_PICT; adjust = -1; break;
case 's': button = eSpecPicker::NODE; force_global = false; break;
case 'S': button = eSpecPicker::NODE; force_global = true; break;
case 'x': button = eSpecPicker::SOUND; break;
case 'X': button = eSpecPicker::STRING; str_type = STRT_TRAP; break;
case 't': button = eSpecPicker::STRING; str_type = STRT_TER; break;
case 'T': button = eSpecPicker::STRING; str_type = STRT_TOWN; break;
case 'i': button = eSpecPicker::STRING; str_type = STRT_ITEM; break;
case 'I': button = eSpecPicker::STRING; str_type = STRT_SPEC_ITEM; break;
case 'c': button = eSpecPicker::STRING; str_type = STRT_MONST; adjust = -1; break;
case 'C': button = eSpecPicker::STRING; str_type = STRT_MONST_STAT; break;
case 'a': button = eSpecPicker::STRING; str_type = STRT_ALCHEMY; break;
case 'A': button = eSpecPicker::STRING; str_type = STRT_MAGE; break;
case 'P': button = eSpecPicker::STRING; str_type = STRT_PRIEST; break;
case 'k': button = eSpecPicker::STRING; str_type = STRT_SKILL; augmented = false; break;
case 'K': button = eSpecPicker::STRING; str_type = STRT_SKILL; augmented = true; break;
case 'f': button = eSpecPicker::FIELD; augmented = false; break;
case 'F': button = eSpecPicker::FIELD; augmented = true; break;
case 'q': button = eSpecPicker::STRING; str_type = STRT_TRAIT; break;
case 'Q': button = eSpecPicker::STRING; str_type = STRT_RACE; break;
case '=': button = eSpecPicker::STRING; str_type = STRT_CMP; adjust = 2; break;
case '+': button = eSpecPicker::STRING; str_type = STRT_ACCUM; adjust = 1; break;
case '*': button = eSpecPicker::STRING; str_type = STRT_CONTEXT; break;
case '@': button = eSpecPicker::STRING; str_type = STRT_ATTITUDE; break;
case 'D': button = eSpecPicker::DAMAGE_TYPE; break;
case '!': button = eSpecPicker::EXPLOSION; break;
case '/': button = eSpecPicker::STRING; str_type = STRT_STAIR; break;
case ':': button = eSpecPicker::STRING; str_type = STRT_STAIR_MODE; break;
case 'L': button = eSpecPicker::STRING; str_type = STRT_LIGHT; break;
case '&': button = eSpecPicker::STRING; str_type = STRT_SHOP; break;
case '%': button = eSpecPicker::STRING; str_type = STRT_COST_ADJ; break;
case '{': button = eSpecPicker::STRING; str_type = STRT_SPELL_PAT; augmented = false; break;
case '}': button = eSpecPicker::STRING; str_type = STRT_SPELL_PAT; augmented = true; break;
case '^': button = eSpecPicker::STRING; str_type = STRT_POS_MODE; break;
case 'e': button = eSpecPicker::STATUS; break;
case 'E': button = eSpecPicker::STATUS_PARTY; break;
case 'w': button = eSpecPicker::STRING; str_type = STRT_STATUS; adjust = 1; break;
case 'j': button = eSpecPicker::STRING; str_type = STRT_QUEST; break;
case 'J': button = eSpecPicker::STRING; str_type = STRT_QUEST_STATUS; break;
case '<': button = eSpecPicker::STRING; str_type = STRT_DIR; break;
case '~': button = eSpecPicker::STRING; str_type = STRT_ENCHANT; break;
case '_': button = eSpecPicker::PICTURE; pic_type = PIC_FULL; break;
case '0': button = eSpecPicker::PICTURE; pic_type = PIC_TER; break;
case '1': button = eSpecPicker::PICTURE; pic_type = PIC_MONST; break;
case '2': button = eSpecPicker::PICTURE; pic_type = PIC_DLOG; break;
case '3': button = eSpecPicker::PICTURE; pic_type = PIC_TALK; break;
case '4': button = eSpecPicker::PICTURE; pic_type = PIC_ITEM; break;
case '5': button = eSpecPicker::PICTURE; pic_type = PIC_PC; break;
case '6': button = eSpecPicker::PICTURE; pic_type = PIC_FIELD; break;
case '7': button = eSpecPicker::PICTURE; pic_type = PIC_BOOM; break;
case '8': button = eSpecPicker::PICTURE; pic_type = PIC_MISSILE; break;
case '9': button = eSpecPicker::PICTURE; pic_type = PIC_STATUS; break;
}
}
std::string node_properties_t::sdf2_lbl() const {
return get_node_string("specials-text", self, 2);
std::string node_function_t::label() const {
return get_node_string("specials-text", self, lbl_idx);
}
std::string node_properties_t::msg1_lbl() const {
return get_node_string("specials-text", self, 3);
node_function_t node_properties_t::sdf1(const cSpecial&) const {
return f_sd1;
}
std::string node_properties_t::msg2_lbl() const {
return get_node_string("specials-text", self, 4);
node_function_t node_properties_t::sdf2(const cSpecial&) const {
return f_sd2;
}
std::string node_properties_t::msg3_lbl() const {
return get_node_string("specials-text", self, 5);
node_function_t node_properties_t::msg1(const cSpecial&) const {
return f_m1;
}
std::string node_properties_t::pic_lbl() const {
return get_node_string("specials-text", self, 6);
node_function_t node_properties_t::msg2(const cSpecial&) const {
return f_m2;
}
std::string node_properties_t::pt_lbl() const {
return get_node_string("specials-text", self, 7);
node_function_t node_properties_t::msg3(const cSpecial&) const {
return f_m3;
}
std::string node_properties_t::ex1a_lbl() const {
return get_node_string("specials-text", self, 8);
node_function_t node_properties_t::pic(const cSpecial&) const {
return f_pic;
}
std::string node_properties_t::ex1b_lbl() const {
return get_node_string("specials-text", self, 9);
node_function_t node_properties_t::pictype(const cSpecial&) const {
return f_pt;
}
std::string node_properties_t::ex1c_lbl() const {
return get_node_string("specials-text", self, 10);
node_function_t node_properties_t::ex1a(const cSpecial&) const {
return f_x1a;
}
std::string node_properties_t::ex2a_lbl() const {
return get_node_string("specials-text", self, 11);
node_function_t node_properties_t::ex1b(const cSpecial&) const {
return f_x1b;
}
std::string node_properties_t::ex2b_lbl() const {
return get_node_string("specials-text", self, 12);
node_function_t node_properties_t::ex1c(const cSpecial&) const {
return f_x1c;
}
std::string node_properties_t::ex2c_lbl() const {
return get_node_string("specials-text", self, 13);
node_function_t node_properties_t::ex2a(const cSpecial&) const {
return f_x2a;
}
std::string node_properties_t::jmp_lbl() const {
return get_node_string("specials-text", self, 14);
node_function_t node_properties_t::ex2b(const cSpecial&) const {
return f_x2b;
}
node_function_t node_properties_t::ex2c(const cSpecial&) const {
return f_x2c;
}
node_function_t node_properties_t::jump(const cSpecial&) const {
return f_jmp;
}

View File

@@ -13,6 +13,7 @@
#include <string>
#include <functional>
#include "location.hpp"
#include "dialogxml/widgets/pictypes.hpp"
namespace legacy { struct special_node_type; };
@@ -125,21 +126,63 @@ enum class eSpecCat {
GENERAL, ONCE, AFFECT, IF_THEN, TOWN, RECT, OUTDOOR
};
enum eStrType {
STRT_MONST, STRT_ITEM, STRT_TER, STRT_BUTTON,
STRT_SPEC_ITEM, STRT_MAGE, STRT_PRIEST, STRT_ALCHEMY,
STRT_TOWN, STRT_SECTOR, STRT_SKILL, STRT_TRAIT, STRT_RACE,
STRT_PICT, STRT_CMP, STRT_ACCUM, STRT_TRAP,
STRT_ATTITUDE, STRT_STAIR, STRT_LIGHT, STRT_CONTEXT,
STRT_SHOP, STRT_COST_ADJ, STRT_STAIR_MODE, STRT_TALK_NODE,
STRT_STATUS, STRT_SPELL_PAT, STRT_SUMMON, STRT_TALK, STRT_TALK_NODE_PERSON,
STRT_ENCHANT, STRT_DIR, STRT_QUEST, STRT_QUEST_STATUS,
STRT_HEALING, STRT_TREASURE, STRT_MONST_STAT, STRT_POS_MODE,
};
enum class eSpecPicker {
NONE,
MSG_SINGLE, MSG_PAIR, MSG_SEQUENCE,
PICTURE, NODE, STRING, SOUND,
FIELD, DAMAGE_TYPE, EXPLOSION,
STATUS, STATUS_PARTY,
};
struct node_function_t {
eSpecPicker button;
union {
eStrType str_type; // for eSpecPicker::STRING only
ePicType pic_type; // for eSpecPicker::PICTURE only; PIC_NONE = use pictype field from node
bool force_global; // for eSpecPicker::NODE and eSpecPicker::MSG_*
// other pickers don't put anything in here
};
bool augmented = false; // only for eSpecPicker::FIELD and eSpecPicker::STRING with certain string types
int adjust = 0; // only for eSpecPicker::STRING
std::string label() const;
std::string help() const; // maybe we don't need this though? I guess it would be for a hypothetical help button next to each field to give addition info on how that one field works.
node_function_t();
node_function_t(char c);
private:
eSpecType self = eSpecType::NONE;
std::string lbl;
int lbl_idx = 0, sub_idx = 0;
bool needs_split = false;
friend struct node_properties_t;
};
struct node_properties_t {
eSpecType self;
eSpecCat cat;
std::string opcode() const;
std::string name() const, descr() const;
std::string sdf1_lbl() const, sdf2_lbl() const, sdf1_hlp() const, sdf2_hlp() const;
std::string msg1_lbl() const, msg2_lbl() const, msg3_lbl() const, msg1_hlp() const, msg2_hlp() const, msg3_hlp() const;
std::string pic_lbl() const, pt_lbl() const, pic_hlp() const, pt_hlp() const;
std::string ex1a_lbl() const, ex1b_lbl() const, ex1c_lbl() const, ex1a_hlp() const, ex1b_hlp() const, ex1c_hlp() const;
std::string ex2a_lbl() const, ex2b_lbl() const, ex2c_lbl() const, ex2a_hlp() const, ex2b_hlp() const, ex2c_hlp() const;
std::string jmp_lbl() const, jmp_hlp() const;
char sd1_btn, sd2_btn, m1_btn, m2_btn, m3_btn, p_btn, pt_btn;
char x1a_btn, x1b_btn, x1c_btn, x2a_btn, x2b_btn, x2c_btn;
node_function_t sdf1(const cSpecial&) const, sdf2(const cSpecial&) const, jump(const cSpecial&) const;
node_function_t msg1(const cSpecial&) const, msg2(const cSpecial&) const, msg3(const cSpecial&) const;
node_function_t pic(const cSpecial&) const, pictype(const cSpecial&) const;
node_function_t ex1a(const cSpecial&) const, ex1b(const cSpecial&) const, ex1c(const cSpecial&) const;
node_function_t ex2a(const cSpecial&) const, ex2b(const cSpecial&) const, ex2c(const cSpecial&) const;
node_properties_t() : self(eSpecType::INVALID), cat(eSpecCat::INVALID) {}
node_properties_t(std::initializer_list<std::function<void(node_properties_t)>>);
static void load();
private:
node_function_t f_sd1, f_sd2, f_jmp, f_m1, f_m2, f_m3, f_pic, f_pt, f_x1a, f_x1b, f_x1c, f_x2a, f_x2b, f_x2c;
};
const node_properties_t& operator* (eSpecType t);

View File

@@ -520,17 +520,17 @@ struct editing_node_t {
typedef std::stack<editing_node_t> node_stack_t;
static void setup_node_field(cDialog& me, std::string field, short value, std::string label, char buttonType) {
me[field + "-lbl"].setText(label);
static void setup_node_field(cDialog& me, std::string field, short value, const node_function_t& fcn) {
me[field + "-lbl"].setText(fcn.label());
me[field].setTextToNum(value);
bool is_sdf = field.substr(0,3) == "sdf";
std::string button = field + "-edit";
switch(buttonType) {
case ' ':
switch(fcn.button) {
case eSpecPicker::NONE:
me[button].hide();
break;
case 'm': case 'M': case '$': case 'd': // messages
case 's': case 'S': // specials
case eSpecPicker::MSG_PAIR: case eSpecPicker::MSG_SINGLE:
case eSpecPicker::MSG_SEQUENCE: case eSpecPicker::NODE:
me[button].show();
if(is_sdf) break;
me[button].setText("Create/Edit");
@@ -546,8 +546,6 @@ static void setup_node_field(cDialog& me, std::string field, short value, std::s
}
static void put_spec_enc_in_dlog(cDialog& me, node_stack_t& edit_stack) {
// These are the node types that should not have a Create/Edit button on the JumpTo
static std::set<eSpecType> dead_ends = {eSpecType::ENTER_SHOP, eSpecType::START_TALK, eSpecType::TOWN_GENERIC_STAIR, eSpecType::TOWN_STAIR};
cSpecial& spec = edit_stack.top().node;
// Show which node is being edited and what type of node it is
@@ -563,25 +561,25 @@ static void put_spec_enc_in_dlog(cDialog& me, node_stack_t& edit_stack) {
node_properties_t info = *spec.type;
// Set up the labels, fields, and buttons
setup_node_field(me, "sdf1", spec.sd1, info.sdf1_lbl(), info.sd1_btn);
setup_node_field(me, "sdf2", spec.sd2, info.sdf2_lbl(), info.sd2_btn);
setup_node_field(me, "sdf1", spec.sd1, info.sdf1(spec));
setup_node_field(me, "sdf2", spec.sd2, info.sdf2(spec));
setup_node_field(me, "msg1", spec.m1, info.msg1_lbl(), info.m1_btn);
setup_node_field(me, "msg2", spec.m2, info.msg2_lbl(), info.m2_btn);
setup_node_field(me, "msg3", spec.m3, info.msg3_lbl(), info.m3_btn);
setup_node_field(me, "msg1", spec.m1, info.msg1(spec));
setup_node_field(me, "msg2", spec.m2, info.msg2(spec));
setup_node_field(me, "msg3", spec.m3, info.msg3(spec));
setup_node_field(me, "pict", spec.pic, info.pic_lbl(), info.p_btn);
setup_node_field(me, "pictype", spec.pictype, info.pt_lbl(), info.pt_btn);
setup_node_field(me, "pict", spec.pic, info.pic(spec));
setup_node_field(me, "pictype", spec.pictype, info.pictype(spec));
setup_node_field(me, "x1a", spec.ex1a, info.ex1a_lbl(), info.x1a_btn);
setup_node_field(me, "x1b", spec.ex1b, info.ex1b_lbl(), info.x1b_btn);
setup_node_field(me, "x1c", spec.ex1c, info.ex1c_lbl(), info.x1c_btn);
setup_node_field(me, "x1a", spec.ex1a, info.ex1a(spec));
setup_node_field(me, "x1b", spec.ex1b, info.ex1b(spec));
setup_node_field(me, "x1c", spec.ex1c, info.ex1c(spec));
setup_node_field(me, "x2a", spec.ex2a, info.ex2a_lbl(), info.x2a_btn);
setup_node_field(me, "x2b", spec.ex2b, info.ex2b_lbl(), info.x2b_btn);
setup_node_field(me, "x2c", spec.ex2c, info.ex2c_lbl(), info.x2c_btn);
setup_node_field(me, "x2a", spec.ex2a, info.ex2a(spec));
setup_node_field(me, "x2b", spec.ex2b, info.ex2b(spec));
setup_node_field(me, "x2c", spec.ex2c, info.ex2c(spec));
setup_node_field(me, "jump", spec.jumpto, info.jmp_lbl(), dead_ends.count(spec.type) ? ' ' : 's');
setup_node_field(me, "jump", spec.jumpto, info.jump(spec));
}
static void save_spec_enc(cDialog& me, node_stack_t& edit_stack) {
@@ -807,57 +805,46 @@ snd_num_t choose_sound(short cur, cDialog* parent, std::string title) {
return snd_dlg.show(cur);
}
static node_function_t get_field_function(const cSpecial& spec, const std::string& field) {
if(field == "sdf1") return (*spec.type).sdf1(spec);
else if(field == "sdf2") return (*spec.type).sdf2(spec);
else if(field == "msg1") return (*spec.type).msg1(spec);
else if(field == "msg2") return (*spec.type).msg2(spec);
else if(field == "msg3") return (*spec.type).msg3(spec);
else if(field == "pict") return (*spec.type).pic(spec);
else if(field == "pictype") return (*spec.type).pictype(spec);
else if(field == "x1a") return (*spec.type).ex1a(spec);
else if(field == "x1b") return (*spec.type).ex1b(spec);
else if(field == "x1c") return (*spec.type).ex1c(spec);
else if(field == "x2a") return (*spec.type).ex2a(spec);
else if(field == "x2b") return (*spec.type).ex2b(spec);
else if(field == "x2c") return (*spec.type).ex2c(spec);
else if(field == "jump") return (*spec.type).jump(spec);
return node_function_t();
}
static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t& edit_stack) {
static const ePicType pics[11] = {
PIC_TER, PIC_MONST, PIC_DLOG, PIC_TALK, PIC_ITEM,
PIC_PC, PIC_FIELD, PIC_BOOM, PIC_MISSILE, PIC_STATUS,
PIC_FULL
};
std::string field = item_hit.substr(0, item_hit.find_first_of('-'));
char btn = '\0';
eSpecType type = edit_stack.top().node.type;
if(field == "sdf1") btn = (*type).sd1_btn;
else if(field == "sdf2") btn = (*type).sd2_btn;
else if(field == "msg1") btn = (*type).m1_btn;
else if(field == "msg2") btn = (*type).m2_btn;
else if(field == "msg3") btn = (*type).m3_btn;
else if(field == "pict") btn = (*type).p_btn;
else if(field == "pictype") btn = (*type).pt_btn;
else if(field == "x1a") btn = (*type).x1a_btn;
else if(field == "x1b") btn = (*type).x1b_btn;
else if(field == "x1c") btn = (*type).x1c_btn;
else if(field == "x2a") btn = (*type).x2a_btn;
else if(field == "x2b") btn = (*type).x2b_btn;
else if(field == "x2c") btn = (*type).x2c_btn;
else if(field == "jump") {
if(type == eSpecType::CALL_GLOBAL) btn = 'S';
else btn = 's';
}
short val = me[field].getTextAsNum(), mode = (btn == 'S' || btn == '$') ? 0 : edit_stack.top().mode, store;
short pictype = me["pictype"].getTextAsNum();
bool choose_string = true;
eStrType strt;
short str_adj = 0;
const char* title = "";
switch(btn) {
case 'm':
choose_string = false;
const cSpecial& spec = edit_stack.top().node;
node_function_t fcn = get_field_function(spec, field);
short val = me[field].getTextAsNum(), store;
switch(fcn.button) {
case eSpecPicker::MSG_PAIR:
store = me["msg2"].getTextAsNum();
edit_spec_text(eStrMode(mode), &val, &store, &me);
edit_spec_text(fcn.force_global ? STRS_SCEN : eStrMode(edit_stack.top().mode), &val, &store, &me);
me["msg2"].setTextToNum(store);
store = val;
break;
case 'M': case '$':
choose_string = false;
edit_spec_text(eStrMode(mode), &val, nullptr, &me);
case eSpecPicker::MSG_SINGLE:
edit_spec_text(fcn.force_global ? STRS_SCEN : eStrMode(edit_stack.top().mode), &val, nullptr, &me);
store = val;
break;
case 'd':
choose_string = false;
case eSpecPicker::MSG_SEQUENCE:
store = val;
edit_dialog_text(eStrMode(mode), &store, &me);
edit_dialog_text(fcn.force_global ? STRS_SCEN : eStrMode(edit_stack.top().mode), &store, &me);
break;
case 's': case 'S': {
case eSpecPicker::NODE: {
short mode = fcn.force_global ? 0 : edit_stack.top().mode;
store = val < 0 ? get_fresh_spec(mode) : val;
me[field].setTextToNum(store);
save_spec_enc(me, edit_stack);
@@ -877,64 +864,64 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
me["back"].show();
return true;
}
case 'p':
choose_string = false;
if(pictype < 0) me["pictype"].setTextToNum(PIC_DLOG);
store = choose_graphic(val, pictype < 0 ? PIC_DLOG : ePicType(pictype), &me);
case eSpecPicker::STRING: {
std::string title;
switch(fcn.str_type) {
case STRT_SPELL_PAT: title = "Which spell pattern?"; break;
case STRT_ITEM: title = "Which item?"; break;
case STRT_SPEC_ITEM: title = "Which special item?"; break;
case STRT_TER: title = "Which terrain?"; break;
case STRT_MONST: title = "Which monster?"; break;
case STRT_MONST_STAT: title = "Which statistic?"; break;
case STRT_ALCHEMY: title = "Which recipe?"; break;
case STRT_MAGE: title = "Which spell?"; break;
case STRT_PRIEST: title = "Which spell?"; break;
case STRT_SKILL: title = "Which statistic?"; break;
case STRT_TRAIT: title = "Which trait?"; break;
case STRT_RACE: title = "Which species?"; break;
case STRT_TOWN: title = "Which town?"; break;
case STRT_BUTTON: title = "Which button?"; break;
case STRT_PICT: title = "Which picture type?"; break;
case STRT_TRAP: title = "What trap type?"; break;
case STRT_CMP: title = "What comparison method?"; break;
case STRT_ACCUM: title = "What accumulation method?"; break;
case STRT_ATTITUDE: title = "What attitude?"; break;
case STRT_STAIR: title = "Which stairway text?"; break;
case STRT_LIGHT: title = "What lighting type?"; break;
case STRT_SHOP: title = "Which shop?"; break;
case STRT_COST_ADJ: title = "What cost adjust?"; break;
case STRT_CONTEXT: title = "What context?"; break;
case STRT_ENCHANT: title = "Which enchantment?"; break;
case STRT_POS_MODE: title = "Select positioning mode:"; break;
case STRT_STAIR_MODE: title = "Select trigger limitations:"; break;
case STRT_STATUS: title = "Select status:"; break;
case STRT_QUEST: title = "Select a quest:"; break;
case STRT_QUEST_STATUS: title = "Select the quest's status:"; break;
case STRT_DIR: title = "Select the direction:"; break;
default: title = "Title not set for this string type!!!"; break;
}
store = choose_text(fcn.str_type, val + fcn.adjust, &me, title) - fcn.adjust;
} break;
case eSpecPicker::PICTURE: {
ePicType type = fcn.pic_type;
if(type == PIC_NONE) {
short pictype = me["pictype"].getTextAsNum();
if(pictype < 0) {
me["pictype"].setTextToNum(PIC_DLOG);
type = PIC_DLOG;
} else type = ePicType(pictype);
}
store = choose_graphic(val, type, &me);
if(store < 0) store = val;
break;
case 'f': case 'F': choose_string = false; store = choose_field_type(val, &me, btn == 'F'); break;
case 'D': choose_string = false; store = choose_damage_type(val, &me, true); break;
case '!': choose_string = false; store = choose_boom_type(val, &me); break;
case 'e': choose_string = false; store = choose_status_effect(val, false, &me); break;
case 'E': choose_string = false; store = choose_status_effect(val, true, &me); break;
case '{': case '}': strt = STRT_SPELL_PAT; title = "Which spell pattern?"; break;
case 'i': strt = STRT_ITEM; title = "Which item?"; break;
case 'I': strt = STRT_SPEC_ITEM; title = "Which special item?"; break;
case 't': strt = STRT_TER; title = "Which terrain?"; break;
case 'c': strt = STRT_MONST; title = "Which monster?"; str_adj = -1; break;
case 'C': strt = STRT_MONST_STAT; title = "Which statistic?"; break;
case 'a': strt = STRT_ALCHEMY; title = "Which recipe?"; break;
case 'A': strt = STRT_MAGE; title = "Which spell?"; break;
case 'P': strt = STRT_PRIEST; title = "Which spell?"; break;
case 'k': case 'K': strt = STRT_SKILL; title = "Which statistic?"; break;
case 'q': strt = STRT_TRAIT; title = "Which trait?"; break;
case 'Q': strt = STRT_RACE; title = "Which species?"; break;
case 'T': strt = STRT_TOWN; title = "Which town?"; break;
case 'b': strt = STRT_BUTTON; title = "Which button?"; break;
case '?': strt = STRT_PICT; title = "Which picture type?"; str_adj = -1; break;
case 'x': choose_string = false; store = choose_sound(val, &me); break;
case 'X': strt = STRT_TRAP; title = "What trap type?"; break;
case '=': strt = STRT_CMP; title = "What comparison method?"; str_adj = 2; break;
case '+': strt = STRT_ACCUM; title = "What accumulation method?"; str_adj = 1; break;
case '@': strt = STRT_ATTITUDE; title = "What attitude?"; break;
case '/': strt = STRT_STAIR; title = "Which stairway text?"; break;
case 'L': strt = STRT_LIGHT; title = "What lighting type?"; break;
case '&': strt = STRT_SHOP; title = "Which shop?"; break;
case '%': strt = STRT_COST_ADJ; title = "What cost adjust?"; break;
case '*': strt = STRT_CONTEXT; title = "What context?"; break;
case '~': strt = STRT_ENCHANT; title = "Which enchantment?"; break;
case '^': strt = STRT_POS_MODE; title = "Select positioning mode:"; break;
case ':': strt = STRT_STAIR_MODE; title = "Select trigger limitations:"; break;
case 'w': strt = STRT_STATUS; title = "Select status:"; str_adj = 1; break;
case 'j': strt = STRT_QUEST; title = "Select a quest:"; break;
case 'J': strt = STRT_QUEST_STATUS; title = "Select the quest's status:"; break;
case '<': strt = STRT_DIR; title = "Select the direction:"; break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '_':
choose_string = false;
store = choose_graphic(val, pics[btn == '_' ? 10 : btn - '0'], &me);
if(store < 0) store = val;
break;
default:
choose_string = false;
store = val;
showError("Whoops! Unknown edit type! (" + (btn + std::string(")")), "", &me);
break;
} break;
case eSpecPicker::FIELD: store = choose_field_type(val, &me, fcn.augmented); break;
case eSpecPicker::DAMAGE_TYPE: store = choose_damage_type(val, &me, true); break;
case eSpecPicker::EXPLOSION: store = choose_boom_type(val, &me); break;
case eSpecPicker::STATUS: store = choose_status_effect(val, false, &me); break;
case eSpecPicker::STATUS_PARTY: store = choose_status_effect(val, true, &me); break;
case eSpecPicker::SOUND: store = choose_sound(val, &me); break;
case eSpecPicker::NONE: return false;
}
if(choose_string)
store = choose_text(strt, val + str_adj, &me, title) - str_adj;
me[field].setTextToNum(store);
return true;
}

View File

@@ -4,18 +4,6 @@
#include "location.hpp" // for info_rect_t
class cDialog;
enum eStrType {
STRT_MONST, STRT_ITEM, STRT_TER, STRT_BUTTON,
STRT_SPEC_ITEM, STRT_MAGE, STRT_PRIEST, STRT_ALCHEMY,
STRT_TOWN, STRT_SECTOR, STRT_SKILL, STRT_TRAIT, STRT_RACE,
STRT_PICT, STRT_CMP, STRT_ACCUM, STRT_TRAP,
STRT_ATTITUDE, STRT_STAIR, STRT_LIGHT, STRT_CONTEXT,
STRT_SHOP, STRT_COST_ADJ, STRT_STAIR_MODE, STRT_TALK_NODE,
STRT_STATUS, STRT_SPELL_PAT, STRT_SUMMON, STRT_TALK, STRT_TALK_NODE_PERSON,
STRT_ENCHANT, STRT_DIR, STRT_QUEST, STRT_QUEST_STATUS,
STRT_HEALING, STRT_TREASURE, STRT_MONST_STAT, STRT_POS_MODE,
};
bool cre(short val,short min,short max,std::string text1,std::string text2,cDialog* parent) ;
void display_strings(char *text1, char *text2,
char *title,short sound_num,short graphic_num,short graphic_type,cDialog* parent);