Support multiple super tags and even conditional super tags
Use this to conditionally import [unit] keys in [side] based on no_leader
This commit is contained in:
parent
7fc359bf16
commit
bebab878e3
4 changed files with 56 additions and 40 deletions
|
@ -17,8 +17,14 @@
|
|||
[tag]
|
||||
name="$side"
|
||||
max=0
|
||||
# TODO: This superclass should only be used if no_leader=no
|
||||
super="units/$unit"
|
||||
[if]
|
||||
[not]
|
||||
no_leader=yes
|
||||
[/not]
|
||||
[then]
|
||||
super="units/$unit"
|
||||
[/then]
|
||||
[/if]
|
||||
{DEFAULT_KEY no_leader bool no}
|
||||
{SIMPLE_KEY recruit string}
|
||||
{DEFAULT_KEY gold int 100}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
key=apply_to
|
||||
[case]
|
||||
value=new_attack
|
||||
super="units/unit_type/attack"
|
||||
super="units/unit_type~core/attack"
|
||||
[/case]
|
||||
{FILTER_TAG "case" weapon value=remove_attacks}
|
||||
{FILTER_TAG "case" weapon (
|
||||
|
|
|
@ -215,13 +215,13 @@ void class_tag::add_link(const std::string& link)
|
|||
links_.emplace(name_link, link);
|
||||
}
|
||||
|
||||
const class_key* class_tag::find_key(const std::string& name, const config& match) const
|
||||
const class_key* class_tag::find_key(const std::string& name, const config& match, bool ignore_super) const
|
||||
{
|
||||
// Check the conditions first, so that conditional definitions
|
||||
// override base definitions in the event of duplicates.
|
||||
for(auto& cond : conditions_) {
|
||||
if(cond.matches(match)) {
|
||||
if(auto key = cond.find_key(name, match)) {
|
||||
if(auto key = cond.find_key(name, match, true)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
@ -241,6 +241,23 @@ const class_key* class_tag::find_key(const std::string& name, const config& matc
|
|||
if(it_fuzzy != keys_.end()) {
|
||||
return &(it_fuzzy->second);
|
||||
}
|
||||
|
||||
if(!ignore_super) {
|
||||
for(auto& cond : conditions_) {
|
||||
if(cond.matches(match)) {
|
||||
// This results in a little redundancy (checking things twice) but at least it still works.
|
||||
if(auto key = cond.find_key(name, match, false)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto& super_tag : super_refs_) {
|
||||
if(const class_key* found_key = super_tag->find_key(name, match)) {
|
||||
return found_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -254,7 +271,7 @@ const std::string* class_tag::find_link(const std::string& name) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const class_tag* class_tag::find_tag(const std::string& fullpath, const class_tag& root, const config& match) const
|
||||
const class_tag* class_tag::find_tag(const std::string& fullpath, const class_tag& root, const config& match, bool ignore_super) const
|
||||
{
|
||||
if(fullpath.empty()) {
|
||||
return nullptr;
|
||||
|
@ -275,7 +292,7 @@ const class_tag* class_tag::find_tag(const std::string& fullpath, const class_ta
|
|||
// override base definitions in the event of duplicates.
|
||||
for(auto& cond : conditions_) {
|
||||
if(cond.matches(match)) {
|
||||
if(auto tag = cond.find_tag(fullpath, root, match)) {
|
||||
if(auto tag = cond.find_tag(fullpath, root, match, true)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
@ -309,6 +326,22 @@ const class_tag* class_tag::find_tag(const std::string& fullpath, const class_ta
|
|||
}
|
||||
}
|
||||
|
||||
if(!ignore_super) {
|
||||
for(auto& cond : conditions_) {
|
||||
if(cond.matches(match)) {
|
||||
// This results in a little redundancy (checking things twice) but at least it still works.
|
||||
if(auto tag = cond.find_tag(fullpath, root, match, false)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto& super_tag : super_refs_) {
|
||||
if(const class_tag* found_tag = super_tag->find_tag(fullpath, root, match)) {
|
||||
return found_tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(any_tag_) {
|
||||
return &any_tag;
|
||||
}
|
||||
|
@ -448,37 +481,13 @@ void class_tag::add_tag(const std::string& path, const class_tag& tag, class_tag
|
|||
it_tags->second.add_tag(next_path, tag, root);
|
||||
}
|
||||
|
||||
void class_tag::append_super(const class_tag& tag, const std::string& path)
|
||||
{
|
||||
// TODO: Ensure derived tag definitions override base tag definitions in the event of duplicates
|
||||
add_keys(tag.keys_);
|
||||
add_links(tag.links_);
|
||||
add_conditions(tag.conditions_);
|
||||
|
||||
for(const auto& t : tag.tags_) {
|
||||
links_.erase(t.first);
|
||||
if(t.second.is_fuzzy()) {
|
||||
// Fuzzy tags won't work as links, so make a copy
|
||||
// (Links just don't hold enough info for this to work.)
|
||||
add_tag(t.second);
|
||||
} else {
|
||||
add_link(path + "/" + t.first);
|
||||
}
|
||||
}
|
||||
if(tag.any_tag_) {
|
||||
any_tag_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void class_tag::expand(class_tag& root)
|
||||
{
|
||||
if(!super_.empty()) {
|
||||
class_tag* super_tag = root.find_tag(super_, root, config());
|
||||
for(auto& super : utils::split(super_)) {
|
||||
class_tag* super_tag = root.find_tag(super, root, config());
|
||||
if(super_tag) {
|
||||
if(super_tag != this) {
|
||||
super_tag->expand(root);
|
||||
append_super(*super_tag, super_);
|
||||
super_.clear();
|
||||
super_refs_.push_back(super_tag);
|
||||
} else {
|
||||
// TODO: Detect super cycles too!
|
||||
std::cerr << "the same" << super_tag->name_ << "\n";
|
||||
|
|
|
@ -256,6 +256,7 @@ public:
|
|||
using key_map = std::map<std::string, class_key>;
|
||||
using link_map = std::map<std::string, std::string>;
|
||||
using condition_list = std::vector<class_condition>;
|
||||
using super_list = std::vector<class_tag*>;
|
||||
private:
|
||||
void push_new_tag_conditions(std::queue<const class_tag*> q, const class_tag& tag);
|
||||
template<typename T, typename Map = std::map<std::string, T>>
|
||||
|
@ -478,7 +479,7 @@ public:
|
|||
}
|
||||
|
||||
/** Returns pointer to child key. */
|
||||
const class_key* find_key(const std::string& name, const config& match) const;
|
||||
const class_key* find_key(const std::string& name, const config& match, bool ignore_super = false) const;
|
||||
|
||||
/** Returns pointer to child link. */
|
||||
const std::string* find_link(const std::string& name) const;
|
||||
|
@ -487,7 +488,7 @@ public:
|
|||
* Returns pointer to tag using full path to it.
|
||||
* Also work with links
|
||||
*/
|
||||
const class_tag* find_tag(const std::string& fullpath, const class_tag& root, const config& match) const;
|
||||
const class_tag* find_tag(const std::string& fullpath, const class_tag& root, const config& match, bool ignore_super = false) const;
|
||||
|
||||
/** Calls the expansion on each child. */
|
||||
void expand_all(class_tag& root);
|
||||
|
@ -551,6 +552,9 @@ private:
|
|||
/** conditional partial matches */
|
||||
condition_list conditions_;
|
||||
|
||||
/** super-tag references */
|
||||
super_list super_refs_;
|
||||
|
||||
/** whether this is a "fuzzy" tag. */
|
||||
bool fuzzy_;
|
||||
|
||||
|
@ -591,10 +595,7 @@ private:
|
|||
conditions_.insert(conditions_.end(), list.begin(), list.end());
|
||||
}
|
||||
|
||||
/** Copies tags, keys and links of tag to this. */
|
||||
void append_super(const class_tag& tag, const std::string& super);
|
||||
|
||||
/** Expands all "super" copying their data to this. */
|
||||
/** Expands all "super", storing direct references for easier access. */
|
||||
void expand(class_tag& root);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue