The special node dictionary now supports specifying different labels or pickers based on the value of another field.
This commit is contained in:
@@ -346,6 +346,7 @@
|
||||
<ClInclude Include="..\..\..\src\scenario\scenario.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\shop.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\special.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\special-conditions.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\talking.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\terrain.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\terrain_abilities.hpp" />
|
||||
|
@@ -901,6 +901,9 @@
|
||||
<ClInclude Include="..\..\..\src\scenario\special.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\scenario\special-conditions.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\scenario\shop.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
|
@@ -505,6 +505,7 @@
|
||||
<ClInclude Include="..\..\..\src\scenario\scenario.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\shop.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\special.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\special-conditions.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\talking.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\terrain.hpp" />
|
||||
<ClInclude Include="..\..\..\src\scenario\terrain_abilities.hpp" />
|
||||
|
@@ -925,6 +925,9 @@
|
||||
<ClInclude Include="..\..\..\src\scenario\special.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\scenario\special-conditions.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\scenario\talking.hpp">
|
||||
<Filter>Scenario</Filter>
|
||||
</ClInclude>
|
||||
|
@@ -744,6 +744,7 @@
|
||||
9170C5262D74237A009B6E7C /* scen.sdfpicker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = scen.sdfpicker.hpp; sourceTree = "<group>"; };
|
||||
9170C5962D75EE42009B6E7C /* pattern.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pattern.cpp; sourceTree = "<group>"; };
|
||||
9170C5972D75EE42009B6E7C /* pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = pattern.hpp; sourceTree = "<group>"; };
|
||||
9170C5A32D79659A009B6E7C /* special-conditions.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = "special-conditions.hpp"; sourceTree = "<group>"; };
|
||||
9176FEC01D550EFC006EF694 /* out_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = out_legacy.cpp; sourceTree = "<group>"; };
|
||||
9176FEC11D550EFC006EF694 /* scen_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scen_legacy.cpp; sourceTree = "<group>"; };
|
||||
9176FEC41D550EFD006EF694 /* talk_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talk_legacy.cpp; sourceTree = "<group>"; };
|
||||
@@ -1301,6 +1302,7 @@
|
||||
91279C570F9D1253007B0D52 /* scenario.hpp */,
|
||||
91FDB5771A4E71A900DE5983 /* shop.hpp */,
|
||||
91279CC50F9D1A02007B0D52 /* special.hpp */,
|
||||
9170C5A32D79659A009B6E7C /* special-conditions.hpp */,
|
||||
91E5C7B60F9F619D00C21460 /* talking.hpp */,
|
||||
91279C650F9D12D6007B0D52 /* terrain.hpp */,
|
||||
9185BD9C1EA02BA20027C346 /* terrain_abilities.hpp */,
|
||||
|
@@ -10,7 +10,7 @@ Restrictions
|
||||
Special if Cancel button pressed
|
||||
Unused
|
||||
Selection Mode
|
||||
0..6 - PC, 100+ - monster (if above = 2)
|
||||
Unused|0..6 - PC, 100+ - monster
|
||||
Unused
|
||||
Special to Jump To
|
||||
|
||||
|
@@ -196,7 +196,7 @@ Unused
|
||||
0 - allow, 1 - prevent
|
||||
Unused
|
||||
Unused
|
||||
Force allow if blocked?
|
||||
Unused|Force allow if blocked?
|
||||
Unused
|
||||
Unused
|
||||
Special to Jump To
|
||||
@@ -509,16 +509,16 @@ Special to Jump To
|
||||
|
||||
--------------------
|
||||
Debug Print Numbers
|
||||
Stuff Done Flag Part A
|
||||
Stuff Done Flag Part B
|
||||
Unused|Stuff Done Flag Part A
|
||||
Unused|Stuff Done Flag Part B
|
||||
Unused
|
||||
Unused
|
||||
Unused
|
||||
Specify what to print
|
||||
Unused
|
||||
Number of monster, or value to print
|
||||
Value to print (could be a pointer)
|
||||
Value to print (could be a pointer)
|
||||
Unused|Value to print (could be a pointer)|Number of monster
|
||||
Unused|Value to print (could be a pointer)
|
||||
Unused|Value to print (could be a pointer)
|
||||
Unused
|
||||
Unused
|
||||
Unused
|
||||
@@ -774,7 +774,7 @@ Unused
|
||||
Which quest?
|
||||
New Quest Status
|
||||
Unused
|
||||
Job Board Source / Anger (see docs)
|
||||
Unused|Job Board Source|Job Board Anger
|
||||
Unused
|
||||
Unused
|
||||
Special to Jump To
|
||||
|
@@ -465,11 +465,11 @@ Minimum allowed response
|
||||
Maximum allowed response
|
||||
Comparison Mode
|
||||
If tests 1 and 2 both pass, call this special ...
|
||||
Range lower bound (or value to compare to)
|
||||
Range upper bound (or comparison method -2 .. 2)
|
||||
Range lower bound|Value to compare to
|
||||
Range upper bound|Comparison method
|
||||
If test 1 passes but test 2 fails, call this special ...
|
||||
Range lower bound (or value to compare to)
|
||||
Range upper bound (or comparison method -2 .. 2)
|
||||
Range lower bound|Value to compare to
|
||||
Range upper bound|Comparison method
|
||||
If test 2 passes but test 1 fails, call this special ...
|
||||
Otherwise call this special
|
||||
|
||||
|
@@ -231,7 +231,7 @@ Type of trap
|
||||
Trap severity (0 .. 3)
|
||||
Animation Loops (-2 for infinite)
|
||||
Penalty (0 .. 100, higher is harder)
|
||||
(Custom only) Special node for effect
|
||||
Unused|Special node for effect
|
||||
Animation FPS (-1 for default 2)
|
||||
Special after trap finished
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_AFFECT{eSpecType::SELECT_TARGET, eSpecType::UNSTORE_PC};
|
||||
@@ -15,7 +16,10 @@ namespace {
|
||||
.msg()
|
||||
.ex1a(STRT_TARG_TYPE)
|
||||
.ex1b(eSpecPicker::NODE)
|
||||
.ex2a(STRT_TARG_MODE);
|
||||
.ex2a(STRT_TARG_MODE)
|
||||
.when(eSpecField::EX2A == 2, 1)
|
||||
.ex2b()
|
||||
.end();
|
||||
node_properties_t S_DAMAGE = node_builder_t(eSpecType::DAMAGE)
|
||||
.msg()
|
||||
.ex2b(eSpecPicker::DAMAGE_TYPE)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_COND{eSpecType::IF_SDF, eSpecType::IF_QUEST};
|
||||
@@ -111,10 +112,14 @@ namespace {
|
||||
.msg1(+eSpecPicker::MSG_SINGLE)
|
||||
.pict(STRT_CMP_MODE)
|
||||
.ptyp(eSpecPicker::NODE)
|
||||
.ex1b(STRT_CMP)
|
||||
.ex1c(eSpecPicker::NODE)
|
||||
.ex2b(STRT_CMP)
|
||||
.ex2c(eSpecPicker::NODE);
|
||||
.ex2c(eSpecPicker::NODE)
|
||||
.when(eSpecField::PICT == 2, 1)
|
||||
.ex1a()
|
||||
.ex1b(STRT_CMP)
|
||||
.ex2a()
|
||||
.ex2b(STRT_CMP)
|
||||
.end();
|
||||
node_properties_t S_BOAT = node_builder_t(eSpecType::IF_IN_BOAT)
|
||||
.ex1b(STRT_BOAT)
|
||||
.ex1c(eSpecPicker::NODE);
|
||||
|
98
src/scenario/special-conditions.hpp
Normal file
98
src/scenario/special-conditions.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// special-conditions.hpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 2025-03-06.
|
||||
//
|
||||
|
||||
#ifndef BOE_DATA_SPECIAL_COND_H
|
||||
#define BOE_DATA_SPECIAL_COND_H
|
||||
|
||||
struct node_literal_t {
|
||||
using value_type = short;
|
||||
short operator()(const cSpecial&) const { return value; }
|
||||
node_literal_t(short v) : value(v) {}
|
||||
private:
|
||||
short value;
|
||||
};
|
||||
|
||||
struct node_value_t {
|
||||
using value_type = eSpecField;
|
||||
short operator()(const cSpecial& spec) const { return spec->*field; }
|
||||
node_value_t(eSpecField fld) : field(fld) {}
|
||||
private:
|
||||
eSpecField field;
|
||||
};
|
||||
|
||||
template<template<class> class P, typename A, typename B>
|
||||
struct node_comparison_t {
|
||||
static const bool node_expr = true;
|
||||
bool operator()(const cSpecial& spec) const {
|
||||
short a = lhs(spec), b = rhs(spec);
|
||||
return pred(a, b);
|
||||
}
|
||||
node_comparison_t(A a, B b, P<short> p) : lhs(a), rhs(b), pred(p) {}
|
||||
private:
|
||||
A lhs;
|
||||
B rhs;
|
||||
P<short> pred;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct node_logic_t {
|
||||
static const bool node_expr = true;
|
||||
bool operator()(const cSpecial& spec) const {
|
||||
return conjunct ? (a(spec) && b(spec)) : (a(spec) || b(spec));
|
||||
}
|
||||
node_logic_t(A a, B b, bool conj) : a(a), b(b), conjunct(conj) {}
|
||||
private:
|
||||
A a;
|
||||
B b;
|
||||
bool conjunct;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct node_negate_t {
|
||||
static const bool node_expr = true;
|
||||
bool operator()(const cSpecial& spec) const {
|
||||
return !pred(spec);
|
||||
}
|
||||
node_negate_t(T p) : pred(p) {}
|
||||
private:
|
||||
T pred;
|
||||
};
|
||||
|
||||
#define DEFINE_CMP(LHS, RHS, OP, OP_NAME) \
|
||||
inline node_comparison_t<std::OP_NAME, LHS, RHS> operator OP(LHS::value_type a, RHS::value_type b) { \
|
||||
return node_comparison_t<std::OP_NAME, LHS, RHS>{ \
|
||||
LHS{a}, \
|
||||
RHS{b}, \
|
||||
std::OP_NAME<short>() \
|
||||
}; \
|
||||
}
|
||||
#define DEFINE_CMPS(OP, OP_NAME) \
|
||||
DEFINE_CMP(node_value_t, node_literal_t, OP, OP_NAME); \
|
||||
DEFINE_CMP(node_literal_t, node_value_t, OP, OP_NAME);
|
||||
DEFINE_CMPS(==, equal_to);
|
||||
DEFINE_CMPS(<=, less_equal);
|
||||
DEFINE_CMPS(>=, greater_equal);
|
||||
DEFINE_CMPS(!=, not_equal_to);
|
||||
DEFINE_CMPS(<, less);
|
||||
DEFINE_CMPS(>, greater);
|
||||
#undef DEFINE_CMP
|
||||
#undef DEFINE_CMPS
|
||||
|
||||
template<typename A, typename B>
|
||||
inline node_logic_t<A, B> operator&&(typename std::enable_if<A::node_expr, A>::type a, typename std::enable_if<B::node_expr, B>::type b) {
|
||||
return node_logic_t<A, B>{a, b, true};
|
||||
}
|
||||
template<typename A, typename B>
|
||||
inline node_logic_t<A, B> operator||(typename std::enable_if<A::node_expr, A>::type a, typename std::enable_if<B::node_expr, B>::type b) {
|
||||
return node_logic_t<A, B>{a, b, false};
|
||||
}
|
||||
template<typename T>
|
||||
inline node_negate_t<T> operator!(typename std::enable_if<T::node_expr, T>::type v) {
|
||||
return node_negate_t<T>{v};
|
||||
};
|
||||
|
||||
#endif
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_GENERAL{eSpecType::NONE, eSpecType::STR_BUF_TO_SIGN};
|
||||
@@ -47,7 +48,9 @@ namespace{
|
||||
node_properties_t S_PREVENT = node_builder_t(eSpecType::CANT_ENTER)
|
||||
.msg()
|
||||
.ex1a(eSpecPicker::TOGGLE)
|
||||
.ex2a(eSpecPicker::TOGGLE);
|
||||
.when(eSpecField::EX1A < 1, 1)
|
||||
.ex2a(eSpecPicker::TOGGLE)
|
||||
.end();
|
||||
node_properties_t S_TIME = node_builder_t(eSpecType::CHANGE_TIME)
|
||||
.msg();
|
||||
node_properties_t S_TIMER = node_builder_t(eSpecType::SCEN_TIMER_START)
|
||||
@@ -103,8 +106,18 @@ namespace{
|
||||
.msg1(+eSpecPicker::MSG_SINGLE)
|
||||
.ex2a(eSpecPicker::TOGGLE);
|
||||
node_properties_t S_DEBUG = node_builder_t(eSpecType::PRINT_NUMS)
|
||||
.sdf()
|
||||
.pict(STRT_DEBUG_PRINT);
|
||||
.pict(STRT_DEBUG_PRINT)
|
||||
.when(eSpecField::PICT == 0, 1)
|
||||
.sdf()
|
||||
.end()
|
||||
.when(eSpecField::PICT == 1, 1)
|
||||
.ex1a()
|
||||
.ex1b()
|
||||
.ex1c()
|
||||
.end()
|
||||
.when(eSpecField::PICT == 2, 2)
|
||||
.ex1a()
|
||||
.end();
|
||||
node_properties_t S_MULFLAG = node_builder_t(eSpecType::SDF_TIMES)
|
||||
.sdf()
|
||||
.msg();
|
||||
@@ -151,7 +164,13 @@ namespace{
|
||||
node_properties_t S_QUEST = node_builder_t(eSpecType::UPDATE_QUEST)
|
||||
.msg()
|
||||
.ex1a(STRT_QUEST)
|
||||
.ex1b(STRT_QUEST_STATUS);
|
||||
.ex1b(STRT_QUEST_STATUS)
|
||||
.when(eSpecField::EX1B == 1, 1)
|
||||
.ex2a(eSpecPicker::JOB_BOARD)
|
||||
.end()
|
||||
.when(eSpecField::EX1B == 3, 2)
|
||||
.ex2a()
|
||||
.end();
|
||||
node_properties_t S_BUF_SWAP = node_builder_t(eSpecType::SWAP_STR_BUF)
|
||||
.msg();
|
||||
node_properties_t S_ALTER_SIGN = node_builder_t(eSpecType::STR_BUF_TO_SIGN)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_ONCE{eSpecType::ONCE_GIVE_ITEM, eSpecType::ONCE_TRAP};
|
||||
@@ -55,5 +56,7 @@ namespace {
|
||||
.msg()
|
||||
.pic()
|
||||
.ex1a(STRT_TRAP)
|
||||
.ex2b(+eSpecPicker::NODE);
|
||||
.when(eSpecField::EX1A == 13, 1)
|
||||
.ex2b(+eSpecPicker::NODE)
|
||||
.end();
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_OUTD{eSpecType::OUT_MAKE_WANDER, eSpecType::OUT_MOVE_PARTY};
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_RECT{eSpecType::RECT_PLACE_FIELD, eSpecType::RECT_UNLOCK};
|
||||
|
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#include "special.hpp"
|
||||
#include "special-conditions.hpp"
|
||||
|
||||
// Note: If adding a new node type below, be sure to adjust the end point here too.
|
||||
node_category_info_t CAT_TOWN{eSpecType::MAKE_TOWN_HOSTILE, eSpecType::TOWN_PLACE_LABEL};
|
||||
|
@@ -584,37 +584,36 @@ std::string node_properties_t::opcode() const {
|
||||
return get_str("specials-opcodes", int(self));
|
||||
}
|
||||
|
||||
static std::string get_node_string(std::string base, eSpecType type, int which) {
|
||||
static std::string get_node_string(std::string base, eSpecType type, int which, int sect) {
|
||||
eSpecCat cat = getNodeCategory(type);
|
||||
int offset = int((*cat).first), i = int(type);
|
||||
int strnum = (i - offset) * 17 + which + 1;
|
||||
switch(cat) {
|
||||
case eSpecCat::GENERAL:
|
||||
return get_str(base + "-general", strnum);
|
||||
case eSpecCat::ONCE:
|
||||
return get_str(base + "-once", strnum);
|
||||
case eSpecCat::AFFECT:
|
||||
return get_str(base + "-affect", strnum);
|
||||
case eSpecCat::IF_THEN:
|
||||
return get_str(base + "-ifthen", strnum);
|
||||
case eSpecCat::TOWN:
|
||||
return get_str(base + "-town", strnum);
|
||||
case eSpecCat::RECT:
|
||||
return get_str(base + "-rect", strnum);
|
||||
case eSpecCat::OUTDOOR:
|
||||
return get_str(base + "-outdoor", strnum);
|
||||
case eSpecCat::INVALID:
|
||||
return "error";
|
||||
case eSpecCat::GENERAL: base += "-general"; break;
|
||||
case eSpecCat::ONCE: base += "-once"; break;
|
||||
case eSpecCat::AFFECT: base += "-affect"; break;
|
||||
case eSpecCat::IF_THEN: base += "-ifthen"; break;
|
||||
case eSpecCat::TOWN: base += "-town"; break;
|
||||
case eSpecCat::RECT: base += "-rect"; break;
|
||||
case eSpecCat::OUTDOOR: base += "-outdoor"; break;
|
||||
case eSpecCat::INVALID: return "error";
|
||||
}
|
||||
return "";
|
||||
std::string str = get_str(base, strnum);
|
||||
if(sect < 0) return str;
|
||||
size_t start = 0, end = str.find_first_of('|');
|
||||
while(sect --> 0 && end != std::string::npos) {
|
||||
start = end + 1;
|
||||
end = str.find_first_of('|', end + 1);
|
||||
}
|
||||
return str.substr(start, end - start);
|
||||
}
|
||||
|
||||
std::string node_properties_t::name() const {
|
||||
return get_node_string("specials-text", self, 0);
|
||||
return get_node_string("specials-text", self, 0, -1);
|
||||
}
|
||||
|
||||
std::string node_properties_t::descr() const {
|
||||
return get_node_string("specials-text", self, 15);
|
||||
return get_node_string("specials-text", self, 15, -1);
|
||||
}
|
||||
|
||||
node_function_t::node_function_t() {}
|
||||
@@ -670,10 +669,16 @@ node_function_t operator+(eSpecPicker picker) {
|
||||
}
|
||||
|
||||
std::string node_function_t::label() const {
|
||||
return get_node_string("specials-text", self, lbl_idx);
|
||||
return get_node_string("specials-text", self, lbl_idx, sub_idx);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::get(eSpecField fld) const {
|
||||
node_function_t node_properties_t::get(const cSpecial& spec, eSpecField fld) const {
|
||||
for(const auto& cond : conditions) {
|
||||
if(cond.first(spec)) {
|
||||
auto iter = cond.second.fields.find(fld);
|
||||
if(iter != cond.second.fields.end()) return iter->second;
|
||||
}
|
||||
}
|
||||
auto iter = fields.find(fld);
|
||||
if(iter != fields.end()) return iter->second;
|
||||
static node_function_t nil_fcn;
|
||||
@@ -688,60 +693,60 @@ void node_properties_t::set(eSpecField fld, node_function_t fcn) {
|
||||
fields[fld] = fcn;
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::sdf1(const cSpecial&) const {
|
||||
return get(eSpecField::SDF1);
|
||||
node_function_t node_properties_t::sdf1(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::SDF1);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::sdf2(const cSpecial&) const {
|
||||
return get(eSpecField::SDF2);
|
||||
node_function_t node_properties_t::sdf2(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::SDF2);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::msg1(const cSpecial&) const {
|
||||
return get(eSpecField::MSG1);
|
||||
node_function_t node_properties_t::msg1(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::MSG1);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::msg2(const cSpecial&) const {
|
||||
return get(eSpecField::MSG2);
|
||||
node_function_t node_properties_t::msg2(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::MSG2);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::msg3(const cSpecial&) const {
|
||||
return get(eSpecField::MSG3);
|
||||
node_function_t node_properties_t::msg3(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::MSG3);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::pic(const cSpecial&) const {
|
||||
return get(eSpecField::PICT);
|
||||
node_function_t node_properties_t::pic(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::PICT);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::pictype(const cSpecial&) const {
|
||||
return get(eSpecField::PTYP);
|
||||
node_function_t node_properties_t::pictype(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::PTYP);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex1a(const cSpecial&) const {
|
||||
return get(eSpecField::EX1A);
|
||||
node_function_t node_properties_t::ex1a(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX1A);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex1b(const cSpecial&) const {
|
||||
return get(eSpecField::EX1B);
|
||||
node_function_t node_properties_t::ex1b(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX1B);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex1c(const cSpecial&) const {
|
||||
return get(eSpecField::EX1C);
|
||||
node_function_t node_properties_t::ex1c(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX1C);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex2a(const cSpecial&) const {
|
||||
return get(eSpecField::EX2A);
|
||||
node_function_t node_properties_t::ex2a(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX2A);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex2b(const cSpecial&) const {
|
||||
return get(eSpecField::EX2B);
|
||||
node_function_t node_properties_t::ex2b(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX2B);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::ex2c(const cSpecial&) const {
|
||||
return get(eSpecField::EX2C);
|
||||
node_function_t node_properties_t::ex2c(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::EX2C);
|
||||
}
|
||||
|
||||
node_function_t node_properties_t::jump(const cSpecial&) const {
|
||||
return get(eSpecField::JUMP);
|
||||
node_function_t node_properties_t::jump(const cSpecial& spec) const {
|
||||
return get(spec, eSpecField::JUMP);
|
||||
}
|
||||
|
||||
struct field_map {
|
||||
@@ -763,9 +768,9 @@ struct field_map {
|
||||
};
|
||||
};
|
||||
|
||||
static field_map& fields() {
|
||||
short operator->*(const cSpecial& spec, eSpecField fld) {
|
||||
static field_map map;
|
||||
return map;
|
||||
return spec.*map.map[fld];
|
||||
}
|
||||
|
||||
node_builder_t& node_builder_t::sdf() {
|
||||
@@ -872,3 +877,139 @@ node_builder_t::operator node_properties_t() {
|
||||
allNodeProps.emplace(node.self, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
node_condition_builder_t node_builder_t::when(node_condition_t cond, int lbl_sub) {
|
||||
return node_condition_builder_t(*this, cond, lbl_sub);
|
||||
}
|
||||
|
||||
node_condition_builder_t::node_condition_builder_t(node_builder_t& parent, node_condition_t cond, int sub)
|
||||
: cond(cond)
|
||||
, self(parent.node.self)
|
||||
, parent(parent)
|
||||
, sub(sub)
|
||||
{
|
||||
self.node.fields.clear();
|
||||
}
|
||||
|
||||
node_builder_t& node_condition_builder_t::end() {
|
||||
for(auto& field : self.node.fields) {
|
||||
field.second.sub_idx = sub;
|
||||
}
|
||||
parent.node.conditions.emplace_back(cond, self.node);
|
||||
return parent;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::field(eSpecField field, node_function_t picker) {
|
||||
self.field(field, picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::field_pair(eSpecField main, eSpecField extra, node_function_t picker) {
|
||||
self.field_pair(main, extra, picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::sdf1(node_function_t picker) {
|
||||
self.sdf1(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::sdf2(node_function_t picker) {
|
||||
self.sdf2(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::jump(node_function_t picker) {
|
||||
self.jump(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::msg1(node_function_t picker) {
|
||||
self.msg1(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::msg2(node_function_t picker) {
|
||||
self.msg2(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::msg3(node_function_t picker) {
|
||||
self.msg3(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::pict(node_function_t picker) {
|
||||
self.pict(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ptyp(node_function_t picker) {
|
||||
self.ptyp(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex1a(node_function_t picker) {
|
||||
self.ex1a(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex1b(node_function_t picker) {
|
||||
self.ex1b(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex1c(node_function_t picker) {
|
||||
self.ex1c(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex2a(node_function_t picker) {
|
||||
self.ex2a(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex2b(node_function_t picker) {
|
||||
self.ex2b(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::ex2c(node_function_t picker) {
|
||||
self.ex2c(picker);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::sdf() {
|
||||
self.sdf();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::msg() {
|
||||
self.msg();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::pic() {
|
||||
self.pic();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::rect(eLocType type) {
|
||||
self.rect(type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::sdf(eSpecField a, eSpecField b) {
|
||||
self.sdf(a, b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::loc(eSpecField a, eSpecField b, eLocType type) {
|
||||
self.loc(a, b, type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_condition_builder_t& node_condition_builder_t::loc(eSpecField a, eSpecField b, eLocType type, eSpecField where) {
|
||||
self.loc(a, b, type, where);
|
||||
return *this;
|
||||
}
|
||||
|
@@ -167,6 +167,7 @@ enum class eLocType {
|
||||
};
|
||||
|
||||
enum class eSpecField { NONE, SDF1, SDF2, MSG1, MSG2, MSG3, PICT, PTYP, EX1A, EX1B, EX1C, EX2A, EX2B, EX2C, JUMP };
|
||||
short operator->*(const cSpecial& spec, eSpecField fld);
|
||||
|
||||
struct node_function_t {
|
||||
eSpecPicker button = eSpecPicker::NONE;
|
||||
@@ -194,10 +195,13 @@ private:
|
||||
bool needs_split = false;
|
||||
friend struct node_builder_t;
|
||||
friend struct node_properties_t;
|
||||
friend struct node_condition_builder_t;
|
||||
};
|
||||
|
||||
node_function_t operator+(eSpecPicker);
|
||||
|
||||
using node_condition_t = std::function<bool(const cSpecial&)>;
|
||||
|
||||
struct node_properties_t {
|
||||
eSpecType self;
|
||||
eSpecCat cat;
|
||||
@@ -211,16 +215,20 @@ struct node_properties_t {
|
||||
node_properties_t() : node_properties_t(eSpecType::INVALID) {}
|
||||
private:
|
||||
node_properties_t(eSpecType type);
|
||||
node_function_t get(eSpecField fld) const;
|
||||
node_function_t get(const cSpecial& spec, eSpecField fld) const;
|
||||
void set(eSpecField fld, node_function_t fcn);
|
||||
std::map<eSpecField, node_function_t> fields;
|
||||
std::vector<std::pair<node_condition_t, node_properties_t>> conditions;
|
||||
friend struct node_builder_t;
|
||||
friend struct node_condition_builder_t;
|
||||
friend struct field_map;
|
||||
};
|
||||
|
||||
const node_properties_t& operator* (eSpecType t);
|
||||
const node_category_info_t& operator* (eSpecCat t);
|
||||
|
||||
struct node_condition_builder_t;
|
||||
|
||||
// Builds the information needed to display the correct buttons when editing a special node.
|
||||
struct node_builder_t {
|
||||
node_builder_t(eSpecType type) : node(type) {}
|
||||
@@ -259,9 +267,45 @@ struct node_builder_t {
|
||||
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);
|
||||
node_condition_builder_t when(node_condition_t cond, int lbl_sub);
|
||||
operator node_properties_t();
|
||||
private:
|
||||
node_properties_t node;
|
||||
friend struct node_condition_builder_t;
|
||||
};
|
||||
|
||||
struct node_condition_builder_t {
|
||||
node_builder_t& end();
|
||||
node_condition_builder_t& field(eSpecField field, node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& field_pair(eSpecField main, eSpecField extra, node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& sdf1(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& sdf2(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& jump(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& msg1(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& msg2(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& msg3(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& pict(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ptyp(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex1a(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex1b(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex1c(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex2a(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex2b(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& ex2c(node_function_t picker = eSpecPicker::NONE);
|
||||
node_condition_builder_t& sdf();
|
||||
node_condition_builder_t& msg();
|
||||
node_condition_builder_t& pic();
|
||||
node_condition_builder_t& rect(eLocType type);
|
||||
node_condition_builder_t& sdf(eSpecField a, eSpecField b);
|
||||
node_condition_builder_t& loc(eSpecField a, eSpecField b, eLocType type);
|
||||
node_condition_builder_t& loc(eSpecField a, eSpecField b, eLocType type, eSpecField where);
|
||||
private:
|
||||
node_condition_builder_t(node_builder_t& parent, node_condition_t cond, int sub);
|
||||
node_condition_t cond;
|
||||
node_builder_t self;
|
||||
node_builder_t& parent;
|
||||
int sub;
|
||||
friend class node_builder_t;
|
||||
};
|
||||
|
||||
// An overview of how the builder works.
|
||||
|
@@ -1273,6 +1273,9 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
|
||||
case eSpecPicker::NONE: return false;
|
||||
}
|
||||
me[field].setTextToNum(store);
|
||||
// Field labels might need to change, so refresh them
|
||||
save_spec_enc(me, edit_stack);
|
||||
put_spec_enc_in_dlog(me, edit_stack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1321,6 +1324,17 @@ bool edit_spec_enc(short which_node,short mode,cDialog* parent) {
|
||||
"x1a-toggle", "x1b-toggle", "x1c-toggle", "x2a-toggle", "x2b-toggle", "x2c-toggle",
|
||||
"sdf1-toggle", "sdf2-toggle",
|
||||
});
|
||||
special.attachFocusHandlers([&edit_stack](cDialog& me, std::string, bool losing) {
|
||||
if(losing) {
|
||||
save_spec_enc(me, edit_stack);
|
||||
put_spec_enc_in_dlog(me, edit_stack);
|
||||
}
|
||||
return true;
|
||||
}, {
|
||||
"msg1", "msg2", "msg3", "pict", "pictype", "jump",
|
||||
"x1a", "x1b", "x1c", "x2a", "x2b", "x2c",
|
||||
"sdf1", "sdf2",
|
||||
});
|
||||
special["cancel"].attachClickHandler(std::bind(discard_spec_enc, _1, std::ref(edit_stack)));
|
||||
special["node-help"].attachClickHandler([&edit_stack](cDialog& me, std::string item_hit, eKeyMod mods) {
|
||||
eSpecType type = edit_stack.top().node.type;
|
||||
|
Reference in New Issue
Block a user