add the capacity to have variables automatically set in WML
* all SUF now can access the filtered unit via * events can access and the same way
This commit is contained in:
parent
8ab001268e
commit
3d86ca3575
6 changed files with 150 additions and 18 deletions
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define ERR_CF LOG_STREAM(err, config)
|
||||
|
||||
config::config(const config& cfg)
|
||||
config::config(const config& cfg):variable_set()
|
||||
{
|
||||
append(cfg);
|
||||
}
|
||||
|
@ -649,6 +649,60 @@ void config::debug() const{
|
|||
i--;
|
||||
}
|
||||
|
||||
const t_string& config::get_variable_const(const std::string& key)
|
||||
{
|
||||
const std::string::const_iterator itor = std::find(key.begin(),key.end(),'.');
|
||||
size_t MaxLoop= 1024;
|
||||
if(itor != key.end()) {
|
||||
std::string element(key.begin(),itor);
|
||||
std::string sub_key(itor+1,key.end());
|
||||
|
||||
size_t index = 0;
|
||||
const std::string::iterator index_start = std::find(element.begin(),element.end(),'[');
|
||||
const bool explicit_index = index_start != element.end();
|
||||
|
||||
if(explicit_index) {
|
||||
const std::string::iterator index_end = std::find(index_start,element.end(),']');
|
||||
const std::string index_str(index_start+1,index_end);
|
||||
index = size_t(atoi(index_str.c_str()));
|
||||
if(index > MaxLoop) {
|
||||
index = MaxLoop;
|
||||
}
|
||||
|
||||
element = std::string(element.begin(),index_start);
|
||||
}
|
||||
|
||||
const config::child_list& items = get_children(element);
|
||||
|
||||
//special case -- '.length' on an array returns the size of the array
|
||||
if(explicit_index == false && sub_key == "length") {
|
||||
static t_string zero_str = "0";
|
||||
if(items.empty()) {
|
||||
return zero_str;
|
||||
} else {
|
||||
int size = minimum<int>(MaxLoop,int(items.size()));
|
||||
(*items.back())["__length"] = lexical_cast<std::string>(size);
|
||||
|
||||
return (*items.back())["__length"];
|
||||
}
|
||||
}
|
||||
|
||||
while(get_children(element).size() <= index) {
|
||||
add_child(element);
|
||||
}
|
||||
return (*get_children(element)[index]).get_variable_const(sub_key);
|
||||
} else {
|
||||
if(values.find(key) != values.end()){
|
||||
return values.find(key)->second;
|
||||
}else {
|
||||
static t_string empty = "";
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string config::hash() const
|
||||
{
|
||||
static const unsigned int hash_length = 128;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "tstring.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
||||
//This module defines the interface to Wesnoth Markup Language (WML).
|
||||
//WML is a simple hierarchical text-based file format. The format
|
||||
|
@ -32,7 +33,7 @@ typedef std::map<std::string,t_string> string_map;
|
|||
|
||||
//a config object defines a single node in a WML file, with access to
|
||||
//child nodes.
|
||||
class config
|
||||
class config: public variable_set
|
||||
{
|
||||
public:
|
||||
//create an empty node.
|
||||
|
@ -141,6 +142,9 @@ public:
|
|||
//resets the translated values of all strings contained in this object
|
||||
void reset_translation() const;
|
||||
|
||||
// allow any WML to be used to interpolate variables
|
||||
const t_string& get_variable_const(const std::string& id) ;
|
||||
|
||||
//all the attributes of this node.
|
||||
string_map values;
|
||||
|
||||
|
|
|
@ -278,6 +278,9 @@ public:
|
|||
|
||||
bool& rebuild_screen() {return rebuild_screen_;}
|
||||
|
||||
void add_event_var(const unit* primary_unit, const unit* secondary_unit=NULL);
|
||||
void rem_event_var();
|
||||
|
||||
private:
|
||||
bool handle_event_command(const queued_event& event_info, const std::string& cmd, const vconfig cfg, bool& mutated);
|
||||
|
||||
|
@ -288,6 +291,26 @@ private:
|
|||
vconfig cfg_;
|
||||
};
|
||||
|
||||
void event_handler::add_event_var(const unit* primary_unit, const unit* secondary_unit)
|
||||
{
|
||||
if(primary_unit) {
|
||||
config tmp_cfg;
|
||||
primary_unit->write(tmp_cfg);
|
||||
cfg_.add_local_var("_primary_unit",tmp_cfg);
|
||||
}
|
||||
if(secondary_unit) {
|
||||
config tmp_cfg;
|
||||
secondary_unit->write(tmp_cfg);
|
||||
cfg_.add_local_var("_secondary_unit",tmp_cfg);
|
||||
}
|
||||
|
||||
}
|
||||
void event_handler::rem_event_var()
|
||||
{
|
||||
cfg_.rem_local_var("_primary_unit");
|
||||
cfg_.rem_local_var("_secondary_unit");
|
||||
}
|
||||
|
||||
gamemap::location cfg_to_loc(const vconfig cfg,int defaultx = 0, int defaulty = 0)
|
||||
{
|
||||
int x = lexical_cast_default(cfg["x"], defaultx) - 1;
|
||||
|
@ -2038,13 +2061,24 @@ bool process_event(event_handler& handler, const queued_event& ev)
|
|||
|
||||
unit_map::iterator unit1 = units->find(ev.loc1);
|
||||
unit_map::iterator unit2 = units->find(ev.loc2);
|
||||
unit* tmp_unit1 = NULL;
|
||||
unit* tmp_unit2 = NULL;
|
||||
if(unit1!= units->end()) {
|
||||
tmp_unit1 = &(unit1->second);
|
||||
}
|
||||
if(unit2!= units->end()) {
|
||||
tmp_unit2 = &(unit2->second);
|
||||
}
|
||||
handler.add_event_var(tmp_unit1,tmp_unit2);
|
||||
|
||||
|
||||
const vconfig::child_list first_filters = handler.first_arg_filters();
|
||||
vconfig::child_list::const_iterator ffi;
|
||||
for(ffi = first_filters.begin();
|
||||
ffi != first_filters.end(); ++ffi) {
|
||||
ffi != first_filters.end(); ++ffi) {
|
||||
|
||||
if(unit1 == units->end() || !game_events::unit_matches_filter(unit1,*ffi)) {
|
||||
handler.rem_event_var();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2052,33 +2086,36 @@ bool process_event(event_handler& handler, const queued_event& ev)
|
|||
const vconfig::child_list first_special_filters = handler.first_special_filters();
|
||||
special_matches = first_special_filters.size() ? false : true;
|
||||
for(ffi = first_special_filters.begin();
|
||||
ffi != first_special_filters.end(); ++ffi) {
|
||||
ffi != first_special_filters.end(); ++ffi) {
|
||||
|
||||
if(unit1 != units->end() && game_events::matches_special_filter(ev.data.child("first"),*ffi)) {
|
||||
special_matches = true;
|
||||
}
|
||||
}
|
||||
if(!special_matches) {
|
||||
handler.rem_event_var();
|
||||
return false;
|
||||
}
|
||||
|
||||
const vconfig::child_list second_filters = handler.second_arg_filters();
|
||||
for(vconfig::child_list::const_iterator sfi = second_filters.begin();
|
||||
sfi != second_filters.end(); ++sfi) {
|
||||
sfi != second_filters.end(); ++sfi) {
|
||||
if(unit2 == units->end() || !game_events::unit_matches_filter(unit2,*sfi)) {
|
||||
handler.rem_event_var();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const vconfig::child_list second_special_filters = handler.second_special_filters();
|
||||
special_matches = second_special_filters.size() ? false : true;
|
||||
for(ffi = second_special_filters.begin();
|
||||
ffi != second_special_filters.end(); ++ffi) {
|
||||
ffi != second_special_filters.end(); ++ffi) {
|
||||
|
||||
if(unit2 != units->end() && game_events::matches_special_filter(ev.data.child("second"),*ffi)) {
|
||||
special_matches = true;
|
||||
}
|
||||
}
|
||||
if(!special_matches) {
|
||||
handler.rem_event_var();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2096,6 +2133,7 @@ bool process_event(event_handler& handler, const queued_event& ev)
|
|||
handler.disable();
|
||||
}
|
||||
|
||||
handler.rem_event_var();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "game_events.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "sdl_utils.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
|
@ -880,8 +881,13 @@ bool unit::has_ability_by_id(const std::string& ability) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool unit::matches_filter(const config& cfg,const gamemap::location& loc,bool use_flat_tod) const
|
||||
bool unit::matches_filter(const config& orig_cfg,const gamemap::location& loc,bool use_flat_tod) const
|
||||
{
|
||||
vconfig tmp_vconf(&orig_cfg);
|
||||
config tmp_unit;
|
||||
write(tmp_unit);
|
||||
tmp_vconf.add_local_var("_filtered_unit",tmp_unit);
|
||||
config cfg = tmp_vconf.get_parsed_config();
|
||||
const std::string& description = cfg["description"];
|
||||
const std::string& speaker = cfg["speaker"];
|
||||
const std::string& type = cfg["type"];
|
||||
|
|
|
@ -71,8 +71,11 @@ const config vconfig::get_parsed_config() const
|
|||
|
||||
for(config::all_children_iterator child = cfg_->ordered_begin();
|
||||
child != cfg_->ordered_end(); ++child) {
|
||||
vconfig tmp_vconf= (*child).second;
|
||||
tmp_vconf.local_vars_ = local_vars_;
|
||||
|
||||
res.add_child(*(*child).first, vconfig((*child).second).get_parsed_config());
|
||||
|
||||
res.add_child(*(*child).first, tmp_vconf.get_parsed_config());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -82,35 +85,59 @@ vconfig::child_list vconfig::get_children(const std::string& key) const
|
|||
const config::child_list& list = cfg_->get_children(key);
|
||||
vconfig::child_list res(list.size());
|
||||
std::copy(list.begin(), list.end(),res.begin());
|
||||
for(vconfig::child_list::iterator itor = res.begin(); itor != res.end() ;itor++) {
|
||||
itor->local_vars_ = local_vars_;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vconfig vconfig::child(const std::string& key) const
|
||||
{
|
||||
return vconfig(cfg_->child(key));
|
||||
vconfig tmp = cfg_->child(key);
|
||||
tmp.local_vars_ = local_vars_;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const t_string& vconfig::operator[](const std::string& key) const
|
||||
const t_string vconfig::operator[](const std::string& key) const
|
||||
{
|
||||
return expand(key);
|
||||
}
|
||||
|
||||
const t_string& vconfig::expand(const std::string& key) const
|
||||
const t_string vconfig::expand(const std::string& key) const
|
||||
{
|
||||
const t_string& val = (*cfg_)[key];
|
||||
|
||||
if(repos != NULL && !val.str().empty() && val.str()[0] == '$') {
|
||||
return repos->get_variable(val.str().substr(1));
|
||||
if(!val.str().empty() && val.str()[0] == '$') {
|
||||
std::string tmp = val.str();
|
||||
// stupid const
|
||||
config grr = local_vars_;
|
||||
// first expand local variables
|
||||
tmp = utils::interpolate_variables_into_string(val.str(),grr);
|
||||
if(tmp.empty()) tmp = val.str();
|
||||
// now expand global variables
|
||||
if(repos != NULL && !tmp.empty() && tmp[0] == '$') {
|
||||
tmp = repos->get_variable(tmp.substr(1));
|
||||
if(tmp.empty()) tmp = val.str();
|
||||
}
|
||||
return tmp;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
const t_string& vconfig::get_attribute(const std::string& key) const
|
||||
const t_string vconfig::get_attribute(const std::string& key) const
|
||||
{
|
||||
return (*cfg_)[key];
|
||||
}
|
||||
|
||||
void vconfig::add_local_var(std::string var_name, config& var)
|
||||
{
|
||||
local_vars_.add_child(var_name,var);
|
||||
}
|
||||
void vconfig::rem_local_var(std::string var_name)
|
||||
{
|
||||
local_vars_.clear_children(var_name);
|
||||
}
|
||||
namespace variable
|
||||
{
|
||||
manager::manager(game_state* repository)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class config;
|
||||
#include "config.hpp"
|
||||
class t_string;
|
||||
struct game_state;
|
||||
|
||||
|
@ -43,12 +43,15 @@ public:
|
|||
child_list get_children(const std::string& key) const;
|
||||
vconfig child(const std::string& key) const;
|
||||
|
||||
const t_string& operator[](const std::string&) const;
|
||||
const t_string& expand(const std::string&) const; /** < Synonym for operator[] */
|
||||
const t_string& get_attribute(const std::string&) const;
|
||||
const t_string operator[](const std::string&) const;
|
||||
const t_string expand(const std::string&) const; /** < Synonym for operator[] */
|
||||
const t_string get_attribute(const std::string&) const;
|
||||
void add_local_var(std::string var_name, config& var);
|
||||
void rem_local_var(std::string var_name);
|
||||
|
||||
private:
|
||||
const config* cfg_;
|
||||
config local_vars_;
|
||||
};
|
||||
|
||||
namespace variable
|
||||
|
|
Loading…
Add table
Reference in a new issue