Add a location picker for selecting a location in a town or outdoor sector.

It's currently used in special node editing and in advanced town details.
This commit is contained in:
2025-02-28 01:26:29 -05:00
committed by Celtic Minstrel
parent 63bbb38374
commit 5861268e8c
24 changed files with 484 additions and 59 deletions

View File

@@ -28,7 +28,7 @@ namespace {
.sdf(eSpecField::EX1A, eSpecField::EX1B)
.ex2b(eSpecPicker::NODE);
node_properties_t S_TERRAIN = node_builder_t(eSpecType::IF_TER_TYPE)
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_AUTO)
.ex2a(STRT_TER)
.ex2b(eSpecPicker::NODE);
node_properties_t S_ALIVE = node_builder_t(eSpecType::IF_ALIVE)
@@ -41,7 +41,7 @@ namespace {
.ex1b(eSpecPicker::NODE)
.ex2a(eSpecPicker::TOGGLE);
node_properties_t S_ITEM_THERE = node_builder_t(eSpecType::IF_ITEM_CLASS_ON_SPACE)
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(eSpecPicker::ITEM_CLASS)
.ex2b(eSpecPicker::NODE)
.ex2c(eSpecPicker::TOGGLE);
@@ -72,7 +72,7 @@ namespace {
node_properties_t S_DAY = node_builder_t(eSpecType::IF_DAY_REACHED)
.ex1b(eSpecPicker::NODE);
node_properties_t S_FIELDS = node_builder_t(eSpecType::IF_FIELDS)
.rect()
.rect(eLocType::ACTIVE_TOWN)
.msg1(eSpecPicker::FIELD)
.msg2(eSpecPicker::NODE);
node_properties_t S_PARTY_SIZE = node_builder_t(eSpecType::IF_PARTY_SIZE)

View File

@@ -117,16 +117,16 @@ namespace{
.msg();
node_properties_t S_TERCHANGE = node_builder_t(eSpecType::CHANGE_TER)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_AUTO)
.ex2a(STRT_TER);
node_properties_t S_TERSWAP = node_builder_t(eSpecType::SWAP_TER)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_AUTO)
.ex2a(STRT_TER)
.ex2b(STRT_TER);
node_properties_t S_TERTRANS = node_builder_t(eSpecType::TRANS_TER)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_AUTO);
node_properties_t S_BUF_CLEAR = node_builder_t(eSpecType::CLEAR_BUF);
node_properties_t S_BUF_ADDSTR = node_builder_t(eSpecType::APPEND_STRING)
.ex1a(eSpecPicker::MSG_SINGLE)

View File

@@ -14,11 +14,12 @@ namespace {
node_properties_t S_WANDER = node_builder_t(eSpecType::OUT_MAKE_WANDER);
node_properties_t S_TOWN = node_builder_t(eSpecType::OUT_FORCE_TOWN)
.msg()
.loc(eSpecField::EX2A, eSpecField::EX2B, eLocType::SPECIFIED_TOWN, eSpecField::EX1A)
.ex1a(STRT_TOWN)
.ex1b(STRT_DIR);
node_properties_t S_ENCOUNTER = node_builder_t(eSpecType::OUT_PLACE_ENCOUNTER)
.msg();
node_properties_t S_TELEPORT = node_builder_t(eSpecType::OUT_MOVE_PARTY)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_OUT);
}

View File

@@ -13,36 +13,36 @@ node_category_info_t CAT_RECT{eSpecType::RECT_PLACE_FIELD, eSpecType::RECT_UNLOC
namespace {
node_properties_t S_FIELDS = node_builder_t(eSpecType::RECT_PLACE_FIELD)
.msg()
.rect()
.rect(eLocType::ACTIVE_TOWN)
.sdf2(+eSpecPicker::FIELD);
node_properties_t S_EXPLORE = node_builder_t(eSpecType::RECT_SET_EXPLORED)
.msg()
.rect()
.rect(eLocType::ACTIVE_AUTO)
.sdf1(eSpecPicker::TOGGLE);
node_properties_t S_MOVE = node_builder_t(eSpecType::RECT_MOVE_ITEMS)
.msg()
.rect()
.rect(eLocType::ACTIVE_TOWN)
.msg3(eSpecPicker::TOGGLE)
.loc(eSpecField::SDF1, eSpecField::SDF2);
.loc(eSpecField::SDF1, eSpecField::SDF2, eLocType::ACTIVE_TOWN);
node_properties_t S_DESTROY = node_builder_t(eSpecType::RECT_DESTROY_ITEMS)
.msg()
.rect();
.rect(eLocType::ACTIVE_TOWN);
node_properties_t S_CHANGE = node_builder_t(eSpecType::RECT_CHANGE_TER)
.msg()
.rect()
.rect(eLocType::ACTIVE_AUTO)
.sdf1(STRT_TER);
node_properties_t S_SWAP = node_builder_t(eSpecType::RECT_SWAP_TER)
.msg()
.rect()
.rect(eLocType::ACTIVE_AUTO)
.sdf1(STRT_TER)
.sdf2(STRT_TER);
node_properties_t S_TRANS = node_builder_t(eSpecType::RECT_TRANS_TER)
.msg()
.rect();
.rect(eLocType::ACTIVE_AUTO);
node_properties_t S_LOCK = node_builder_t(eSpecType::RECT_LOCK)
.msg()
.rect();
.rect(eLocType::ACTIVE_TOWN);
node_properties_t S_UNLOCK = node_builder_t(eSpecType::RECT_UNLOCK)
.msg()
.rect();
.rect(eLocType::ACTIVE_TOWN);
}

View File

@@ -17,38 +17,39 @@ namespace {
node_properties_t S_MISSILE = node_builder_t(eSpecType::TOWN_RUN_MISSILE)
.msg()
.pict(PIC_MISSILE)
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX2A, eSpecField::EX2B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.loc(eSpecField::EX2A, eSpecField::EX2B, eLocType::ACTIVE_TOWN)
.ex1c(STRT_PATH)
.ex2c(eSpecPicker::SOUND);
node_properties_t S_ATTACK = node_builder_t(eSpecType::TOWN_MONST_ATTACK)
.msg();
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_BOOM = node_builder_t(eSpecType::TOWN_BOOM_SPACE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(PIC_BOOM)
.ex2c(eSpecPicker::SOUND);
node_properties_t S_TELEPORT = node_builder_t(eSpecType::TOWN_MOVE_PARTY)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(eSpecPicker::TOGGLE);
node_properties_t S_HIT = node_builder_t(eSpecType::TOWN_HIT_SPACE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2b(eSpecPicker::DAMAGE_TYPE);
node_properties_t S_EXPLODE = node_builder_t(eSpecType::TOWN_EXPLODE_SPACE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2b(eSpecPicker::DAMAGE_TYPE);
node_properties_t S_LOCK = node_builder_t(eSpecType::TOWN_LOCK_SPACE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_UNLOCK = node_builder_t(eSpecType::TOWN_UNLOCK_SPACE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_BURST = node_builder_t(eSpecType::TOWN_SFX_BURST)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(eSpecPicker::EXPLOSION)
.ex2b(eSpecPicker::TOGGLE)
.ex2c(eSpecPicker::SOUND);
@@ -56,23 +57,23 @@ namespace {
.msg();
node_properties_t S_SPAWN = node_builder_t(eSpecType::TOWN_PLACE_MONST)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(STRT_MONST)
.ex2b(eSpecPicker::TOGGLE);
node_properties_t S_KILL = node_builder_t(eSpecType::TOWN_DESTROY_MONST)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_NUKE = node_builder_t(eSpecType::TOWN_NUKE_MONSTS)
.msg()
.ex1a(STRT_MONST);
node_properties_t S_LEVER_G = node_builder_t(eSpecType::TOWN_GENERIC_LEVER)
.ex1b(eSpecPicker::NODE);
node_properties_t S_PORTAL_G = node_builder_t(eSpecType::TOWN_GENERIC_PORTAL)
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_BUTTON_G = node_builder_t(eSpecType::TOWN_GENERIC_BUTTON)
.ex1b(eSpecPicker::NODE);
node_properties_t S_STAIR_G = node_builder_t(eSpecType::TOWN_GENERIC_STAIR)
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::SPECIFIED_TOWN, eSpecField::EX2A)
.ex2a(STRT_TOWN)
.ex2b(STRT_STAIR)
.ex2c(STRT_STAIR_MODE)
@@ -84,11 +85,11 @@ namespace {
node_properties_t S_PORTAL = node_builder_t(eSpecType::TOWN_PORTAL)
.msg1(eSpecPicker::MSG_SEQUENCE)
.pic()
.loc(eSpecField::EX1A, eSpecField::EX1B);
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN);
node_properties_t S_STAIR = node_builder_t(eSpecType::TOWN_STAIR)
.msg1(eSpecPicker::MSG_SEQUENCE)
.pic()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::SPECIFIED_TOWN, eSpecField::EX2A)
.ex2a(STRT_TOWN)
.ex2b(eSpecPicker::TOGGLE)
.ex2c(STRT_STAIR_MODE)
@@ -96,15 +97,15 @@ namespace {
node_properties_t S_OUTDOOR = node_builder_t(eSpecType::TOWN_RELOCATE)
.msg()
.field_pair(eSpecField::EX1A, eSpecField::EX1B, STRT_SECTOR)
.loc(eSpecField::EX2A, eSpecField::EX2B);
.loc(eSpecField::EX2A, eSpecField::EX2B, eLocType::SPECIFIED_OUT, eSpecField::EX1A);
node_properties_t S_ITEM = node_builder_t(eSpecType::TOWN_PLACE_ITEM)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(STRT_ITEM)
.ex2b(eSpecPicker::TOGGLE);
node_properties_t S_SPLIT = node_builder_t(eSpecType::TOWN_SPLIT_PARTY)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(eSpecPicker::SOUND);
node_properties_t S_REUNITE = node_builder_t(eSpecType::TOWN_REUNITE_PARTY)
.msg()
@@ -133,21 +134,21 @@ namespace {
.ex2c(eSpecPicker::TOGGLE);
node_properties_t S_FIELDS = node_builder_t(eSpecType::TOWN_SPELL_PAT_FIELD)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex1c(+STRT_SPELL_PAT)
.ex2a(+eSpecPicker::FIELD);
node_properties_t S_PATTERN = node_builder_t(eSpecType::TOWN_SPELL_PAT_BOOM)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex1c(+STRT_SPELL_PAT)
.ex2a(eSpecPicker::DAMAGE_TYPE)
.ex2c(STRT_SPELL_PAT_MODE);
node_properties_t S_WARP = node_builder_t(eSpecType::TOWN_RELOCATE_CREATURE)
.msg()
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2b(STRT_POS_MODE);
node_properties_t S_LABEL = node_builder_t(eSpecType::TOWN_PLACE_LABEL)
.msg1(eSpecPicker::MSG_SINGLE)
.loc(eSpecField::EX1A, eSpecField::EX1B)
.loc(eSpecField::EX1A, eSpecField::EX1B, eLocType::ACTIVE_TOWN)
.ex2a(STRT_LABEL_ALIGN);
}

View File

@@ -652,6 +652,11 @@ node_function_t::node_function_t(ePicType pic)
, pic_type(pic)
{}
node_function_t::node_function_t(eLocType loc)
: button(eSpecPicker::LOCATION)
, loc_type(loc)
{}
node_function_t operator+(eSpecPicker picker) {
node_function_t n(picker);
if(picker == eSpecPicker::NODE || picker == eSpecPicker::MSG_PAIR || picker == eSpecPicker::MSG_SINGLE || picker == eSpecPicker::MSG_SEQUENCE) {
@@ -765,10 +770,8 @@ node_builder_t& node_builder_t::msg() {
return field_pair(eSpecField::MSG1, eSpecField::MSG2, eSpecPicker::MSG_PAIR);
};
node_builder_t& node_builder_t::rect() {
// The intent is to specify that ex1a,ex1b, and ex2a,ex2b are locations.
// But specifying that two fields are a location isn't implemented yet.
return loc(eSpecField::EX1A, eSpecField::EX1B).loc(eSpecField::EX2A, eSpecField::EX2B).pict(eSpecPicker::TOGGLE);
node_builder_t& node_builder_t::rect(eLocType type) {
return loc(eSpecField::EX1A, eSpecField::EX1B, type).loc(eSpecField::EX2A, eSpecField::EX2B, type).pict(eSpecPicker::TOGGLE);
};
node_builder_t& node_builder_t::pic() {
@@ -847,8 +850,14 @@ node_builder_t& node_builder_t::sdf(eSpecField a, eSpecField b) {
return field_pair(a, b, eSpecPicker::SDF);
}
node_builder_t& node_builder_t::loc(eSpecField a, eSpecField b) {
return field_pair(a, b, eSpecPicker::LOCATION);
node_builder_t& node_builder_t::loc(eSpecField a, eSpecField b, eLocType type) {
return field_pair(a, b, type);
}
node_builder_t& node_builder_t::loc(eSpecField a, eSpecField b, eLocType type, eSpecField where) {
loc(a, b, type);
(node.*fields().map[b]).continuation = where;
return *this;
}
node_builder_t::operator node_properties_t() {

View File

@@ -160,6 +160,11 @@ enum class eSpecPicker {
POINTER,
};
enum class eLocType {
ACTIVE_AUTO, ACTIVE_TOWN, ACTIVE_OUT,
SPECIFIED_TOWN, SPECIFIED_OUT
};
enum class eSpecField { NONE, SDF1, SDF2, MSG1, MSG2, MSG3, PICT, PTYP, EX1A, EX1B, EX1C, EX2A, EX2B, EX2C, JUMP };
struct node_function_t {
@@ -167,6 +172,7 @@ struct node_function_t {
union {
eStrType str_type; // for eSpecPicker::STRING only
ePicType pic_type; // for eSpecPicker::PICTURE only; PIC_NONE = use pictype field from node
eLocType loc_type; // for eSpecPicker::LOCATION only
bool force_global; // for eSpecPicker::NODE and eSpecPicker::MSG_*
// other pickers don't put anything in here
};
@@ -179,6 +185,7 @@ struct node_function_t {
node_function_t(eSpecPicker button);
node_function_t(eStrType str);
node_function_t(ePicType pic);
node_function_t(eLocType loc);
private:
eSpecType self = eSpecType::NONE;
std::string lbl;
@@ -246,11 +253,13 @@ struct node_builder_t {
// Specifies that ex1a,ex1b and ex2a,ex2b define opposing corners of a rectangle.
// DO NOT use for other cases where there are two points, for example defining a path!
// Also DO NOT use for cases where an outdoor sector is identified by its coordinates.
node_builder_t& rect();
node_builder_t& rect(eLocType type);
// Specifies that the indicated two fields combine to define an SDF.
node_builder_t& sdf(eSpecField a, eSpecField b);
// Specifies that the indicated two fields combine to define a location.
node_builder_t& loc(eSpecField a, eSpecField b);
node_builder_t& loc(eSpecField a, eSpecField b, eLocType type);
// As above, but also notes that the area the location is in will be specified by the indicated field.
node_builder_t& loc(eSpecField a, eSpecField b, eLocType type, eSpecField where);
operator node_properties_t();
private:
node_properties_t node;