/*
 * Синтаксический анализатор BB-кодов v1.1c
 * © Sir Nikolas, Май - Август 2013
 */

//===========================================================================
// Ядро анализатора - класс BbParser.
//===========================================================================

//Флаг, вызывающий прекращение разбора при получении любого предупреждения.
var BB_STRICT      = 0x1;
//Флаг, делающий анализатор нечувствительным к регистру.
var BB_INSENSITIVE = 0x2;

//Конструктор класса. Принимает битовую маску флагов.
function BbParser(flags) {
    //Флаги разбора.
    this.flags = flags || 0x0;
    //Предупреждения, полученные в ходе разбора. Обновляются при каждом вызове parse.
    this.warnings = [ ];
    //Количество вызовов метода parse с момента конструирования объекта.
    this.execCount = 0;
    //Строка, переданная методу parse.
    this.input = "";
    //Текущая позиция в строке.
    this.pos = 0;

    //Приватные члены.
    this._tagClass = [ ];
    this._tagArgs = [ ];
    this._tags = { };
    //this._banned = [ ];//Пока не поддерживается.
}

BbParser.prototype = {
    //Регистрирует переданные теги. Повторный вызов замещает уже зарегистрированные теги.
    register: function(/*...*/) {
        var len = arguments.length, len2;
        var hash, j, a;
        this._tagClass = arguments;
        this._tagArgs.length = len;
        this._tags = { };
        //this._banned = [ ];
        for (var i = 0; i < len; i++) {
            a = arguments[i].prototype;
            this._tags[a.name] = i;
            hash = { };
            if (a.bbArgs) {
                len2 = a.bbArgs.length;
                for (j = 0; j < len2; j++)
                    hash[a.bbArgs[j]] = true;
            }
            this._tagArgs[i] = hash;
        }
    },

    //Запрет тегов пока не реализован.
    /*
    //Запрещает раскрывать указанные теги.
    banTags: function(...) {
        var len = arguments.length;
        var id;
        for (var i = 0; i < len; i++) {
            id = this._tags[arguments[i]];
            if (id !== undefined)
                this._banned.push(id);
        }
    },

    //Снимает запрет с указанных тегов.
    unbanTags: function(...) {
        var len = arguments.length;
        var id;
        for (var i = 0; i < len; i++) {
            id = this._tags[arguments[i]];
            if (id !== undefined) {
                //Удалить id из this._banned.
            }
        }
    },

    //Очищает список запрещенных тегов.
    clearBanned: function() { this._banned = [ ]; },
    */

    //Генерирует предупреждение или ошибку, если включен STRICT MODE.
    raiseWarning: function(msg) {
        this.warnings.push(msg);
        if (this.flags & BB_STRICT)
            throw msg;
    },

    //Генерирует ошибку.
    raiseError: function(msg) {
        this.warnings.push(msg);
        throw msg;
    },

    //Разбирает входную строку и строит для нее дерево DOM. При возникновении ошибки возвращает null.
    parse: function(input) {
        this.warnings = [ ];
        this.execCount++;
        this.input = input;
        this.pos = 0;
        var r = new BbRoot;
        try {
            this._parse(r);
            return r.toDom(this);
        }
        catch (e) {
            return null;
        }
    },

    //Вставляет в элемент DOM содержимое переданного массива.
    insertContent: function(e, nodes) {
        var len = nodes.length;
        for (var i = 0; i < len; i++)
            e.appendChild(nodes[i].toDom ? nodes[i].toDom(this) : this._defaultDomConversion(nodes[i]));
    },

    //Устанавливает элементу DOM атрибуты. Поддерживает вставку аргументов тега и вызов его функций.
    processArgs: function(e, node) {
        var t = this, v;
        var f = function(_0, s) {
            return (s.charAt(0) != '=' ? node.args[s] : node.funcs[s.substr(1)].call(node, t)) || "";
        };
        var p = function(e, args) {
            for (var key in args)
                if (v = args[key].replace(t._rxDefArg, f))
                    e[key] = v;
        };
        p(e, node.htmlArgs);
        p(e.style, node.cssArgs);
    },

    //Приватные методы и статичные члены.
    _rxSearchPattern: /[\[\r\n]/g,//Ищет скобку или перевод строки.
    _rxSpaces: /\S/g,//Пропускает все пробелы.
    _rxAttrValue: /[\s\]]/g,//Пропускает символы до пробела или закрывающей скобки.
    _rxWord: /[\s=\[\]]/g,//Пропускает идентификатор.
    _rxDefArg: /\$(.*?)\$/g,//Выделяет BB-аргументы для установки свойств DOM.

    _defaultDomConversion: function(node) {
        var e = document.createElement(node.htmlName || node.name);
        if (node.htmlArgs || node.cssArgs)
            this.processArgs(e, node);
        if (node.content)
            this.insertContent(node.target && node.target(e) || e, node.content);
        return e;
    },

    _convertCase: function(str) {
        return this.flags & BB_INSENSITIVE ? str.toLowerCase() : str;
    },

    _getAttrValue: function(tagId, args, key) {
        var c = this.input.charAt(this.pos);
        if (c == '"' || c == "'") {
            //Значение в кавычках.
            var p = this.input.indexOf(c, this.pos + 1);
            if (!~p)
                return 1;
            args[key] = this.input.substring(this.pos + 1, p);
            this.pos = p + 1;
        } else {
            //Значение без кавычек.
            if (c == ']' || c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\u00A0')
                return 2;
            this._rxAttrValue.lastIndex = this.pos;
            if (!this._rxAttrValue.test(this.input))
                return 3;
            args[key] = this.input.substring(this.pos, this._rxAttrValue.lastIndex - 1);
            this.pos = this._rxAttrValue.lastIndex - 1;
        }
        return !this._tagArgs[tagId][key] << 2;
    },

    _skipWord: function() {
        this._rxWord.lastIndex = this.pos;
        return this._rxWord.test(this.input) ? this._rxWord.lastIndex - 1 : this.input.length;
    },

    _parse: function(parent) {
        var start = this.pos;
        var len = this.input.length;
        var tagStart, p, tagId;
        var trim = parent.trim, br = 0;
        var c, tagName, key, actualKey, prev;
        var e, args;
        top: while (this.pos < len) {
            if (br)
                br--;
            //Ищем теги или переводы строк.
            this._rxSearchPattern.lastIndex = this.pos;
            if (!this._rxSearchPattern.test(this.input)) {
                //Больше тегов в строке нет.
                if (start != len)
                    parent.content.push(new BbText(this.input.substr(start)));
                this.pos = len;
                break /*top*/;
            }
            this.pos = this._rxSearchPattern.lastIndex;
            trim = false;
            tagStart = this.pos - 1;
            c = this.input.charAt(tagStart);
            if (c != '[') {
                //Нашли перевод строки. Заменим его на <br />.
                if (start != tagStart)
                    parent.content.push(new BbText(this.input.substring(start, tagStart)));
                if (c == '\r' && this.input.charCodeAt(this.pos) == 10)
                    this.pos++;
                if (parent.content[parent.content.length - 1] instanceof BbBr)
                    parent.content[parent.content.length - 1] = new BbDoubleBr;
                else if (!(parent.content[parent.content.length - 1] instanceof BbDoubleBr)) {
                    parent.content.push(new BbBr);
                    br = 2;
                }
                start = this.pos;
                continue /*top*/;
            }
            if (this.input.charAt(this.pos) == '/') {
                if (parent.name && this._convertCase(this.input.substr(this.pos + 1, parent.name.length)) == parent.name && /*
                */ this.input.charAt(this.pos + 1 + parent.name.length) == ']') {
                    //Найден закрывающий тег.
                    if (start != tagStart)
                        parent.content.push(new BbText(this.input.substring(start, tagStart)));
                    else if (br && parent.trim)
                        parent.content.pop();
                    this.pos += parent.name.length + 2;
                    return;
                }
                //В противном случае это либо не тот тег, либо вообще не тег.
                this.pos++;
                p = this._skipWord();
                if (this.input.charAt(p) == ']') {
                    tagName = this._convertCase(this.input.substring(this.pos, p));
                    this.pos = p + 1;
                    if (tagName in this._tags)
                        this.raiseWarning("Неверный порядок закрытия тегов: [" + (parent.name || " ") + "]...[/" + tagName + "]!");
                } else
                    this.pos = p;
            } else {
                //Читаем имя тега.
                p = this._skipWord();
                if (p != this.pos) {
                    //Имя тега корректное.
                    tagName = this._convertCase(this.input.substring(this.pos, p));
                    this.pos = p;
                    if (tagName in this._tags) {
                        //Тег зарегистрирован.
                        tagId = this._tags[tagName];
                        args = { };
                        c = this.input.charAt(this.pos);
                        if (c == '=') {
                            //У основного атрибута есть значение.
                            this.pos++;
                            switch (this._getAttrValue(tagId, args, "")) {
                                case 1: this.raiseError("Незакрытые кавычки тега " + tagName + "!"); break;
                                case 2: this.raiseError("Отсутствует значение тега " + tagName + "!"); break;
                                case 3: this.raiseError("Неоконченный тег [" + tagName + "!"); this.pos = len; break top;
                                case 4: this.raiseWarning("Неизвестный атрибут тега [" + tagName + "=" + args[""] + "]!");
                            }
                            c = this.input.charAt(this.pos);
                        }
                        while (c != ']') {
                            //Пропускаем пробелы.
                            this._rxSpaces.lastIndex = this.pos;
                            this._rxSpaces.test(this.input);
                            this.pos = this._rxSpaces.lastIndex - 1;
                            //Читаем ключ.
                            p = this._skipWord();
                            if (p == this.pos)
                                continue top;
                            key = this._convertCase(this.input.substring(this.pos, p));
                            prev = args[actualKey = key == tagName ? "" : key];
                            c = this.input.charAt(p);
                            if (c == '=') {
                                this.pos = p + 1;
                                switch (this._getAttrValue(tagId, args, actualKey)) {
                                    case 1: this.raiseError("Незакрытые кавычки атрибута " + key + " тега " + tagName + "!"); break;
                                    case 2: this.raiseError("Отсутствует значение атрибута " + key + " тега " + tagName + "!"); break;
                                    case 3: this.raiseError("Неоконченный тег [" + tagName + "!"); this.pos = len; break top;
                                    case 4: this.raiseWarning("Неизвестный атрибут тега [" + tagName + " " + key + "=" + args[actualKey] + "]!");
                                }
                                c = this.input.charAt(this.pos);
                            } else {
                                //Ключ указан без значения.
                                args[actualKey] = "";
                                this.pos = p;
                            }
                            if (prev !== undefined)
                                this.raiseWarning("Повторно определен атрибут тега [" + tagName + " " + key + "=" + prev + " " + key + "=" + args[actualKey] + "]!");
                        }
                        this.pos++;
                        if (start != tagStart) {
                            parent.content.push(new BbText(this.input.substring(start, tagStart)));
                            br = 0;
                        }
                        e = new this._tagClass[tagId];
                        e.args = args;
                        if (br && e.trim)
                            parent.content.pop();
                        //Метод onEnter возвращает true, если самостоятельно разбирает содержимое тега.
                        if ((!e.onEnter || !e.onEnter(this)) && e.content) {
                            this._parse(e);
                            if (e.trim && e.content[e.content.length - 1] instanceof BbBr)
                                e.content.pop();
                        }
                        parent.content.push(e);
                        if (e.onLeave)
                            e.onLeave(this);
                        start = this.pos;
                        trim = e.trim;
                    }
                }
            }
        }
        if (parent.name)
            this.raiseWarning("Незакрытый тег [" + parent.name + "]!");
        else if (parent.content[parent.content.length - 1] instanceof BbBr)
            parent.content.pop();//Последний перевод строки в сообщении.
    }
};

function BbRoot() { this.content = [ ]; }
BbRoot.prototype = {
    trim: true,
    toDom: function(parser) {
        var e = document.createDocumentFragment();
        parser.insertContent(e, this.content);
        return e;
    }
};

function BbText(text) { this.text = text || ""; }
BbText.prototype.toDom = function(/*parser*/) {
    return document.createTextNode(this.text);
};

function BbBr() { }
BbBr.prototype.toDom = function(/*parser*/) {
    return document.createElement("br");
};

function BbDoubleBr() { }
BbDoubleBr.prototype.toDom = function(/*parser*/) {
    var f = document.createDocumentFragment();
    f.appendChild(document.createElement("br"));
    f.appendChild(document.createElement("br"));
    return f;
};

//===========================================================================
// Подмодуль парсера - анализатор программного кода.
//===========================================================================

function CodeParser(l, w, o) {
    this.s = "";
    this.i = 0;
    this.len = 0;
    this.lang = l || "";
    this.keywords = w || { };
    this.ops = [ ];
    if (o) {
        var i = o.length;
        while (i)
            this.ops[o.charCodeAt(--i)] = 1;
    }
}

CodeParser.prototype = {
    _str: /"|'|`|\[\/code\]/g,
    _cmt: /\/\*|\*\/|\n|\[\/code\]/g,
    _endl: /\n|\[\/code\]/g,
    _alpha: /[a-zA-Z_]/,
    _digit: /\d/,
    _Digit: /\D/g,
    _alnum: /\w/,
    _Alnum: /\W/g,
    _X: /[^\da-fA-F]/g,
    _O: /[^0-7]/g,
    _s: /\s/,
    _esc: /[<&\t]/g,

    _kw: {
        "enum": 1,
        "for": 1,
        "function": 1,
        globals: 1,
        "if": 1,
        library: 1,
        library_once: 1,
        loop: 1,
        method: 1,
        module: 1,
        repeat: 1,
        scope: 1,
        struct: 1,
        vblock: 1,
        "while": 1,
        whilenot: 1
    },

    _select: function(x) {
        return x === +x ? { "": x } : x;
    },

    _rep: function(s) {
        return s == '<' ? "&lt;" : s == '&' ? "&amp;" : "    ";
    },

    _tab: function(first, tab, sharp) {
        var s = first && tab > 0 ? new Array(tab + 1).join("    ") : "";
        if (sharp)
            return s + '#';
        return s;
    },

    readWord: function() {
        var t = this, n = t.keywords;
        var i = t.i;
        var c, key;
        lp: while (i <= t.len) {
            c = t.s.charAt(t.i);
            if (t._alnum.test(c))
                if (c in n)
                    n = t._select(n[c]);//Односимвольный узел.
                else {
                    for (key in n)
                        if (c == key.charAt(0)) {
                            //Проверить остальные символы в подстроке и продолжить сравнение.
                            if (key != t.s.substr(t.i, key.length))
                                break;
                            n = t._select(n[key]);
                            t.i += key.length;
                            continue lp;
                        }
                    //Строка не совпала, пропустить оставшиеся символы.
                    t._Alnum.lastIndex = t.i;
                    if (t._Alnum.test(t.s)) {
                        t.i = t._Alnum.lastIndex - 1;
                        return [ t.s.substring(i, t.i), -1 ];
                    }
                    t.i = t.len;
                    return [ t.s.substr(i), -1 ];
                }
            else if ("" in n)
                /* Строка совпала. */
                return [ t.s.substring(i, t.i), n[""] ];
            else
                break;
            t.i++;
        }
        //Строка не совпала.
        return [ t.i < t.len ? t.s.substring(i, t.i) : t.s.substr(i), -1 ];
    },

    readString: function(c, nm) {
        var t = this;
        var i = t.i;
        t._str.lastIndex = i + 1;
        while (t._str.test(t.s))
            if (c == t.s.charAt(t._str.lastIndex - 1)) {
                if (t.s.charCodeAt(t._str.lastIndex - 2) != 92)
                    return "<span class='" + t.lang + "-" + nm + "'>" + t.s.substring(i, t.i = t._str.lastIndex).replace(/</g, "&lt;") + "</span>";
            } else if (t.s.charCodeAt(t._str.lastIndex - 1) == 93) {
                //Незакрытые кавычки.
                t.i = t._str.lastIndex - 7;
                return t.s.substring(i, t.i).replace(/</g, "&lt;");
            }
        //Конец сообщения.
        t.i = t.len;
        return t.s.substr(i).replace(/</g, "&lt;");
    },

    readComment: function(tab) {
        var t = this;
        var i = t.i, ct = 1, x;
        var res = "";
        t._cmt.lastIndex = t.i + 2;
        while (t._cmt.test(t.s)) {
            x = t.s.charCodeAt(t._cmt.lastIndex - 1);
            if (x == 42)
                ct++;
            else if (x == 10) {
                res += t.s.substring(i, t._cmt.lastIndex) + t._tab(true, tab, false);
                i = t._cmt.lastIndex;
            } else if (x == 93) {
                //Незакрытый комментарий.
                t.i = t._cmt.lastIndex - 7;
                return (res + t.s.substring(i, t.i)).replace(/</g, "&lt;");
            } else if (!--ct) {
                t.i = t._cmt.lastIndex;
                return "<span class='" + t.lang + "-comment'>" + (res + t.s.substring(i, t.i)).replace(/</g, "&lt;") + "</span>";
            }
        }
        //Конец сообщения.
        t.i = t.len;
        return t.s.substr(i).replace(/</g, "&lt;");
    },

    readOper: function() {
        return "<span class='" + this.lang + "-oper'>" + this.s.charAt(this.i++) + "</span>";
    },

    readNum: function() {
        var t = this;
        var i = t.i, x = t.s.charCodeAt(i);
        var rx = t._Digit;
        var dot = 0;
        var more = 0;
        if (x == 48) {
            x = t.s.charCodeAt(++t.i);
            if (x == 120)
                rx = t._X;
            else if (x >= 48 && x <= 55)
                rx = t._O;
            else if (x == 46)
                dot = 1;
            else
                return "<span class='" + t.lang + "-number'>0</span>";
        } else if (x == 46)
            dot = 1;
        rx.lastIndex = t.i + 1;
        do
            if (rx.test(t.s)) {
                if (!dot && rx != t._X && t.s.charCodeAt(rx.lastIndex - 1) == 46) {
                    dot = more = 1;
                    continue;
                }
                t.i = rx.lastIndex - 1;
            } else
                t.i = t.len;
        while (more--);
        return "<span class='" + t.lang + "-number'>" + t.s.substring(i, t.i) + "</span>";
    },

    readDollar: function() {
        var t = this, c;
        var i = t.i, m = 0;
        t._X.lastIndex = i + 1;
        if (t._X.test(t.s)) {
            c = t.s.charAt(t.i = t._X.lastIndex - 1);
            if (c == '$') {
                m = 1;
                t.i++;
            } else if (t._alpha.test(c)) {
                m = 1;
                t._Alnum.lastIndex = t.i + 1;
                if (t._Alnum.test(t.s))
                    t.i = t._Alnum.lastIndex - (t.s.charCodeAt(t._Alnum.lastIndex - 1) != 36);
                else
                    t.i = t.len;
            }
        } else
            t.i = t.len;
        return "<span class='" + t.lang + (m ? "-macro-arg'>" : "-number'>") + t.s.substring(i, t.i).replace(/</g, "&lt;") + "</span>";
    },

    read: function() {
        var t = this;
        var res = "";
        var c, x, iface = 0, tab = 0, lastTab = 0, funcmod = 0, first = 2;
        var elseBracket = 1, sharp = 0;
        var bslash = 0;
        var postCond = [ ], brackets = new Array(5);
        var a;
        if (t.s.charCodeAt(t.i) == 10)
            t.i++;
        while (t.i < t.len) {
            if (first)
                first--;
            if (sharp)
                sharp--;
            c = t.s.charAt(t.i);
            if (c == '[' && t.s.substr(t.i + 1, 6) == "/code]") {
                t.i += 7;
                return res;
            }
            if (t._alpha.test(c)) {
                if (funcmod)
                    funcmod--;
                x = t.i;
                a = t.readWord();
                if (~a[1]) {
                    if (!a[1]) {
                        //Найдено ключевое слово.
                        x = a[0];
                        if (x == "interface") {
                            iface = 1;
                            res += t._tab(first, tab++, sharp);
                            lastTab = 2;
                        } else {
                            if (x == "endinterface") {
                                iface = 0;
                                if (tab)
                                    res += t._tab(first, --tab, sharp);
                            } else if (x == "do") {
                                postCond[tab] = 1;
                                res += t._tab(first, tab, sharp);
                            } else if (x == "while" || x == "whilenot") {
                                res += t._tab(first, tab, sharp);
                                if (postCond[tab])
                                    postCond[tab] = 0;
                                else {
                                    tab++;
                                    lastTab = 2;
                                }
                            } else if (x == "else" || x == "elseif") {
                                res += t._tab(first, tab - elseBracket, sharp);
                            } else if (x == "function") {
                                res += t._tab(first, tab, sharp);
                                if (!iface && (first || funcmod)) {
                                    tab++;
                                    lastTab = 2;
                                }
                            } else if (t._kw[x]) {
                                res += t._tab(first, tab, sharp);
                                if (!iface)
                                    tab++;
                                lastTab = 2;
                            } else if (x.substr(0, 3) == "end" && t._kw[x.substr(3)] && x != "endlibrary_once") {
                                if (tab)
                                    res += t._tab(first, --tab, sharp);
                            } else {
                                res += t._tab(first, tab, sharp);
                                if (x == "private" || x == "public" || x == "constant")
                                    funcmod = 2;
                            }
                        }
                    } else
                        res += t._tab(first, tab, sharp);
                    res += "<span class='" + t.lang + "-keyword-" + a[1] + "'>" + a[0] + "</span>";
                } else
                    res += t._tab(first, tab, sharp) + a[0];
                elseBracket = 1;
            } else if (t._digit.test(c))
                res += t._tab(first, tab, sharp) + t.readNum();
            else if (c == '.')
                res += t._tab(first, tab, sharp) + (t._digit.test(t.s.charAt(t.i + 1)) ? t.readNum() : t.readOper());
            else if (c == '-')
                res += t._tab(first, tab, sharp) + (t._digit.test(t.s.charAt(t.i + 1 + (t.s.charCodeAt(t.i + 1) == 46))) ? t.readNum() : t.readOper());
            else if (c == '"' || c == "'" || c == '`')
                res += t._tab(first, tab, sharp) + t.readString(c, c == '"' ? "string" : c == "'" ? "char" : "macro-string");
            else if (c == '/') {
                x = t.s.charCodeAt(t.i + 1);
                res += t._tab(first, tab, sharp);
                if (x == 47) {
                    x = t.s.indexOf('\n', t.i + 2);
                    t._endl.lastIndex = t.i + 2;
                    if (t._endl.test(t.s))
                        x = t._endl.lastIndex - (t.s.charCodeAt(t._endl.lastIndex - 1) == 10 ? 1 : 7);
                    else
                        x = t.len;
                    res += "<span class='jass-" + (t.s.charCodeAt(t.i + 2) == 33 ? "pre'>" : "comment'>") + t.s.substring(t.i, x).replace(/</g, "&lt;") + "</span>";
                    t.i = x;
                    if (lastTab)
                        lastTab--;
                } else if (x == 42)
                    res += t.readComment(tab);
                else
                    res += t.readOper();
            } else if (c == '$')
                res += t._tab(first, tab, sharp) + t.readDollar();
            else if (c == '#') {
                if (sharp)
                    res += '#';
                sharp = 2;
                first++;
                t.i++;
            } else if (c == '{') {
                if (lastTab) {
                    res += t._tab(first, tab - 1, sharp) + t.readOper();
                    lastTab = 0;
                } else
                    res += t._tab(first, tab++, sharp) + t.readOper();
            } else if (c == '}') {
                if (tab)
                    tab--;
                res += t._tab(first, tab, sharp) + t.readOper();
                elseBracket = 0;
                iface = 0;
            } else if (c == '(') {
                if (lastTab == 2)
                    brackets[tab] = (brackets[tab] || 0) + 1;
                else
                    tab++;
                res += t._tab(first, tab, sharp) + t.readOper();
            } else if (c == ')') {
                if (brackets[tab])
                    brackets[tab]--;
                else if (tab)
                    tab--;
                res += t._tab(first, tab, sharp) + t.readOper();
            } else if (c == '\\') {
                bslash = 1;
                res += t._tab(first, tab, sharp) + t.readOper();
            } else if (c == '\n') {
                first = 2;
                if (bslash)
                    bslash = 0;
                else if (lastTab)
                    lastTab--;
                res += '\n';
                t.i++;
            } else if (t.ops[c.charCodeAt(0)])
                res += t._tab(first, tab, sharp) + t.readOper();
            else {
                res += t._tab(first, tab, sharp) + c;
                t.i++;
            }
        }
        return res;
    }
};

//===========================================================================
// База данных анализатора JASS-кода - дерево ключевых слов.
//===========================================================================

var rcs={H:2,N:2,O:2,T:2,U:2,X:{H:2,N:2,O:2,U:2}},loc={"":3,Loc:3},locxy={Loc:3,X:3,Y:3},byid={"":3,ById:3},bj={"":3,BJ:4},ebj={"":3,BJ:4,Ex:bj},en={"":4,Enum:4},six2=[2,2,2,2,2,2],ten2=[2,2,2,2,2,2,2,2,2,2],ffn={ff:2,n:2},fn={"":2,o:ffn},sw={"":3,Swapped:4},jkw={A:{I_DIFFICULTY_:{INSANE:2,N:{EWBIE:2,ORMAL:2}},LL:{IANCE_:{HELP_RE:{QUEST:2,SPONSE:2},PASSIVE:2,RESCUABLE:2,SHARED_:{ADVANCED_CONTROL:2,CONTROL:2,SPELLS:2,VISION:{"":2,_FORCED:2},XP:2}},_Remove:2},TTACK_TYPE_:{CHAOS:2,HERO:2,M:{AGIC:2,ELEE:2},NORMAL:2,PIERCE:2,SIEGE:2},UTOFLUSH_LOCALS:2,b:{ilityId:{"":3,"2String":3},ortCinematicFadeBJ:4},cos:bj,d:{d:{HeroXP:sw,I:{ndicator:3,temTo:{AllStock:3,Stock:bj}},Lightning:{"":3,Ex:3,Loc:4},PlayerTechResearched:3,ResourceAmount:bj,Spe:{cialEffect:{"":3,Loc:bj,Target:{"":3,UnitBJ:4}},llEffect:{"":3,ById:loc,Loc:3,Target:byid}},Unit:{AnimationProperties:bj,To:{AllStock:3,Stock:bj}},WeatherEffect:{"":3,SaveLast:4}},just:{Camera:{Bounds:{BJ:4,ForPlayerBJ:4},Field:3},PlayerState:{BJ:4,SimpleBJ:4}}},llowVictoryDefeat:4,n:{d:3,gleBetweenPoints:4},sin:bj,t:{an:{"":3,"2":bj,BJ:4},tachSoundToUnit:bj}},B:{JDebugMsg:4,LEND_MODE_:{ADDITIVE:2,BLEND:2,DONT_CARE:2,KEYALPHA:2,MODULATE:{"":2,_2X:2},NONE:2},lightGoldMineForPlayer:{"":4,BJ:4}},C:{AMERA_:{FIELD_:{ANGLE_OF_ATTACK:2,F:{ARZ:2,IELD_OF_VIEW:2},RO:{LL:2,TATION:2},TARGET_DISTANCE:2,ZOFFSET:2},MARGIN_:{BOTTOM:2,LEFT:2,RIGHT:2,TOP:2}},OUNTER:2,a:{chePlayerHeroData:3,mera:{ClearNoiseForPlayer:4,ResetSmoothingFactorBJ:4,Set:{EQNoiseForPlayer:4,S:{moothingFactor:bj,ourceNoise:{"":3,Ex:3,ForPlayer:4}},TargetNoise:{"":3,Ex:3,ForPlayer:4},up:{Apply:{"":3,For:{Player:4,ceDuration:{"":3,WithZ:3}},WithZ:3},Get:{DestPosition:locxy,Field:{"":3,Swap:4}},Set:{DestPosition:3,Field:3}}}},ncelCineSceneBJ:4},h:{ange:{Elevator:{Height:4,Wall:{Blocker:4,s:4}},Level:3},e:{at:3,ckI:{nitPlayerSlotAvailability:4,tem:{Status:4,codeStatus:4}}},ooseRandom:{Creep:bj,Item:ebj,NPBuilding:bj}},inematic:{F:{ade:{BJ:4,CommonBJ:4},ilterGenericBJ:4},Mode:{BJ:4,ExBJ:4}},lear:{MapMusic:bj,Selection:{"":3,ForPlayer:4},TextMessages:bj},o:{m:{m:{andAI:3,entString:4},pare:{LocationsBJ:4,RectsBJ:4}},n:{dition:{"":3,alTriggerExecute:4},figureNeutralVictim:4,tinueCinematicFade:{AfterBJ:4,BJ:4},vert:{A:{IDifficulty:3,llianceType:3,ttackType:3},BlendMode:3,CameraField:3,D:{amageType:3,ialogEvent:3},EffectType:3,F:{GameState:3,ogState:3},Game:{Difficulty:3,Event:3,Speed:3,Type:3},I:{GameState:3,temType:3},LimitOp:3,Map:{Control:3,Density:3,Flag:3,Setting:3,Visibility:3},P:{athingType:3,la:{cement:3,yer:{Color:3,Event:3,GameResult:3,S:{core:3,lotState:3,tate:3},UnitEvent:3}}},Ra:{ce:{"":3,Pref:3},rityControl:3},S:{oundType:3,tartLocPrio:3},TexMapFlags:3,Unit:{Event:3,State:3,Type:3},V:{ersion:3,olumeGroup:3},W:{eaponType:3,idgetEvent:3},edPlayer:4}},pySaveGame:bj,s:bj,unt:{LivingPlayerUnitsOfTypeId:4,PlayersInForce:{BJ:4,Enum:4},UnitsInGroup:en,er:{Inc:3,Reset:3}}},r:{e:{ate:{BlightedGoldmine:3,C:{ameraSetup:3,orpse:{"":3,LocBJ:4}},De:{adDestructable:{"":3,LocBJ:4,Z:3},featCondition:bj,structable:{"":3,Loc:4,Z:3}},Fo:{gModifierR:{adius:{"":3,Loc:{"":3,BJ:4,Simple:4}},ect:{"":3,BJ:4,Simple:4}},rce:3},Group:3,I:{mage:bj,tem:{"":3,Loc:4,Pool:3}},Leaderboard:bj,M:{IDISound:3,ultiboard:bj},NUnitsAtLoc:{"":4,FacingLocBJ:4},PermanentCorpseLocBJ:4,Quest:{"":3,BJ:4,ItemBJ:4},Region:3,Sound:{"":3,F:{ilenameWithLabel:3,romLabel:3}},T:{extTag:{"":3,LocBJ:4,UnitBJ:4},imer:{"":3,BJ:4,Dialog:bj},r:{ackable:3,igger:3}},U:{bersplat:bj,nit:{"":3,AtLoc:{"":3,ByName:3,SaveLast:4},ByName:3,Pool:3}}},epsOnMap:3},ipplePlayer:3},ustom:{Defeat:{BJ:4,DialogBJ:4,LoadBJ:4,QuitBJ:4,Re:{duceDifficultyBJ:4,startBJ:4}},Victory:{BJ:4,DialogBJ:4,OkBJ:4,QuitBJ:4,SkipBJ:4}}},D:{AMAGE_TYPE_:{ACID:2,COLD:2,D:{E:{ATH:2,FENSIVE:2,MOLITION:2},I:{SEASE:2,VINE:2}},ENHANCED:2,F:{IRE:2,ORCE:2},LIGHTNING:2,M:{AGIC:2,IND:2},NORMAL:2,P:{LANT:2,OISON:2},S:{HADOW_STRIKE:2,LOW_POISON:2,ONIC:2,PIRIT_LINK:2},UN:{IVERSAL:2,KNOWN:2}},EBUG:{"":2,_MODE:2},e:{cUnitAbilityLevel:sw,f:{eatConditionSetDescription:bj,ineStartLocation:loc},g2Rad:3,layedSuspendDecay:{"":4,BoneEnum:4,Create:4,FleshEnum:4,StopAnimEnum:4},str:{oy:{BoolExpr:3,Condition:3,DefeatCondition:bj,Effect:bj,F:{ilter:3,o:{gModifier:3,rce:3}},Group:3,I:{mage:3,temPool:3},L:{eaderboard:bj,ightning:bj},Multiboard:bj,Quest:bj,T:{extTag:bj,imer:{"":3,BJ:4,Dialog:bj},rigger:3},U:{bersplat:3,nitPool:3}},uctable:{AddIndicatorBJ:4,RestoreLife:3}},tectGameStarted:4},i:{alog:{Add:{Button:{"":3,BJ:4,WithHotkeyBJ:4},QuitButton:3},C:{lear:bj,reate:3},D:{estroy:3,isplay:bj},SetMessage:bj},s:{able:{RestartMission:3,Trigger:3},play:{CineFilter:bj,LoadDialog:3,T:{extTo:{Force:4,Player:3},imedText:{FromPlayer:3,To:{Force:4,Player:3}}}},tanceBetweenPoints:4}},o:{Not:{SaveReplay:3,hing:4},TransmissionBasicsXYBJ:4,esUnitGenerateAlarms:4}},E:{FFECT_TYPE_:{AREA_EFFECT:2,CASTER:2,EFFECT:2,LIGHTNING:2,MISSILE:2,SPECIAL:2,TARGET:2},QUAL:2,VENT_:{DIALOG_:{BUTTON_CLICK:2,CLICK:2},GAME_:{BUILD_SUBMENU:2,EN:{D_LEVEL:2,TER_REGION:2},L:{EAVE_REGION:2,OADED:2},S:{AVE:2,HOW_SKILL:2,TATE_LIMIT:2},T:{IMER_EXPIRED:2,OURNAMENT_FINISH_:{NOW:2,SOON:2},RACKABLE_:{HIT:2,TRACK:2}},V:{ARIABLE_LIMIT:2,ICTORY:2}},PLAYER_:{A:{LLIANCE_CHANGED:2,RROW_:{DOWN_:{DOWN:2,UP:2},LEFT_:{DOWN:2,UP:2},RIGHT_:{DOWN:2,UP:2},UP_:{DOWN:2,UP:2}}},CHAT:2,DEFEAT:2,END_CINEMATIC:2,HERO_:{LEVEL:2,REVIV:{ABLE:2,E_:{CANCEL:2,FINISH:2,START:2}},SKILL:2},LEAVE:2,STATE_LIMIT:2,UNIT_:{ATTACKED:2,C:{HANGE_OWNER:2,ONSTRUCT_:{CANCEL:2,FINISH:2,START:2}},D:{E:{ATH:2,CAY:2,SELECTED:2,TECTED:2},ROP_ITEM:2},HIDDEN:2,ISSUED_:{ORDER:2,POINT_ORDER:2,TARGET_ORDER:2,UNIT_ORDER:2},LOADED:2,P:{AWN_ITEM:2,ICKUP_ITEM:2},RES:{CUED:2,EARCH_:{CANCEL:2,FINISH:2,START:2}},S:{EL:{ECTED:2,L:{"":2,_ITEM:2}},PELL_:{C:{AST:2,HANNEL:2},E:{FFECT:2,NDCAST:2},FINISH:2},UMMON:2},TRAIN_:{CANCEL:2,FINISH:2,START:2},U:{PGRADE_:{CANCEL:2,FINISH:2,START:2},SE_ITEM:2}},VICTORY:2},UNIT_:{A:{CQUIRED_TARGET:2,TTACKED:2},C:{HANGE_OWNER:2,ONSTRUCT_:{CANCEL:2,FINISH:2}},D:{AMAGED:2,E:{ATH:2,CAY:2,SELECTED:2,TECTED:2},ROP_ITEM:2},H:{ERO_:{LEVEL:2,REVIV:{ABLE:2,E_:{CANCEL:2,FINISH:2,START:2}},SKILL:2},IDDEN:2},ISSUED_:{ORDER:2,POINT_ORDER:2,TARGET_ORDER:2},LOADED:2,P:{AWN_ITEM:2,ICKUP_ITEM:2},RES:{CUED:2,EARCH_:{CANCEL:2,FINISH:2,START:2}},S:{EL:{ECTED:2,L:{"":2,_ITEM:2}},PELL_:{C:{AST:2,HANNEL:2},E:{FFECT:2,NDCAST:2},FINISH:2},TATE_LIMIT:2,UMMON:2},T:{ARGET_IN_RANGE:2,RAIN_:{CANCEL:2,FINISH:2,START:2}},U:{PGRADE_:{CANCEL:2,FINISH:2,START:2},SE_ITEM:2}},WIDGET_DEATH:2},n:{able:{CreepSleepBJ:4,D:{awnDusk:4,ragSelect:3},MinimapFilterButtons:3,Occlusion:bj,PreSelect:3,Select:3,Trigger:3,User:{Control:3,UI:3},W:{eatherEffect:3,orldFogBoundary:bj}},d:{CinematicScene:3,Game:bj,ThematicMusic:bj},um:{DestructablesIn:{CircleBJ:{"":4,Filter:4},Rect:{"":3,All:4}},ItemsInRect:bj,UnitsSelected:4}},x:{ecuteFunc:3,plodeUnitBJ:4}},F:{ALSE:2,FAInitPlayerSlots:4,OG_OF_WAR_:{FOGGED:2,MASKED:2,VISIBLE:2},UNCNAME:2,i:{lter:3,n:{dElevatorWallBlockerEnum:4,ish:{CinematicFade:{AfterBJ:4,BJ:4},Ubersplat:3}},rstOfGroup:3},l:{ashQuestDialogButton:bj,ush:{ChildHashtable:bj,GameCache:bj,ParentHashtable:bj,Stored:{Boolean:3,Integer:3,Mission:bj,Real:3,String:3,Unit:3}}},o:{g:{Enable:{"":3,O:{ff:4,n:4}},M:{askEnable:{"":3,O:{ff:4,n:4}},odifierSt:{art:3,op:3}}},r:{Force:3,Group:bj,ce:{AddPlayer:{"":3,Simple:4},C:{ampaignSelectScreen:3,inematicSubtitles:bj,lear:3},Enum:{Allies:3,Enemies:3,Players:{"":3,Counted:3}},P:{ickRandomPlayer:en,layerStartLocation:3},QuestDialogUpdate:3,RemovePlayer:{"":3,Simple:4},SetLeaderboardBJ:4,UI:{Cancel:bj,Key:bj}}}}},G:{AME_:{STATE_:{DI:{SCONNECTED:2,VINE_INTERVENTION:2},TIME_OF_DAY:2},TYPE_:{BLIZ:2,F:{FA:2,OUR_TEAM_PLAY:2},MELEE:2,ONE_ON_ONE:2,T:{HREE_TEAM_PLAY:2,WO_TEAM_PLAY:2},USE_MAP_SETTINGS:2}},REATER_THAN:{"":2,_OR_EQUAL:2},ameOverDialogBJ:4,et:{A:{IDifficulty:3,bility:{Effect:{"":3,B:{J:4,yId:3}},Name:4,Sound:{"":3,B:{J:4,yId:3}}},llyColorFilterState:3,ttacke:{dUnitBJ:4,r:3}},B:{oolean:{And:4,Or:4},uyingUnit:3},C:{a:{mera:{Bound:{M:{ax:{X:3,Y:3},"in":{X:3,Y:3}},sMapRect:4},EyePosition:{Loc:3,X:3,Y:3,Z:3},Field:3,Margin:3,TargetPosition:{Loc:3,X:3,Y:3,Z:3}},ncelledStructure:3},hangingUnit:{"":3,PrevOwner:3},licked:{Button:bj,Dialog:bj},on:{struct:{edStructure:3,ingStructure:3},vertedPlayerId:4},re:{atureDensity:3,epCampFilterState:3},u:{rrentCamera:{BoundsMapRectBJ:4,Setup:4},stomCampaignButtonVisible:3}},D:{e:{cayingUnit:3,faultDifficulty:3,structable:{L:{ife:3,oc:4},MaxLife:3,Name:3,OccluderHeight:3,TypeId:3,X:3,Y:3},tectedUnit:3},ying:{Destructable:4,Unit:3}},E:{levatorHeight:4,n:{t:{eringUnit:3,ireMapRect:4},um:{Destructable:3,Item:3,Player:3,Unit:3}},vent:{D:{amage:{"":3,Source:3},etectingPlayer:3},GameState:3,Player:{ChatString:{"":3,Matched:3},State:3},TargetUnit:3,UnitState:3},xpiredTimer:3},F:{adeFromSeconds:4,ilter:{Destructable:3,Item:3,Player:3,Unit:3},loatGameState:3,o:{od:{Made:3,Used:3},r:{LoopIndex:{A:4,B:4},ceOfPlayer:4}}},Game:{Difficulty:3,Placement:3,Speed:3,TypeSelected:3},H:{andleId:bj,ero:{Agi:3,Int:3,Level:3,ProperName:3,S:{killPoints:3,t:{atBJ:4,r:3}},XP:3}},I:{n:{tegerGameState:3,ventoryIndexOfItemTypeBJ:4},ssuedOrderId:bj,tem:{Charges:3,L:{evel:3,ifeBJ:4,oc:4},Name:3,OfTypeFromUnitBJ:4,Player:3,Type:{"":3,Id:3},UserData:3,X:3,Y:3}},KillingUnit:bj,L:{ast:{Created:{ButtonBJ:4,De:{featConditionBJ:4,structable:4},EffectBJ:4,FogModifier:4,G:{ameCacheBJ:4,roup:en},HashtableBJ:4,I:{mage:4,tem:4},L:{eaderboard:4,ightningBJ:4},Multiboard:4,Quest:{BJ:4,ItemBJ:4},T:{e:{rrainDeformation:4,xtTag:4},imer:{BJ:4,DialogBJ:4}},U:{bersplat:4,nit:4},WeatherEffect:4},HauntedGoldMine:4,Played:{Music:4,Sound:4},Re:{movedItem:4,placedUnitBJ:4,storedUnitBJ:4},TransmissionDurationBJ:4},e:{a:{rn:{edSkill:{"":3,BJ:4,Level:3},ingUnit:3},vingUnit:3},velingUnit:3},ightningColor:{A:bj,B:bj,G:bj,R:bj},o:{adedUnit:bj,ca:{l:{Player:3,ized:{Hotkey:3,String:3}},tion:{X:3,Y:3,Z:3}}}},Manipulat:{edItem:3,ingUnit:3},O:{bjectName:3,rder:{Point:locxy,Target:{"":3,Destructable:3,Item:3,Unit:3},edUnit:3},wningPlayer:3},Play:{ableMapRect:4,er:{Alliance:3,Co:{lor:3,ntroller:3},Handicap:{"":3,BJ:4,XP:bj},Id:3,Name:3,Race:3,S:{core:3,electable:3,lotState:3,t:{a:{rtLocation:{"":3,Loc:4,X:4,Y:4},te:3},ructureCount:3}},T:{axRate:bj,e:{am:3,ch:{Count:{"":3,Simple:4},MaxAllowed:{"":3,Swap:4},Researched:3}},ypedUnitCount:3},Unit:{Count:3,TypeCount:3},s:{"":3,All:{"":4,ies:4},ByMapControl:4,Enemies:4,Matching:4}}},R:{andom:{DirectionDeg:4,Int:3,LocInRect:4,PercentageBJ:4,Real:3,SubGroup:en},e:{ct:{Center:{"":4,X:3,Y:3},FromCircleBJ:4,HeightBJ:4,M:{ax:{X:3,Y:3},"in":{X:3,Y:3}},WidthBJ:4},s:{cuer:3,earch:{ed:3,ingUnit:3},ource:{Amount:3,Density:3}},viv:{ableUnit:3,ingUnit:3}}},S:{aveBasicFilename:3,el:{ectedUnit:3,lingUnit:3},o:{ld:{Item:3,Unit:3},und:{Duration:bj,FileDuration:bj,Is:{Loading:3,Playing:bj}}},pell:{Ability:{"":3,Id:3,Unit:3},Target:{Destructable:3,Item:3,Loc:3,Unit:3,X:3,Y:3}},t:{artLoc:{Prio:{"":3,Slot:3},ation:locxy},ored:{Boolean:bj,Integer:bj,Real:bj,String:bj}},ummon:{edUnit:3,ingUnit:3}},T:{e:{ams:3,rrain:{CliffLevel:bj,Type:bj,Variance:bj}},imeOfDay:{"":4,Scale:{"":3,PercentBJ:4}},ournament:{Finish:{Now:{Player:3,Rule:3},SoonTimeRemaining:3},Score:3},r:{a:{inedUnit:{"":3,Type:3},ns:{missionDuration:4,portUnit:bj}},igger:{Destructable:3,E:{v:{alCount:3,entId:3},xecCount:3},Player:3,Unit:3,Widget:3,ing:{Region:3,Tr:{ackable:3,igger:3}}}}},Unit:{A:{bilityLevel:sw,cquireRange:3},BuildTime:3,CurrentOrder:3,Default:{AcquireRange:3,FlyHeight:3,MoveSpeed:3,PropWindow:bj,TurnSpeed:3},F:{acing:3,lyHeight:3,ood:{Made:3,Used:3}},GoldCost:3,L:{evel:3,ifePercent:4,oc:3},M:{anaPercent:4,oveSpeed:3},Name:3,P:{ointValue:{"":3,ByType:3},ropWindow:bj},Ra:{ce:3,lly:{Destructable:3,Point:3,Unit:3}},State:{"":3,Percent:4,Swap:4},T:{urnSpeed:3,ypeId:3},UserData:3,WoodCost:3,X:3,Y:3,s:{InR:{angeOfLoc:{All:4,Matching:4},ect:{All:4,Matching:4,OfPlayer:{"":4,Filter:4}}},Of:{Player:{A:{ll:4,ndTypeId:{"":4,Filter:4}},Matching:4},TypeIdAll:{"":4,Filter:4}},SelectedAll:4}},W:{i:{dget:{Life:3,X:3,Y:3},nningPlayer:3},orldBounds:3}},roup:{Add:{Group:en,Unit:{"":3,Simple:4}},Clear:3,EnumUnits:{InR:{ange:{"":3,Counted:3,OfLoc:{"":3,Counted:3}},ect:{"":3,Counted:3}},Of:{Player:3,Type:{"":3,Counted:3}},Selected:3},ImmediateOrder:{"":3,B:{J:4,yId:3}},P:{ickRandomUnit:en,ointOrder:{"":3,ById:loc,Loc:bj}},Remove:{Group:en,Unit:{"":3,Simple:4}},T:{arget:{DestructableOrder:4,ItemOrder:4,Order:{"":3,B:{J:4,yId:3}}},rainOrderByIdBJ:4}}},HaveS:{aved:{Boolean:3,Handle:3,Integer:3,Real:3,String:3,Value:4},tored:{Boolean:3,Integer:3,Real:3,String:3,Unit:3,Value:4}},I:{"2":{R:3,S:3},AbsBJ:4,M:{axBJ:4,inBJ:4},SignBJ:4,TEM_TYPE_:{A:{NY:2,RTIFACT:2},C:{AMPAIGN:2,HARGED:2},MISCELLANEOUS:2,P:{ERMANENT:2,OWERUP:2,URCHASABLE:2},TOME:2,UNKNOWN:2},n:{cUnitAbilityLevel:sw,it:{Blizzard:{"":4,Globals:4},DNCSounds:4,G:{ameCache:bj,enericPlayerSlots:4},Hashtable:bj,MapRects:4,NeutralBuildings:4,QueuedTriggers:4,RescuableBehaviorBJ:4,SummonableCaps:4},tegerTertiaryOp:4},s:{C:{ineFilterDisplayed:3,ustomCampaignButtonVisibile:4},D:{awnDuskEnabled:4,estructable:{AliveBJ:4,DeadBJ:4,Invulnerable:bj}},Fog:{Enabled:3,MaskEnabled:3,gedToPlayer:3},GameTypeSupported:3,HeroUnitId:3,Item:{HiddenBJ:4,I:{d:{P:{awnable:3,owerup:3},Sellable:3},nvulnerable:3},Owned:3,P:{awnable:3,owerup:3},Sellable:3,Visible:3},L:{eaderboardDisplayed:3,ocation:{FoggedToPlayer:3,InRegion:3,MaskedToPlayer:3,VisibleToPlayer:3}},M:{a:{pFlagSet:3,skedToPlayer:3},ultiboard:{Displayed:3,Minimized:3}},No:{DefeatCheat:3,VictoryCheat:3},P:{layer:{Ally:3,Enemy:3,FlagSetBJ:4,InForce:3,Observer:3,RacePrefSet:3,SlotState:4},oint:{Blighted:bj,InRegion:3}},Quest:{Completed:3,Discovered:3,Enabled:3,Failed:3,ItemCompleted:3,Required:3},SuspendedXP:3,T:{errainPathable:bj,imerDialogDisplayed:3,owered:3,rigger:{Enabled:3,Queue:{EmptyBJ:4,dBJ:4},WaitOnSleeps:3}},Unit:{"":3,Al:{iveBJ:4,ly:3},De:{adBJ:4,tected:3},Enemy:3,Fogged:3,Group:{DeadBJ:en,EmptyBJ:en,InRectBJ:en},Hidden:bj,I:{dType:3,llusion:bj,n:{Force:3,Group:3,R:{ange:{"":3,Loc:3,XY:3},egion:3},Transport:bj,visible:3}},Loaded:bj,Masked:3,OwnedByPlayer:3,Paused:bj,Race:3,Selected:3,Type:3,Visible:3},VisibleToPlayer:3,sue:{BuildOrder:{"":3,ById:{"":3,LocBJ:4}},HauntOrderAtLocBJ:{"":4,Filter:4},I:{mmediateOrder:{"":3,B:{J:4,yId:3}},nstant:{PointOrder:byid,TargetOrder:byid}},Neutral:{ImmediateOrder:byid,PointOrder:byid,TargetOrder:byid},PointOrder:{"":3,ById:loc,Loc:bj},T:{arget:{DestructableOrder:4,ItemOrder:4,Order:{"":3,B:{J:4,yId:3}}},rainOrderByIdBJ:4},UpgradeOrderByIdBJ:4}},tem:{AddIndicatorBJ:4,Pool:{AddItemType:3,RemoveItemType:3}}},JASS_MAX_ARRAY_SIZE:2,Kill:{Destructable:3,SoundWhenDone:bj,Unit:3},L:{ESS_THAN:{"":2,_OR_EQUAL:2},eaderboard:{AddItem:bj,Clear:3,Display:bj,Get:{I:{ndexedPlayerBJ:4,temCount:bj},LabelText:3,PlayerIndex:bj},HasPlayerItem:bj,Re:{move:{Item:3,PlayerItem:bj},sizeBJ:4},S:{et:{Item:{Label:{"":3,Color:3},Style:3,Value:{"":3,Color:3}},Label:{"":3,BJ:4,Color:bj},PlayerItem:{Label:{BJ:4,ColorBJ:4},StyleBJ:4,Value:{BJ:4,ColorBJ:4}},S:{izeByItemCount:3,tyle:bj},ValueColor:bj},ortItemsB:{J:4,y:{Label:bj,Player:bj,Value:3}}}},ivingPlayerUnitsOfTypeIdFilter:4,o:{ad:{AbilityHandle:bj,B:{oolean:{"":3,BJ:4,ExprHandle:bj},uttonHandle:bj},D:{e:{featConditionHandle:bj,structableHandle:bj},ialogHandle:bj},EffectHandle:bj,Fo:{g:{ModifierHandle:bj,StateHandle:bj},rceHandle:bj},G:{ame:bj,roupHandle:bj},HashtableHandle:3,I:{mageHandle:bj,nteger:bj,tem:{Handle:bj,PoolHandle:bj}},L:{eaderboardHandle:bj,ightningHandle:bj,ocationHandle:bj},Multiboard:{Handle:bj,ItemHandle:bj},PlayerHandle:bj,Quest:{Handle:bj,ItemHandle:bj},Re:{al:bj,ctHandle:bj,gionHandle:bj},S:{oundHandle:bj,tr:{"":3,ingBJ:4}},T:{extTagHandle:bj,imer:{DialogHandle:bj,Handle:bj},r:{ackableHandle:bj,igger:{ActionHandle:bj,ConditionHandle:bj,EventHandle:bj,Handle:bj}}},U:{bersplatHandle:bj,nit:{Handle:bj,PoolHandle:bj}},WidgetHandle:bj},c:{ation:3,kG:{ameSpeedBJ:4,uardPosition:4}}}},M:{A:{P_:{ALLIANCE_CHANGES_HIDDEN:2,C:{HEATS:{"":2,_HIDDEN:2},ONTROL_:{C:{OMPUTER:2,REEP:2},N:{EUTRAL:2,ONE:2},RESCUABLE:2,USER:2}},D:{ENSITY_:{HEAVY:2,LIGHT:2,MEDIUM:2,NONE:2},IFFICULTY_:{EASY:2,HARD:2,INSANE:2,NORMAL:2}},F:{IXED_COLORS:2,OG_:{ALWAYS_VISIBLE:2,HIDE_TERRAIN:2,MAP_EXPLORED:2}},LOC:{K_:{ALLIANCE_CHANGES:2,R:{ANDOM_SEED:2,ESOURCE_TRADING:2},SPEED:2},_PRIO_:{HIGH:2,LOW:2,NOT:2}},OBSERVERS:{"":2,_ON_DEATH:2},PLACEMENT_:{FIXED:2,RANDOM:2,TEAMS_TOGETHER:2,USE_MAP_SETTINGS:2},R:{ANDOM_:{HERO:2,RACES:2},E:{LOADED:2,SOURCE_TRADING_ALLIES_ONLY:2}},S:{HARED_ADVANCED_CONTROL:2,PEED_:{FAST:{"":2,EST:2},NORMAL:2,SLOW:{"":2,EST:2}}},USE_HANDICAPS:2},TRIX:{"3":1,"4":1}},a:{keUnit:{RescuableToForceBJ:en,sPassiveFor:{Player:en,Team:4}},rkGameStarted:4},elee:{C:{heck:{AddedUnit:4,For:{CrippledPlayers:4,LosersAndVictors:4,Victors:4},LostUnit:4},lear:{ExcessUnit:{"":4,s:4},NearbyUnits:4},rippledPlayerTimeout:4},D:{efeatDialogBJ:4,o:{D:{efeat:en,rawEnum:4},Leave:4,VictoryEnum:4}},E:{numFindNearestMine:4,xpose:{AllPlayers:4,Player:4}},FindNearestMine:4,G:{et:{Ally:{Count:4,KeyStructureCount:4,StructureCount:4},Crippled:{RevealedMessage:4,TimerMessage:4,WarningMessage:4},LocWithinRect:4,NearestValueWithin:4,ProjectedLoc:4},rant:{HeroItems:4,ItemsTo:{H:{ero:4,iredHero:4},TrainedHero:4}}},Init:{PlayerSlots:4,VictoryDefeat:4},PlayerIs:{Crippled:4,Opponent:4},R:{andomHeroLoc:4,emoveObservers:4},Starting:{AI:4,HeroLimit:4,Resources:4,Units:{"":4,ForPlayer:4,Human:4,NightElf:4,Orc:4,Un:{dead:4,knownRace:4}},Visibility:4},T:{ournamentFinishNowRuleA:4,r:{ainedUnitIsHeroBJFilter:4,igger:{Action:{AllianceChange:4,ConstructCancel:4,Player:{Defeated:4,Left:4},Unit:{ConstructionStart:4,Death:4}},TournamentFinish:{Now:4,Soon:4}}}},VictoryDialogBJ:4,WasUserPlayer:4},o:{d:{ify:{GateBJ:4,HeroS:{killPoints:4,tat:4}},ulo:{Integer:4,Real:4}},ve:{L:{ightning:{"":3,Ex:3,Loc:4},ocation:3},RectTo:loc}},ultiboard:{AllowDisplayBJ:4,Clear:3,Display:bj,Get:{ColumnCount:3,Item:3,RowCount:3,TitleText:3},Minimize:bj,ReleaseItem:3,S:{et:{ColumnCount:3,Item:{ColorBJ:4,Icon:bj,Style:bj,Value:{"":3,BJ:4,Color:3},Width:bj,s:{Icon:3,Style:3,Value:{"":3,Color:3},Width:3}},RowCount:3,TitleText:{"":3,Color:bj}},uppressDisplay:3}}},N:{OT_EQUAL:2,e:{arbyElevatorExists:en,wSoundEnvironment:3},ot:3,udge:{ItemsInRectEnum:4,ObjectsInRect:4,UnitsInRectEnum:4}},O:{ffset:{Location:4,RectBJ:4},neOnOneInitPlayerSlots:4,r:{"":3,derId:{"":3,"2String":bj}}},P:{ATHING_TYPE_:{A:{MPHIBIOUSPATHING:2,NY:2},B:{LIGHTPATHING:2,UILDABILITY:2},FL:{OATABILITY:2,YABILITY:2},PEONHARVESTPATHING:2,WALKABILITY:2},LAYER_:{COLOR_:{AQUA:2,B:{LUE:2,ROWN:2},CYAN:2,GREEN:2,LIGHT_:{BLUE:2,GRAY:2},ORANGE:2,P:{INK:2,URPLE:2},RED:2,YELLOW:2},GAME_RESULT_:{DEFEAT:2,NEUTRAL:2,TIE:2,VICTORY:2},NEUTRAL_:{AGGRESSIVE:2,PASSIVE:2},S:{CORE_:{FOOD_MAX:{PROD:2,USED:2},GOLD_:{GIVEN:2,LOST_:{TAX:2,UPKEEP:2},MINED_:{TOTAL:2,UPKEEP:2},RECEIVED:2},HERO:{ES_KILLED:2,_TOTAL:2},ITEMS_GAINED:2,LUMBER_:{GIVEN:2,LOST_:{TAX:2,UPKEEP:2},RECEIVED:2,TOTAL:2},MERCS_HIRED:2,RESOURCE_TOTAL:2,STRUCT_:{BUILT:2,RAZED:2},T:{ECH_PERCENT:2,OTAL:2},UNIT:{S_:{KILLED:2,TRAINED:2},_TOTAL:2}},LOT_STATE_:{EMPTY:2,LEFT:2,PLAYING:2},TATE_:{ALLIED_VICTORY:2,FOOD_CAP_CEILING:2,G:{AME_RESULT:2,IVES_BOUNTY:2,OLD_:{GATHERED:2,UPKEEP_RATE:2}},LUMBER_:{GATHERED:2,UPKEEP_RATE:2},NO_CREEP_SLEEP:2,OBSERVER:{"":2,_ON_DEATH:2},PLACED:2,RESOURCE_:{FOOD_:{CAP:2,USED:2},GOLD:2,HERO_TOKENS:2,LUMBER:2},UNFOLLOWABLE:2}}},a:{nCameraTo:{"":3,ForPlayer:4,LocForPlayer:4,Timed:{"":3,ForPlayer:4,Loc:{ForPlayer:4,WithZForPlayer:4},WithZ:3},WithZ:3},use:{AllUnitsBJ:en,CompAI:3,Game:{"":3,O:{ff:4,n:4}},Timer:bj,Unit:bj}},er:{centTo:{"255":4,Int:4},formStockUpdates:4},i:{ckMeleeAI:4,ngMinimap:{"":3,Ex:3,For:{Force:{"":4,Ex:4},Player:4},LocFor:{Force:{"":4,Ex:4},Player:4}}},la:{ceRandom:{Item:3,Unit:3},y:{Cinematic:3,M:{odelCinematic:3,usic:ebj},Sound:{"":4,AtPointBJ:4,BJ:4,FromOffsetBJ:4,OnUnitBJ:4},ThematicMusic:ebj,er:{"":3,GetLeaderboard:bj,SetLeaderboard:3,sAreCoAllied:4}}},o:{l:{arProjectionBJ:4,ledWait:4},stTriggerExecuteBJ:4,w:3},reload:{"":3,End:{"":3,Ex:3},Gen:{Clear:3,End:3,Start:3},Refresh:3,Start:3,er:3}},Que:{st:{CreateItem:3,ItemSet:{Completed:bj,Description:bj},MessageBJ:4,Set:{Completed:bj,D:{escription:bj,iscovered:bj},Enabled:bj,Failed:bj,IconPath:3,Required:3,Title:bj}},ue:{DestructableAnimation:bj,UnitAnimation:bj,dTrigger:{A:{ddBJ:4,ttemptExec:4},C:{heck:4,lear:{BJ:4,InactiveBJ:4},ountBJ:4},DoneBJ:4,GetIndex:4,RemoveB:{J:4,yIndex:4}}}},R:{"2":{I:3,S:{"":3,W:3}},A:{CE_:{DEMON:2,HUMAN:2,NIGHTELF:2,O:{RC:2,THER:2},PREF_:{DEMON:2,HUMAN:2,NIGHTELF:2,ORC:2,RANDOM:2,U:{NDEAD:2,SER_SELECTABLE:2}},UNDEAD:2},RITY_:{FREQUENT:2,RARE:2},bsBJ:4},M:{axBJ:4,inBJ:4},SignBJ:4,a:{d2Deg:3,ndom:{D:{estructableInRect:{BJ:en,SimpleBJ:4},ist:{AddItem:4,Choose:4,Reset:4}},ItemInRect:{BJ:en,SimpleBJ:4}}},e:{c:{t:{"":3,Contains:{Coords:4,Item:4,Loc:4,Unit:4},From:{CenterSizeBJ:4,Loc:3}},ycleGuardPosition:3},ducePlayerTechMaxAllowed:4,gi:{on:{Add:{Cell:{"":3,AtLoc:3},Rect:3},Clear:{Cell:{"":3,AtLoc:3},Rect:3}},ster:{DestDeathInRegionEnum:4,StackedSound:3}},loadGame:{"":3,CachesFromDisk:3},move:{AllGuardPositions:3,Destructable:3,GuardPosition:3,Item:{"":3,From:{AllStock:3,Stock:bj}},Location:3,P:{layer:{"":3,PreserveUnitsBJ:4},urchasedItem:4},Re:{ct:3,gion:3},Save:{Directory:bj,d:{Boolean:3,Handle:3,Integer:3,Real:3,String:3}},Unit:{"":3,From:{AllStock:3,Stock:bj}},WeatherEffect:bj},nameSaveDirectory:bj,placeUnitBJ:4,s:{cueUnitBJ:4,et:{T:{errainFog:bj,oGameCamera:{"":3,ForPlayer:4},rigger:3},U:{bersplat:3,nit:{Animation:4,LookAt:3}}},t:{artGame:3,oreUnit:{"":3,LocFacing:{AngleBJ:4,PointBJ:4}}},ume:{Music:bj,Timer:3}},viveHero:loc},otateCameraAroundLocBJ:4},S:{"2":{I:3,R:3},COPE_PR:{EFIX:2,IVATE:2},OUND_:{TYPE_EFFECT:{"":2,_LOOPED:2},VOLUMEGROUP_:{AMBIENTSOUNDS:2,COMBAT:2,FIRE:2,MUSIC:2,SPELLS:2,U:{I:2,NIT:{MOVEMENT:2,SOUNDS:2}}}},ave:{A:{bilityHandle:bj,gentHandle:3,nd:{ChangeLevelBJ:4,LoadGameBJ:4}},B:{oolean:{"":3,BJ:4,ExprHandle:bj},uttonHandle:bj},D:{e:{featConditionHandle:bj,structableHandle:bj},ialogHandle:bj,yingWidget:4},EffectHandle:bj,Fo:{g:{ModifierHandle:bj,StateHandle:bj},rceHandle:bj},G:{ame:{"":3,Cache:bj,Exists:3},roupHandle:bj},HashtableHandle:3,I:{mageHandle:bj,nteger:bj,tem:{Handle:bj,PoolHandle:bj}},L:{eaderboardHandle:bj,ightningHandle:bj,ocationHandle:bj},Multiboard:{Handle:bj,ItemHandle:bj},PlayerHandle:bj,Quest:{Handle:bj,ItemHandle:bj},Re:{al:bj,ctHandle:bj,gionHandle:bj},S:{oundHandle:bj,tr:{"":3,ingBJ:4}},T:{extTagHandle:bj,imer:{DialogHandle:bj,Handle:bj},r:{ackableHandle:bj,igger:{ActionHandle:bj,ConditionHandle:bj,EventHandle:bj,Handle:bj}}},U:{bersplatHandle:bj,nit:{Handle:bj,PoolHandle:bj}},WidgetHandle:bj},e:{lect:{Group:{BJ:en,ForPlayerBJ:4},HeroSkill:3,Unit:{"":3,Add:{"":4,ForPlayer:4},ForPlayerSingle:4,Remove:{"":4,ForPlayer:4},Single:4}},t:{A:{l:{l:{ItemTypeSlots:3,UnitTypeSlots:3,yColorFilterState:3},tMinimapIcon:3},mbient:{DaySound:4,NightSound:4}},Blight:{"":3,Loc:3,Point:3,R:{adiusLocBJ:4,ect:bj}},C:{am:{era:{Bounds:{"":3,ToRect:{"":4,ForPlayerBJ:4}},Field:{"":3,ForPlayer:4},OrientController:{"":3,ForPlayerBJ:4},Position:{"":3,ForPlayer:4,LocForPlayer:4},QuickPosition:{"":3,ForPlayer:4,Loc:{"":4,ForPlayer:4}},RotateMode:3,TargetController:{"":3,NoZForPlayer:4}},paign:{Available:bj,MenuRace:{"":3,BJ:4,Ex:3}}},ine:{Filter:{BlendMode:3,Duration:3,End:{Color:3,UV:3},Start:{Color:3,UV:3},Tex:{MapFlags:3,ture:3}},ModeVolumeGroups:{BJ:4,ImmediateBJ:4},matic:{AvailableBJ:4,Camera:{"":3,ForPlayer:4},Scene:bj}},re:{atureDensity:3,epCampFilterState:3},ustomCampaignButtonVisible:3},D:{NCSounds:{D:{a:{wn:4,y:4},usk:4},Night:4},ayNightModels:3,e:{faultDifficulty:3,st:{AnimationSpeedPercent:4,ructable:{Animation:{"":3,BJ:4,Speed:3},Invulnerable:bj,Life:{"":3,PercentBJ:4},MaxLife:bj,OccluderHeight:3}}},oodadAnimation:{"":3,BJ:4,Rect:bj}},EdCinematicAvailable:3,F:{loatGameState:3,o:{gStateR:{adius:loc,ect:3},r:{LoopIndex:{A:4,B:4},ceAllianceStateBJ:4}}},Game:{Difficulty:3,Placement:3,Speed:3,TypeSupported:3},Hero:{Agi:3,Int:3,Level:bj,St:{at:4,r:3},XP:3},I:{mage:{AboveWater:3,Co:{lor:bj,nstantHeight:3},Position:bj,Render:{"":3,Always:3},Type:3},nt:{egerGameState:3,roShot:{Model:3,Text:3}},tem:{Charges:3,Drop:{ID:3,OnDeath:bj,pable:bj},Invulnerable:bj,LifeBJ:4,P:{awnable:3,layer:bj,osition:{"":3,Loc:4}},TypeSlots:3,UserData:3,Visible:bj}},LightningColor:bj,M:{ap:{Description:3,Flag:3,Music:{"":3,IndexedBJ:4,RandomBJ:4},Name:3},issionAvailable:bj,usic:{OffsetBJ:4,PlayPosition:3,Volume:bj}},NextLevelBJ:4,OpCinematicAvailable:3,Player:{A:{bilityAvailable:bj,lliance:{"":3,BJ:4,State:{AllyBJ:4,BJ:4,ControlBJ:4,FullControlBJ:4,VisionBJ:4}}},Co:{lor:{"":3,BJ:en},ntroller:3},FlagBJ:4,Handicap:{"":3,BJ:4,XP:bj},MaxHeroesAllowed:4,Name:3,OnScoreScreen:bj,Race:{Preference:3,Selectable:3},S:{lotAvailable:4,ta:{rtLocation:3,te:bj}},T:{axRate:bj,e:{am:3,ch:{MaxAllowed:{"":3,Swap:4},Researched:{"":3,Swap:4}}}},Unit:{AvailableBJ:4,sOwner:3},s:3},R:{andomSeed:3,e:{ct:{"":3,FromLoc:3},s:{cue:{BuildingColorChangeBJ:4,UnitColorChangeBJ:4},ervedLocalHeroButtons:3,ource:{Amount:3,Density:3}}}},S:{kyModel:3,ound:{C:{hannel:3,one:{Angles:bj,Orientation:3}},D:{istance:{Cutoff:bj,s:3},uration:3},OffsetBJ:4,P:{aramsFromLabel:3,itch:bj,layPosition:3,osition:{"":3,LocBJ:4}},V:{elocity:3,olume:bj}},peechVolumeGroups:{BJ:4,ImmediateBJ:4},ta:{ckedSoundBJ:4,rtLocPrio:{"":3,Count:3}}},T:{e:{ams:3,rrain:{Fog:{"":3,Ex:bj},Pathable:bj,Type:bj},xtTag:{Age:bj,Color:bj,Fadepoint:bj,Lifespan:bj,P:{ermanent:bj,os:{"":3,BJ:4,Unit:bj}},Suspended:bj,Text:bj,V:{elocity:bj,isibility:3}}},hematicMusic:{OffsetBJ:4,PlayPosition:3},imeOfDay:{"":4,Scale:{"":3,PercentBJ:4}},utorialCleared:3},U:{bersplatRender:{"":3,Always:3},nit:{A:{bilityLevel:sw,cquireRange:bj,nimation:{"":3,ByIndex:3,WithRarity:3}},BlendTime:bj,C:{olor:3,reepGuard:3},Exploded:bj,F:{acing:{"":3,T:{imed:3,oFace:{LocTimed:4,UnitTimed:4}}},lyHeight:bj,og:3},Invulnerable:3,L:{ife:{BJ:4,PercentBJ:4},ookAt:3},M:{ana:{BJ:4,PercentBJ:4},oveSpeed:3},Owner:3,P:{athing:3,osition:{"":3,Loc:{"":3,Facing:{BJ:4,LocBJ:4}}},ropWindow:bj},R:{ally:{Destructable:4,Point:4,Unit:4},escu:{able:3,eRange:3}},S:{cale:{"":3,Percent:4},tate:3},T:{imeScale:{"":3,Percent:4},urnSpeed:bj,ypeSlots:3},Use:{Food:bj,rData:3},VertexColor:bj,X:3,Y:3},serControlForceO:{ff:4,n:4}},W:{ater:{BaseColor:bj,Deforms:3},idgetLife:3}}},h:{areEverythingWithTeam:{"":4,AI:4},ow:{CustomCampaignButton:4,Destructable:bj,I:{mage:bj,nterface:{"":3,ForceO:{ff:4,n:4}}},TextTagForceBJ:4,U:{bersplat:bj,nit:{"":3,Hide:4,Show:4}}}},"in":bj,martCameraPanBJ:4,quareRoot:3,t:{art:{CampaignAI:3,MeleeAI:3,S:{ound:{"":3,ForPlayerBJ:4},tockUpdates:4},TimerBJ:4},o:{p:{Camera:{"":3,ForPlayerBJ:4},Music:bj,Sound:bj},re:{Boolean:bj,Integer:bj,Real:bj,String:bj,Unit:bj}},ring:{"2":{OrderIdBJ:4,UnitIdBJ:4},Case:3,Hash:bj,Identity:4,Length:3}},u:{bString:bj,spend:{HeroXP:bj,TimeOfDay:3}},yncS:{elections:3,tored:{Boolean:3,Integer:3,Real:3,String:3,Unit:3}}},T:{EXMAP_FLAG_:{NONE:2,WRAP_:{U:{"":2,V:2},V:2}},RUE:2,an:bj,e:{amInitPlayerSlots:4,rrainDeform:{Crater:3,R:{andom:3,ipple:3},Stop:{"":3,All:3},Wave:3,ation:{CraterBJ:4,R:{andomBJ:4,ippleBJ:4},StopBJ:4,WaveBJ:4}},xtTagS:{ize2Height:4,peed2Velocity:4}},imer:{Dialog:{Display:{"":3,BJ:4,ForPlayerBJ:4},Set:{RealTimeRemaining:3,Speed:bj,Ti:{meColor:bj,tle:{"":3,BJ:4,Color:bj}}}},Get:{Elapsed:3,Remaining:3,Timeout:3},Start:3},r:{ansmissionFromUnit:{TypeWithNameBJ:4,WithNameBJ:4},igger:{A:{ctionUnitRescuedBJ:4,dd:{Action:3,Condition:3}},Clear:{Actions:3,Conditions:3},E:{valuate:3,xecute:{"":3,BJ:4,Wait:3}},Re:{gister:{AnyUnit:{Damaged:3,EventBJ:4},BuildSubmenuEventBJ:4,D:{e:{athEvent:3,stDeathInRegionEvent:4},i:{alog:{ButtonEvent:3,Event:bj},stanceBetweenUnits:4}},EnterRe:{ctSimple:4,gion:{"":3,Simple:4}},FilterUnitEvent:3,Game:{Event:3,LoadedEventBJ:4,S:{avedEventBJ:4,tateEvent:{"":3,TimeOfDay:4}}},LeaveRe:{ctSimple:4,gion:{"":3,Simple:4}},Player:{AllianceChange:3,ChatEvent:3,Event:{"":3,AllianceChanged:4,Defeat:4,EndCinematic:4,Leave:4,Victory:4},KeyEventBJ:4,S:{electionEventBJ:4,tateEvent:3},UnitEvent:{"":3,Simple:4}},ShowSkillEventBJ:4,T:{imerE:{vent:{"":3,Periodic:4,Single:4},xpireEvent:bj},rackable:{HitEvent:3,TrackEvent:3}},Unit:{Event:3,InRange:{"":3,Simple:4},LifeEvent:4,ManaEvent:4,StateEvent:3},VariableEvent:3},move:{Action:3,Condition:3}},S:{leepAction:3,ync:{Ready:3,Start:3}},Wait:{ForSound:3,OnSleeps:3}},yInit:{CinematicBehaviorBJ:4,RescuableTriggersBJ:4}}},U:{NIT_:{STATE_:{LIFE:2,MA:{NA:2,X_:{LIFE:2,MANA:2}}},TYPE_:{A:{NCIENT:2,TTACKS_:{FLYING:2,GROUND:2}},DEAD:2,ETHEREAL:2,FLYING:2,G:{IANT:2,ROUND:2},HERO:2,M:{AGIC_IMMUNE:2,E:{CHANICAL:2,LEE_ATTACKER:2}},P:{EON:2,LAGUED:2,O:{ISONED:2,LYMORPHED:2}},R:{ANGED_ATTACKER:2,ESISTANT:2},S:{APPER:2,LEEPING:2,NARED:2,T:{RUCTURE:2,UNNED:2},UMMONED:2},T:{AUREN:2,OWNHALL:2},UNDEAD:2}},n:{it:{A:{dd:{Ability:bj,I:{ndicator:bj,tem:{"":3,ById:sw,Swapped:4,ToSlotById:3}},Sleep:{"":3,Perm:3},Type:bj},live:3,pplyTimedLife:bj},C:{anSleep:{"":3,BJ:4,Perm:3},ountBuffsEx:bj},D:{amage:{Point:{"":3,Loc:4},Target:bj},ropItem:{"":4,Point:{"":3,BJ:4,Loc:4},Slot:bj,Target:bj}},GenerateAlarms:4,Has:{Buff:{BJ:4,sEx:3},Item:{"":3,OfTypeBJ:4}},I:{d:{"":3,"2":{OrderIdBJ:4,String:bj}},gnoreAlarm:{"":3,Toggled:3},nventory:{Count:4,Size:bj},sSleeping:bj,temInSlot:bj},M:{akeAbilityPermanent:bj,odifySkillPoints:3},P:{auseTimedLife:bj,ool:{AddUnitType:3,RemoveUnitType:3}},Re:{move:{Ability:bj,Buff:{BJ:4,s:ebj},Item:{"":3,FromSlot:sw,Swapped:4},Type:bj},setCooldown:3},S:{et:{C:{anSleepBJ:4,onstructionProgress:3},U:{pgradeProgress:3,sesAltIcon:bj}},hareVision:bj,tripHeroLevel:3,uspendDecay:bj},UseItem:{"":3,Destructable:4,Point:{"":3,Loc:4},Target:3},WakeUp:bj,s:{In:{Group:3,R:{ange:{"":3,OfLoc:3},ect:3}},Of:{Player:3,Type:3},Selected:3}},lockGameSpeedBJ:4,registerStackedSound:3},pdate:{EachStockBuilding:en,StockAvailability:4},seTimeOfDayBJ:4},V:{E:{CTOR3:1,RSION_:{FROZEN_THRONE:2,REIGN_OF_CHAOS:2}},ersion:{Compatible:3,Get:3,Supported:3},olumeGroup:{Reset:{"":3,BJ:4,ImmediateBJ:4},SetVolume:{"":3,BJ:4,ForPlayerBJ:4}}},W:{AR3VER:{"":2,_2:{"3":2,"4":2}},EA:{PON_TYPE_:{AXE_MEDIUM_CHOP:2,CLAW_:{HEAVY_SLICE:2,LIGHT_SLICE:2,MEDIUM_SLICE:2},METAL_:{HEAVY_:{BASH:2,CHOP:2,S:{LICE:2,TAB:2}},LIGHT_:{CHOP:2,SLICE:2},MEDIUM_:{BASH:2,CHOP:2,S:{LICE:2,TAB:2}}},ROCK_HEAVY_BASH:2,W:{HOKNOWS:2,OOD_:{HEAVY_:{BASH:2,SLICE:2},LIGHT_:{BASH:2,S:{LICE:2,TAB:2}},MEDIUM_:{BASH:2,S:{LICE:2,TAB:2}}}}},THER_ON_MARS:2},a:{it:{ForSoundBJ:4,TransmissionDuration:4},kePlayerUnits:en,ygate:{Activate:bj,GetDestination:{LocBJ:4,X:3,Y:3},IsActive:bj,SetDestination:{"":3,LocBJ:4}}},idgetDropItem:4},a:{bility:1,gent:1,idifficulty:1,ll:{iancetype:1,ocate:3},nd:0,rray:1,ttacktype:1},b:{j_:{ALLIANCE_:{ALLIED:{"":2,_:{ADVUNITS:2,UNITS:2,VISION:2}},NEUTRAL:{"":2,_VISION:2},UNALLIED:{"":2,_VISION:2}},BUFF_:{POLARITY_:{EITHER:2,NEGATIVE:2,POSITIVE:2},RESIST_:{BOTH:2,EITHER:2,MAGIC:2,PHYSICAL:2}},C:{AM:{ERA:{BOUNDS_ADJUST_:{ADD:2,SUB:2},_:{DEFAULT_:{AOA:2,DISTANCE:2,F:{ARZ:2,OV:2},RO:{LL:2,TATION:2}},MIN_FARZ:2}},PAIGN_:{INDEX_:rcs,OFFSET_:rcs}},ELLWIDTH:2,INE:{FADETYPE_FADE:{IN:2,OUT:{"":2,IN:2}},M:{ATICINDEX_:{H:{ED:2,OP:2},N:{ED:2,OP:2},O:{ED:2,OP:2},TOP:2,U:{ED:2,OP:2},X:{ED:2,OP:2}},ODE_:{GAMESPEED:2,INTERFACEFADE:2,VOLUME_:{AMBIENTSOUNDS:2,COMBAT:2,FIRE:2,MUSIC:2,SPELLS:2,U:{I:2,NIT:{MOVEMENT:2,SOUNDS:2}}}}}},LIFFHEIGHT:2,ORPSE:{TYPE_:{BONE:2,FLESH:2},_MAX_DEATH_TIME:2},REEP_ITEM_DELAY:2},DEGTORAD:2,E:{"":2,LEVATOR_:{BLOCKER_CODE:2,CODE0:{"1":2,"2":2},WALL_TYPE_:{ALL:2,EAST:2,NORTH:2,SOUTH:2,WEST:2}}},FORCE_:{ALL_PLAYERS:2,PLAYER:2},GA:{ME:{CACHE_:{BOOLEAN:2,INTEGER:2,REAL:2,STRING:2,UNIT:2},_STARTED_THRESHOLD:2},TEOPERATION_:{CLOSE:2,DESTROY:2,OPEN:2}},H:{A:{NDICAP_EASY:2,SHTABLE_:{BOOLEAN:2,HANDLE:2,INTEGER:2,REAL:2,STRING:2}},EROSTAT_:{AGI:2,INT:2,STR:2}},ITEM:{CODE_STATUS_:{P:{AWNABLE:2,OWERUP:2},SELLABLE:2},_STATUS_:{HIDDEN:2,INVULNERABLE:2,OWNED:2,P:{AWNABLE:2,OWERUP:2},SELLABLE:2}},KEYEVENT:{KEY_:{DOWN:2,LEFT:2,RIGHT:2,UP:2},TYPE_:{DEPRESS:2,RELEASE:2}},M:{AX_:{DEST_IN_REGION_EVENTS:2,I:{NVENTORY:2,TEM_LEVEL:2},PLAYER:{S:2,_SLOTS:2},QUEUED_TRIGGERS:2,S:{KELETONS:2,TOCK_:{ITEM_SLOTS:2,UNIT_SLOTS:2}}},ELEE_:{C:{LEAR_UNITS_RADIUS:2,RIPPLE_:{MSG_DURATION:2,TIMEOUT:2}},HERO_:{LIMIT:2,TYPE_LIMIT:2},M:{AX_TWINKED_HEROES:{"":2,_V:[2,2]},INE_SEARCH_RADIUS:2},STARTING_:{GOLD_V:[2,2],HERO_TOKENS:2,LUMBER_V:[2,2],TOD:2}},I:{NIMAPPINGSTYLE_:{ATTACK:2,FLASHY:2,SIMPLE:2},SSION_INDEX_:{H:[ten2,[2,2]],N0:ten2,O:{"0":ten2,"10":2},T0:[2,2],U:[ten2,[2,2]],X:{H0:ten2,N:{"0":ten2,"10":2},O00:2,U:[ten2,[2,2,2,2]]}}},ODIFYMETHOD_:{ADD:2,S:{ET:2,UB:2}}},NOTHING_SOUND_DURATION:2,P:{I:2,LAYER_NEUTRAL_:{EXTRA:2,VICTIM:2},OLLED_WAIT_:{INTERVAL:2,SKIP_THRESHOLD:2}},QUE:{ST:{MESSAGE_:{ALWAYSHINT:2,COMPLETED:2,DISCOVERED:2,FAILED:2,HINT:2,ITEMACQUIRED:2,MISSIONFAILED:2,REQUIREMENT:2,SECRET:2,U:{NITA:{CQUIRED:2,VAILABLE:2},PDATED:2},WARNING:2},TYPE_:{OPT_:{DISCOVERED:2,UNDISCOVERED:2},REQ_:{DISCOVERED:2,UNDISCOVERED:2}}},UE:{D_TRIGGER_TIMEOUT:2,_DELAY_:{HINT:2,QUEST:2,SECRET:2}}},R:{ADTODEG:2,E:{MOVEBUFFS_:{ALL:2,N:{EGATIVE:2,ONTLIFE:2},POSITIVE:2},SCUE_PING_TIME:2}},S:{MARTPAN_TRESHOLD_:{PAN:2,SNAP:2},ORTTYPE_SORTBY:{LABEL:2,PLAYER:2,VALUE:2},PEECH_VOLUME_:{AMBIENTSOUNDS:2,COMBAT:2,FIRE:2,MUSIC:2,SPELLS:2,U:{I:2,NIT:{MOVEMENT:2,SOUNDS:2}}},TOCK_:{MAX_ITERATIONS:2,RESTOCK_IN:{ITIAL_DELAY:2,TERVAL:2}}},T:{EXT_DELAY_:{ALWAYSHINT:2,HINT:2,ITEMACQUIRED:2,MISSIONFAILED:2,QUEST:{"":2,DONE:2,FAILED:2,REQUIREMENT:2,UPDATE:2},SECRET:2,UNITA:{CQUIRED:2,VAILABLE:2},WARNING:2},IMETYPE_:{ADD:2,S:{ET:2,UB:2}},OD_D:{AWN:2,USK:2},RANSMISSION_:{IND_:{ALPHA:2,BLUE:2,GREEN:2,RED:2},P:{ING_TIME:2,ORT_HANGTIME:2}}},UNIT_:{FACING:2,STATE_METHOD_:{ABSOLUTE:2,DEFAULTS:2,MAXIMUM:2,RELATIVE:2}},WAIT_FOR_COND_MIN_INTERVAL:2,attackByHand:2,c:{hangeLevel:{MapName:2,ShowScores:2},ine:{Fade:{Continue:{Blue:2,Duration:2,Green:2,Red:2,T:{ex:2,imer:2,rans:2}},FinishTimer:2},Mode:{AlreadyIn:2,Prior:{DawnDusk:2,FogSetting:2,MaskSetting:2,Speed:2},SavedSeed:2},Scene:{BeingSkipped:2,EndingTimer:2,LastSound:2}},rippledTimer:{"":2,Windows:2}},d:{a:{wnSound:2,yAmbientSound:2},e:{featDialogSound:2,layedSuspendDecayT:{imer:2,rig:2},st:{InRegionDies:{Count:2,Trig:2},RandomC:{onsidered:2,urrentPick:2}}},nc:{IsDaytime:2,Sounds:{D:{a:{wn:2,y:2},usk:2},Night:2}},uskSound:2},e:{levator:{Neighbor:2,WallBlocker:2},numDestructable:{Center:2,Radius:2}},f:{inishSoon:{AllExposed:2,TimerDialog:2},or:{Loop:{AIndex:{"":2,End:2},BIndex:{"":2,End:2}},ce:{CountPlayers:2,RandomC:{onsidered:2,urrentPick:2}}}},g:{ameStarted:{"":2,Timer:2},houl:2,roup:{AddGroupDest:2,CountUnits:2,Enum:{OwningPlayer:2,TypeId:2},LastCreatedDest:2,R:{andomC:{onsidered:2,urrentPick:2},emoveGroupDest:2}}},i:{s:{SinglePlayer:2,UnitGroup:{DeadResult:2,EmptyResult:2,InRectRe:{ct:2,sult:2}}},temRandomC:{onsidered:2,urrentPick:2}},l:{ast:{AttackType:2,Created:{Button:2,De:{featCondition:2,structable:2},Effect:2,FogModifier:2,G:{ameCache:2,roup:2},Hashtable:2,I:{mage:2,tem:2},L:{eaderboard:2,ightning:2},Multiboard:2,Quest:{"":2,Item:2},T:{e:{rrainDeformation:2,xtTag:2},imerDialog:2},U:{bersplat:2,nit:2},WeatherEffect:2},D:{amage:{Amount:2,Source:2,T:{arget:2,ype:2}},yingWidget:2},HauntedGoldMine:2,LoadedUnit:2,Played:{Music:2,Sound:2},Re:{movedItem:2,placedUnit:2},StartedTimer:2,TransmissionDuration:2},ivingPlayerUnitsTypeId:2},m:{a:{keUnitRescuable:{Flag:2,Unit:2},pInitial:{CameraBounds:2,PlayableArea:2}},elee:{Defeated:2,G:{ameOver:2,rantHeroItems:2},NearestMine:{"":2,Dist:2,ToLoc:2},TwinkedHeroes:2,Vi:{ctoried:2,sibility:{IsDay:2,Trained:2}}}},nightAmbientSound:2,p:{auseAllUnitsFlag:2,layerIs:{Crippled:2,Exposed:2}},que:{st:{CompletedSound:2,DiscoveredSound:2,FailedSound:2,HintSound:2,ItemAcquiredSound:2,SecretSound:2,UpdatedSound:2,WarningSound:2},uedExec:{T:{imeout:{"":2,Timer:2},otal:2,riggers:2},UseConds:2}},r:{and:{Dist:{C:{hance:2,ount:2},ID:2},omSubGroup:{Chance:2,Group:2,Total:2,Want:2}},escue:{ChangeColor:{Bldg:2,Unit:2},Sound:2,UnitBehavior:2}},s:{etPlayerTargetColor:2,lotControl:{"":2,Ready:2,Used:2},tock:{Allowed:{Artifact:2,Charged:2,Permanent:2},ItemPurchased:2,PickedItem:{Level:2,Type:2},UpdateTimer:2},uspendDecay:{BoneGroup:2,FleshGroup:2}},useDawnDuskSounds:2,v:{ictoryDialogSound:2,olumeGroupsTimer:2},wantDestroyGroup:2},lendmode:1,ool:{"":1,e:{an:1,xpr:1}},reak:0,u:{ff:1,tton:1}},c:{a:{ll:{"":0,back:0},mera:{field:1,setup:1}},o:{de:1,n:{ditionfunc:1,stant:0}},reate:3},d:{amagetype:1,e:{allocate:3,bug:0,f:{aults:0,eatcondition:1,ine:0},legate:0,str:{oy:3,uctable:1}},ialog:{"":1,event:1},o:{"":0,wnto:0}},e:{ffect:{"":1,type:1},lse:{"":0,"if":0},n:{d:{define:0,"enum":0,f:{or:0,unction:0},globals:0,i:{f:0,nterface:0},l:{ibrary:0,oop:0},m:{ethod:0,odule:0},repeat:0,s:{cope:0,truct:0},vblock:0,"while":{"":0,not:0}},um:0},rror:0,v:{aluate:3,ent:{"":1,id:1}},x:{ecute:3,i:{sts:2,twhen:0},tends:0}},f:{alse:2,gamestate:1,ilter:{EnumDestructablesInCircleBJ:2,GetUnits:{InRectOfPlayer:2,Of:{PlayerAndTypeId:2,TypeIdAll:2}},IssueHauntOrderAtLocBJ:2,LivingPlayerUnitsOfTypeId:2,MeleeTrainedUnitIsHeroBJ:2,func:1},l:{oat:1,ush:0},o:{g:{modifier:1,state:1},r:{"":0,ce:1}},unction:0},g:{ame:{cache:1,difficulty:1,event:1,s:{peed:1,tate:1},type:1},etType:3,lobals:0,roup:1,uard:0},h:{a:{ndle:1,shtable:1},ook:0},i:{f:0,gamestate:1,m:{age:1,plement:0},n:{clude:0,itializer:0,t:{"":1,e:{ger:1,rface:0}}},tem:{"":1,pool:1,type:1}},key:{"":1,word:0},l:{ambda:0,eaderboard:1,i:{brary:{"":0,_once:0},ghtning:1,mitop:1},o:{ca:{l:{"":0,s:0},tion:1},op:0}},m:{ap:{control:1,density:1,flag:1,setting:1,visibility:1},ethod:0,odule:0,ultiboard:{"":1,item:1}},n:{a:{me:2,tive:0},e:{eds:0,w:0},ot:{"":0,hing:1},ull:2},o:{n:{Destroy:3,Hero:{Level:3,Skill:3},Init:3,Unit:{Attacked:3,D:{e:{ath:3,cay:3},ropItem:3},Issued:{Order:3,PointOrder:3,TargetOrder:3},P:{awnItem:3,ickupItem:3},S:{ellItem:3,pell:{C:{ast:3,hannel:3},E:{ffect:3,ndcast:3},Finish:3}},UseItem:3}},p:{erator:0,tional:0},r:{"":0,der_:{AImove:2,a:{bsorb:2,c:{idbomb:2,olyteharvest:2},mbush:2,n:{cestralspirit:{"":2,target:2},imatedead:2,timagicshell:2},tt:{ack:{"":2,ground:2,once:2},ributemodskill:2},u:{ra:{unholy:2,vampiric:2},to:{dispel:fn,entangle:{"":2,instant:2},harvest:{gold:2,lumber:2}}},v:{atar:2,engerform:2},waken:2},b:{a:{nish:2,rkskin:fn,ttle:{roar:2,stations:2}},e:{arform:2,rserk:2},l:{ackarrow:fn,i:{ght:2,nk:2,zzard:2},oodlust:fn},oard:2,reathoff:{ire:2,rost:2},u:{ild:2,rrow:2}},c:{a:{nnibalize:2,rrions:{carabs:{"":2,instant:2,o:ffn},warm:2}},h:{a:{inlightning:2,nnel:2,rm:2},emicalrage:2},l:{oudoffog:2,usterrockets:2},o:{ldarrows:{"":2,targ:2},ntrolmagic:2,r:{porealform:2,rosivebreath:2},uple:{instant:2,target:2}},r:{eep:{animatedead:2,devour:2,heal:fn,thunder:{bolt:2,clap:2}},ipple:2},urse:fn,yclone:2},d:{ark:{conversion:2,portal:2,ritual:2,summoning:2},e:{ath:{anddecay:2,coil:2,pact:2},couple:2,fend:2,t:{ectaoe:2,onate:2},vour:{"":2,magic:2}},i:{s:{associate:2,enchant:2,mount:2,pel:2},vineshield:2},oom:2,r:{ain:2,eadlordinferno:2,opitem:2,unkenhaze:2}},e:{a:{rthquake:2,ttree:2},lementalfury:2,n:{snare:fn,tangl:{e:{"":2,instant:2},ingroots:2}},therealform:2,vileye:2},f:{a:{eriefire:fn,nofknives:2,rsight:2},i:{ngerofdeath:2,rebolt:2},la:{m:{estrike:2,inga:{rrows:{"":2,targ:2},ttack:{"":2,targ:2}}},re:2},or:{ce:{board:2,ofnature:2},kedlightning:2},r:{e:{ezingbreath:2,nzy:fn},ost:{armor:fn,nova:2}}},g:{etitem:2,old2lumber:2,rabtree:2},h:{arvest:2,e:{al:{"":2,ing:{spray:2,wa:{rd:2,ve:2}},o:ffn},x:2},o:{l:{dposition:2,ybolt:2},wlofterror:2},umanbuild:2},i:{m:{molation:2,pale:2},n:{cineratearrow:fn,ferno:2,nerfire:fn,stant:2,visibility:2},tem:{drag0:six2,use0:six2}},l:{avamonster:2,ightningshield:2,o:{ad:{"":2,archer:2,corpse:{"":2,instant:2}},custswarm:2},umber2gold:2},m:{a:{gic:{defense:2,leash:2,undefense:2},na:{burn:2,flareo:ffn,shieldo:ffn},ssteleport:2},e:{chanicalcritter:2,tamorphosis:2},i:{litia:{"":2,convert:2,off:2,unconvert:2},ndrot:2,rrorimage:2},o:{nsoon:2,unt:{"":2,hippogryph:2},ve:2}},n:{agabuild:2,eutral:{detectaoe:2,interact:2,spell:2},ightelfbuild:2},orcbuild:2,p:{a:{rasite:fn,trol:2},h:{aseshift:{"":2,instant:2,o:ffn},oenix:{fire:2,morph:2}},o:{isonarrows:{"":2,targ:2},lymorph:2,ssession:2},reservation:2,urge:2},r:{a:{i:{nof:{chaos:2,fire:2},sedead:fn},venform:2},e:{charge:fn,juvination:2,"new":fn,p:{air:fn,lenish:{"":2,life:fn,mana:fn,o:ffn}},quest:{_hero:2,sacrifice:2},s:{toration:fn,u:{me:{build:2,harvesting:2},rrection:2}},turnresources:2,v:{enge:2,ive:2}},o:{ar:2,bogoblin:2,ot:2}},s:{a:{crifice:2,nctuary:2},cout:2,e:{lfdestruct:fn,ntinel:2,trally:2},h:{adows:{ight:2,trike:2},ockwave:2},ilence:2,l:{eep:2,ow:fn},mart:2,oul:{burn:2,preservation:2},p:{ells:{hield:{"":2,aoe:2},teal:fn},i:{es:2,rit:{link:2,ofvengeance:2,troll:2,wolf:2}}},t:{a:{mpede:2,nddown:2,rfall:2,sistrap:2},eal:2,o:{mp:2,neform:2,p:2}},u:{bmerge:2,mmon:{factory:2,grizzly:2,phoenix:2,quillbeast:2,wareagle:2}}},t:{a:{nk:{droppilot:2,loadpilot:2,pilot:2},unt:2},hunder:{bolt:2,clap:2},o:{rnado:2,wnbello:ffn},ran:{quility:2,smute:2}},un:{av:{atar:2,engerform:2},b:{earform:2,urrow:2},co:{ldarrows:2,rporealform:2},d:{e:{adbuild:2,fend:2},ivineshield:2},etherealform:2,flaminga:{rrows:2,ttack:2},holyfrenzy:2,immolation:2,load:{"":2,all:{"":2,corpses:2,instant:2}},poisonarrows:2,r:{avenform:2,o:{bogoblin:2,ot:2}},s:{t:{ableconcoction:2,oneform:2},u:{bmerge:2,mmon:2}},windwalk:2},v:{engeance:{"":2,instant:2,o:ffn},o:{lcano:2,odoo:2}},w:{a:{rd:2,ter:{elemental:2,yminion:2}},eb:fn,hirlwind:2,i:{ndwalk:2,spharvest:2}}}}},p:{athingtype:1,la:{cement:1,yer:{"":1,color:1,event:1,gameresult:1,s:{core:1,lotstate:1,tate:1},unitevent:1}},ri:{ntf:3,vate:0},ublic:0},quest:{"":1,item:1},r:{a:{ce:{"":1,preference:1},ritycontrol:1},e:{a:{donly:0,l:1},ct:1,gion:1,peat:0,quires:0,turn:{"":0,s:0}}},s:{BJDebugMsg:4,Di:{alog:{Add:{Button:3,QuitButton:3},SetMessage:3},splayT:{extToPlayer:3,imedText:{FromPlayer:3,ToPlayer:3}}},LeaderboardAddItem:3,MultiboardSet:{Item:{Value:3,sValue:3},TitleText:3},Quest:{ItemSetDescription:3,Set:{Description:3,Title:3}},SetTextTagText:3,cope:0,et:{"":0,def:0},ize:2,ound:{"":1,type:1},printf:3,t:{a:{rtlocprio:1,tic:0},r:{ing:1,uct:0},ub:0},uper:2},t:{akes:0,e:{rraindeformation:1,x:{mapflags:1,ttag:1}},h:{en:0,is:{"":2,type:1}},imer:{"":1,dialog:1},o:0,r:{ackable:1,igger:{"":1,action:1,condition:1},ue:2},ype:{"":0,id:2}},u:{bersplat:1,n:{def:0,it:{"":1,event:1,pool:1,state:1,type:1}},se:{"":0,s:0}},v:{block:0,ersion:1,o:{id:1,lumegroup:1}},w:{ea:{pontype:1,thereffect:1},hile:{"":0,not:0},idget:{"":1,event:1}}};

//===========================================================================
// Секция конфигурации - регистрация тегов.
//===========================================================================

function bbAlign(str) {
    switch (str) {
        case "c": case "center": return "center";
        case "r": case "right":  return "right";
        case "l": case "left":   return "left";
        case "t": case "top":    return "top";
        case "b": case "bottom": return "bottom";
    }
    //return undefined;
}

function bbAlg(s) {
    return function(/*parser*/) {
        return bbAlign(this.args[s]) || "";
    };
}

function bbLast(e) {
    return e.lastChild;
}

function bbFragment(parser) {
    var f = document.createDocumentFragment();
    parser.insertContent(f, this.content);
    return f;
}

function bbUnholded(parser) {
    parser.raiseWarning("Использование тега [" + this.name + "] вне [" + this.holder + "]!");
    return document.createDocumentFragment();
}

function BbB() { this.content = [ ]; }
BbB.prototype.name = "b";

function BbI() { this.content = [ ]; }
BbI.prototype.name = "i";

function BbU() { this.content = [ ]; }
BbU.prototype.name = "u";

function BbS() { this.content = [ ]; }
BbS.prototype.name = "s";

function BbO() { this.content = [ ]; }
BbO.prototype = {
    name: "o",
    htmlName: "span",
    cssArgs: { textDecoration: "overline" }
};

function BbSub() { this.content = [ ]; }
BbSub.prototype.name = "sub";

function BbSup() { this.content = [ ]; }
BbSup.prototype.name = "sup";

function BbHr() { this.args = { }; }
BbHr.prototype = {
    name: "hr",
    bbArgs: [ "", "align", "color", "width" ],
    htmlArgs: { align: "$=0$", className: "bbHr" },
    cssArgs: { cssText: "background-color: $color$; color: $color$; height: $$px; width: $width$px;" },
    funcs: [ bbAlg("align") ],
    trim: true
};

function BbC() { this.content = [ ]; }
BbC.prototype = {
    name: "c",
    htmlName: "center",
    trim: true
};

function BbL() { this.content = [ ]; }
BbL.prototype = {
    name: "l",
    htmlName: "div",
    htmlArgs: { align: "left" },
    trim: true
};

function BbR() { this.content = [ ]; }
BbR.prototype = {
    name: "r",
    htmlName: "div",
    htmlArgs: { align: "right" },
    trim: true
};

function BbJ() { this.content = [ ]; }
BbJ.prototype = {
    name: "j",
    htmlName: "div",
    htmlArgs: { align: "justify" },
    trim: true
};

function BbUrl() {
    this.content = [ ];
    this.args = { };
}
BbUrl.prototype = {
    name: "url",
    bbArgs: [ "" ],
    htmlName: "a",
    htmlArgs: { href: "$$", rel: "nofollow", target: "_blank", className: "bbUrl" }
};

function bbMakeLabel(parser) {
    if ("" in this.args)
        return "bb-" + parser.execCount + "-" + this.args[""];
    //return undefined;
}

function BbSharp() { this.args = { }; }
BbSharp.prototype = {
    name: "#",
    bbArgs: [ "" ],
    htmlName: "span",
    htmlArgs: { id: "$=0$" },
    funcs: [ bbMakeLabel ],
    trim: true
};

function BbGoTo() {
    this.content = [ ];
    this.args = { };
}
BbGoTo.prototype = {
    name: "goto",
    bbArgs: [ "" ],
    htmlName: "a",
    htmlArgs: { href: "#$=0$", className: "bbGoTo" },
    funcs: [ bbMakeLabel ]
};

function BbImg() { this.args = { }; }
BbImg.prototype = {
    name: "img",
    bbArgs: [ "", "width", "height" ],
    htmlArgs: { src: "$$", alt: "Изображение", className: "bbImg" },
    cssArgs: { width: "$width$px", height: "$height$px" }
};

function BbMsg() {
    this.content = [ ];
    this.args = { };
}
BbMsg.prototype = {
    name: "msg",
    bbArgs: [ "" ],
    htmlName: "span",
    htmlArgs: { title: "$$" }
};

function BbFloat() {
    this.content = [ ];
    this.args = { };
}
BbFloat.prototype = {
    name: "float",
    bbArgs: [ "" ],
    htmlName: "div",
    htmlArgs: { className: "bbFloat" },
    cssArgs: { cssFloat: "$=0$" },
    funcs: [ bbAlg("") ],
    trim: true
};

function BbClear() { this.args = { }; }
BbClear.prototype = {
    name: "clear",
    bbArgs: [ "" ],
    htmlName: "div",
    cssArgs: { clear: "$=0$" },
    funcs: [ function(/*parser*/) { return bbAlign(this.args[""]) || "both"; } ],
    trim: true
};

function BbSize() {
    this.content = [ ];
    this.args = { };
}
BbSize.prototype = {
    name: "size",
    htmlName: "font",
    bbArgs: [ "" ],
    cssArgs: { fontSize: "$$pt" }
};

function BbColor() {
    this.content = [ ];
    this.args = { };
}
BbColor.prototype = {
    name: "color",
    htmlName: "font",
    bbArgs: [ "" ],
    cssArgs: { color: "$$" }
};

function BbFont() {
    this.content = [ ];
    this.args = { };
}
BbFont.prototype = {
    name: "font",
    bbArgs: [ "", "size", "color" ],
    htmlArgs: { face: "$$", color: "$color$" },
    cssArgs: { fontSize: "$size$pt" }
};

function BbEnt() { this.args = { }; }
BbEnt.prototype = {
    name: "ent",
    bbArgs: [ "" ],
    htmlName: "span",
    htmlArgs: { innerHTML: "&$=0$;" },
    rx: /[^\w\d]/g,
    funcs: [
        function(/*parser*/) {
            var s = this.args[""];
            if (s) {
                this.rx.lastIndex = s.charAt(0) == '#';
                return this.rx.test(s) ? s.substr(0, this.rx.lastIndex - 1) : s;
            }
            //return undefined;
        }
    ]
};

function BbQuote() {
    this.content = [ ];
    this.args = { };
}
BbQuote.prototype = {
    name: "quote",
    bbArgs: [ "" ],
    htmlName: "div",
    htmlArgs: {
        innerHTML: "<div class='bbQuoteHeader'><span class='bbQuoteQuote'>Цитата</span>$=0$</div><div class='bbQuoteMessage'></div>",
        className: "bbQuoteContainer"
    },
    rx: /&|</g,
    replacer: function(s) { return s == '&' ? "&amp;" : "&lt;"; },
    funcs: [
        function(/*parser*/) {
            var a = this.args[""];
            if (a)
                return " (<span class='bbQuoteAuthor'>" + a.replace(this.rx, this.replacer) + "</span>)";
            //return undefined;
        }
    ],
    target: bbLast,
    trim: true
};

function bbSpoilerHandler(f, o, c) {
    var b = f.firstChild;
    var d = f.lastChild;
    var v = d.style.display != "none";
    d.style.display = v ? "none" : "block";
    b.value = v ? o : c;
}

function BbSpoiler() {
    this.content = [ ];
    this.args = { };
}
BbSpoiler.prototype = {
    name: "spoiler",
    bbArgs: [ "", "close", "align" ],
    trim: true,
    toDom: function(parser) {
        var o = this.args[""];
        var c = this.args["close"];
        if (o === undefined) {
            o = "Открыть спойлер";
            if (c === undefined)
                c = "Закрыть спойлер";
        } else if (c === undefined) {
            c = "[\u2013] " + o;
            o = "[+] " + o;
        }
        var f = document.createElement("form");
        f.className = "bbSpoilerContainer";
        f.innerHTML = "<input type='button' class='bbSpoilerButton' /><div class='bbSpoilerText' style='display: none;'></div>";
        var e = f.firstChild;
        e.value = o;
        e.onclick = function() { bbSpoilerHandler(f, o, c); };
        parser.insertContent(f.lastChild, this.content);
        var a = bbAlign(this.args["align"]);
        if (!a)
            return f;
        e = document.createElement("div");
        e.align = a;
        e.appendChild(f);
        return e;
    }
};

function BbList() { this.content = [ ]; }
BbList.prototype = {
    name: "list",
    htmlName: "ul",
    htmlArgs: { className: "bbList" },
    trim: true,
    onLeave: function(/*parser*/) {
        var len = this.content.length;
        var ct = [ ];
        var prev = 0;
        for (var i = 0; i < len; i++)
            if (this.content[i] instanceof BbListStar) {
                if (prev)
                    ct.push(new BbListItem(this.content.slice(prev, i)));
                prev = i + 1;
            } else if (this.content[i] instanceof BbListItem) {
                if (prev) {
                    ct.push(new BbListItem(this.content.slice(prev, i)));
                    prev = 0;
                }
                ct.push(this.content[i]);
            } else if (!prev)
                ct.push(this.content[i]);
        if (prev)
            ct.push(new BbListItem(this.content.slice(prev)));
        this.content = ct;
    }
};

function BbListStar() { }
BbListStar.prototype = {
    name: "*",
    trim: true,
    holder: "list",
    toDom: bbUnholded
};

function BbListItem(content) { this.content = content || [ ]; }
BbListItem.prototype = {
    name: "item",
    htmlName: "li",
    htmlArgs: { className: "bbListItem" },
    trim: true
};

function bbPlainHandler(parser) {
    var start = parser.pos;
    this.rx.lastIndex = start;
    while (this.rx.test(parser.input)) {
        var p = this.rx.lastIndex;
        if (parser.input.charAt(p - 1) == ']') {
            if (p != start)
                this.content.push(new BbText(parser.input.substring(start, p - this.name.length - 3)));
            parser.pos = p;
            return true;
        }
        if (p != start)
            this.content.push(new BbText(parser.input.substring(start, p - 1)));
        this.content.push(new BbBr);
        start = p;
    }
    this.content.push(parser.input.substring(start));
    parser.pos = parser.input.length;
    parser.raiseWarning("Незакрытый тег [" + this.name + "]!");
    return true;
}

function BbPlain() { this.content = [ ]; }
BbPlain.prototype = {
    name: "plain",
    rx: /\r|\n|\[\/plain\]/g,
    onEnter: bbPlainHandler,
    toDom: bbFragment
};

function BbCode() {
    this.content = [ ];
    this.args = [ ];
}
BbCode.prototype = {
    name: "code",
    bbArgs: [ "" ],
    trim: true,
    rx: /\r|\n|\[\/code\]/g,
    onEnter: function(parser) {
        if (this.args[""] != "jass")
            return bbPlainHandler.call(this, parser);
        var div = document.createElement("div");
        div.className = "jass";
        jass.s = parser.input;
        jass.i = parser.pos;
        jass.len = parser.input.length;
        div.innerHTML = jass.read();
        parser.pos = jass.i;
        this.content.push(new BbHtmlNode(div));
        return true;
    },
    toDom: function(parser) {
        var e = document.createElement("div");
        e.className = "bbCodeContainer";
        if (this.args[""] == "jass") {
            e.innerHTML = "<div class='bbCodeTitle'>Код JASS</div>";
            e.appendChild(this.content[0].toDom());
        } else {
            e.innerHTML = "<div class='bbCodeTitle'>Код</div><div class='bbCode'></div>";
            parser.insertContent(e.lastChild, this.content);
        }
        return e;
    }
};

function BbHtmlNode(e) { this.e = e; }
BbHtmlNode.prototype.toDom = function(/*parser*/) { return this.e; };

function BbHtml() { }
BbHtml.prototype = {
    name: "_",
    toDom: function(/*parser*/) { return bbUnparse.q.shift(); }
};

function BbTable() {
    this.content = [ ];
    this.args = { };
}
BbTable.prototype = {
    name: "table",
    bbArgs: [ "", "align", "width", "height" ],
    htmlArgs: {
        align: "$=0$",
        border: "$=1$",
        innerHTML: "<tbody></tbody>",
        height: "$height$",
        width: "$width$",
        className: "bbTable"
    },
    funcs: [
        bbAlg("align"),
        function(/*parser*/) { return "" in this.args ? this.args[""] : 1; }
    ],
    target: bbLast,
    trim: true,
    onLeave: function(parser) {
        var content = [ ];
        var rowcontent, trArgs, tdArgs;
        var i = 1, start = 1, len = this.content.length;
        var t = "th";
        actions: {
            header: if (this.content[0] instanceof BbCol) {
                //Формируем шапку таблицы.
                rowcontent = [ ];
                trArgs = [ ];
                tdArgs = this.content[0].args;
                for (; i < len; i++)
                    if (this.content[i] instanceof BbCol) {
                        rowcontent.push(new BbTd(this.content.slice(start, i), this.content[start - 1].args, "th"));
                        start = i + 1;
                    } else if (this.content[i] instanceof BbRow) {
                        rowcontent.push(new BbTd(this.content.slice(start, i), this.content[start - 1].args, "th"));
                        content.push(new BbTr(rowcontent));
                        start = 0;
                        trArgs = this.content[i].args;
                        i++;
                        break header;
                    }
                break actions;
            } else if (this.content[0] instanceof BbRow)
                trArgs = this.content[0].args;
            else {
                while (i < len && !(this.content[i] instanceof BbRow))
                    i++;
                trArgs = this.content[i].args;
                parser.raiseWarning("Непосредственно в теге [table] могут находиться только [row] и [col]!");
            }
            rowcontent = [ ];
            t = undefined;
            start = 0;
            for (; i < len; i++)
                if (this.content[i] instanceof BbCol) {
                    if (start)
                        rowcontent.push(new BbTd(this.content.slice(start, i), this.content[start - 1].args));
                    start = i + 1;
                } else if (this.content[i] instanceof BbRow) {
                    rowcontent.push(new BbTd(this.content.slice(start, i), this.content[start - 1].args));
                    content.push(new BbTr(rowcontent, trArgs));
                    rowcontent = [ ];
                    trArgs = this.content[i].args;
                    start = 0;
                } else if (!start)
                    parser.raiseWarning("Непосредственно в теге [row] может находиться только [col]!");
        }
        if (start)
            rowcontent.push(new BbTd(this.content.slice(start), this.content[start - 1].args, t));
        this.content = content;
        this.content.push(new BbTr(rowcontent, trArgs));
    }
};

function BbRow() { this.args = { }; }
BbRow.prototype = {
    name: "row",
    bbArgs: [ "", "align", "valign" ],
    trim: true,
    holder: "table",
    toDom: bbUnholded
};

function BbCol() { this.args = { }; }
BbCol.prototype = {
    name: "col",
    bbArgs: [ "", "colspan", "rowspan", "align", "valign" ],
    trim: true,
    holder: "table",
    toDom: bbUnholded
};

function BbTr(content, args) {
    this.content = content || [ ];
    this.args = args || [ ];
}
BbTr.prototype = {
    htmlName: "tr",
    htmlArgs: {
        align: "$=0$",
        vAlign: "$=1$",
        className: "bbTr"
    },
    cssArgs: { height: "$$px" },
    funcs: [
        bbAlg("align"),
        function(/*parser*/) { return "valign" in this.args ? bbAlign("valign") : "top"; }
    ]
};

function BbTd(content, args, type) {
    this.content = content || [ ];
    this.args = args || [ ];
    this.htmlName = type || "td";
}
BbTd.prototype = {
    htmlArgs: {
        align: "$=0$",
        vAlign: "$=1$",
        className: "$=2$",
        width: "$$",
        colSpan: "$colspan$",
        rowSpan: "$rowspan$"
    },
    funcs: [
        bbAlg("align"),
        bbAlg("valign"),
        function(/*parser*/) { return this.htmlName == "th" ? "bbTh" : "bbTd"; }
    ]
};

//===========================================================================
// Секция инициализации - откат разметки uCoz и самостоятельный разбор.
//===========================================================================

var bb = new BbParser(/*BB_STRICT | BB_INSENSITIVE*/);
bb.register(BbB, BbI, BbU, BbS, BbO, BbSub, BbSup, BbHr, BbC, BbL, BbR, BbJ, BbSharp, BbMsg, BbUrl, BbGoTo, BbFloat, BbClear, BbImg, BbSize, BbColor, BbFont, BbEnt, BbQuote, BbSpoiler, BbList, BbListStar, BbListItem, BbPlain, BbCode, BbHtml, BbTable, BbRow, BbCol);
var jass = new CodeParser("jass", jkw, "!&*-=+[];:|,<.>/");

function bbUnparse(n) {
    var t = "", s, s2, index, nodes = n.childNodes, len = nodes.length, br = false, i, e;
    for (i = 0; i < len; i++) {
        e = nodes[i];
        switch (e.nodeName) {
            case "#text": case null: case undefined:
                if (br && e.data.charAt(0) == ' ') {
                    s = e.data.substr(1);
                    br = false;
                } else
                    s = e.data;
                t += s.replace(bbUnparse.rxText, bbUnparse.textReplacer);
                break;

            case "BR": //case "P":
                if (t.charAt(t.length - 1) == ' ')
                    t = t.substr(0, t.length - 1);
                t += "\n";
                if (e.nodeName == "P")
                    t += "\n" + bbUnparse(e);
                else
                    br = true;
                break;

            case "#comment":
                switch (e.data) {
                    case "BBhide":
                        t += "[hide]" + bbUnparse(nodes[i + 2]) + "[/hide]";
                        i += 3;
                        break;

                    case "uSpoiler":
                        s = e;
                        while (!(s = s.nextSibling).lastChild) { }
                        s = s.lastChild;
                        if (s.lastChild.data[2] == 'n')
                            t += "[spoiler=" + s.lastChild.data.substring(5, s.lastChild.data.length - 1) + "]";
                        else
                            t += "[spoiler]";
                        t += bbUnparse(s) + "[/spoiler]";
                        i += 2;
                        break;

                    case "BBvideo":
                    case "BBaudio":
                        if (bbUnparse.pl) {
                            s = nodes[i + 2].innerHTML;
                            s2 = e.data.substr(2, 4) + "o]";
                            index = s.indexOf(':') + 2;
                            t += "[" + s2 + s.substring(index, s.indexOf("'", index)) + "[/" + s2;
                        } else {
                            bbUnparse.q.push(e.nextSibling);
                            bbUnparse.q.push(nodes[i + 2]);
                            t += "[_][_]";
                        }
                        i += 3;
                        break;

                    case "uzcode":
                        s = e;
                        while (!(s = s.nextSibling).lastChild) { }
                        s = s.lastChild.innerHTML;
                        t += "[code]" + s.substring(10, s.length - 11).replace(bbUnparse.rxCode, bbUnparse.codeReplacer) + "[/code]";
                        i += 2;
                        break;

                    case "uzquote":
                        s2 = e;
                        while (!(s2 = s2.nextSibling).lastChild) { }
                        s = s2.firstChild;
                        if (s.childNodes.length >= 3) {
                            s = s.childNodes[2].innerHTML;
                            t += "[quote=" + s.substr(9, s.length - 19) + "]";
                        } else
                            t += "[quote]";
                        t += bbUnparse(s2.lastChild) + "[/quote]";
                        i += 2;
                }
                break;

            case "HR":
                if (e.className == "signatureHr") {
                    s = t.length;
                    do
                        s--;
                    while (t.charAt(s) == '\n');
                    t = t.substr(0, s);
                    do {
                        t += "[_]";
                        bbUnparse.q.push(e);
                    } while (e = e.nextSibling);
                    return t;
                }
                t += "[hr]";
                break;

            case "B": case "I": case "U":
            case "S": case "SUB": case "SUP":
                s = e.nodeName.toLowerCase() + "]";
                t += "[" + s + bbUnparse(e) + "[/" + s;
                break;

            case "SPAN":
                if (e.style.textDecoration == "overline")
                    t += "[o]" + bbUnparse(e) + "[/o]";
                else if (e.style[0] == "font-size")
                    t += "[size=" + e.style.fontSize.substr(0, e.style.fontSize.length - 2) + "]" + bbUnparse(e) + "[/size]";
                else if (e.style[0] == "color")
                    t += "[color='" + e.style.color + "']" + bbUnparse(e) + "[/color]";
                else if (e.style[0] == "font-family")
                    t += "[font=" + e.style.fontFamily.substr(1, e.style.fontFamily.length - 2) + "]" + bbUnparse(e) + "[/font]";
                else if (e.className == "entDots" || e.className == "entryReadAll") {
                    bbUnparse.q.push(e);
                    t += "[_]";
                } else
                    t += e.data;
                break;

            case "DIV":
                if (e.style.cssFloat)
                    text += "[float=" + e.style.cssFloat + "]" + bbUnparse(e) + "[/float]";
                else if (e.className.toLowerCase() == "supermoderhtml") {
                    t += "[_]";
                    bbUnparse.q.push(e);
                } else {
                    s = e.align.charAt(0);
                    t += "[" + s + "]" + bbUnparse(e) + "[/" + s + "]";
                }
                break;

            case "A":
                t += "[url=" + e.href + "]" + bbUnparse(e) + "[/url]";
                break;

            case "IMG":
                if (bbUnparse.pl)
                    t += "[img]" + e.src + "[/img]";
                else {
                    /*
                    if (s = (e.align && e.align != "absmiddle"))
                        t += "[float=" + e.align + "]";
                    t += '[img="' + e.src + '"';
                    if (e.width && e.width != 32)
                        t += "width=" + e.width;
                    if (e.height && e.height != 32)
                        t += " height=" + e.height;
                    t += s ? "][/float]" : "]";
                    */
                    t += "[_]";
                    bbUnparse.q.push(e);
                }
                break;

            case "UL":
                t += "[list]" + bbUnparse(e) + "[/list]";
                break;

            case "LI":
                t += "[*]" + bbUnparse(e);
                break;

            default:
                t += e.data;
        }
    }
    return t;
}
bbUnparse.q = [ ];
bbUnparse.pl = false;
bbUnparse.rxCode = /&[^;]*.| ?(?:<br ?\/?>)+(?: |&nbsp;)/g;
bbUnparse.ent = document.createElement("span");
bbUnparse.codeReplacer = function(s) {
    if (s.charAt(0) == '&') {
        if (s == "&nbsp;")
            return '\u00A0';
        bbUnparse.ent.innerHTML = s;
        return bbUnparse.ent.firstChild.data;
    }
    var i = (s.charAt(s.length - 1) == ';' ? s.length - 7 : s.length) >> 2;
    var res = "";
    while (i--)
        res += "\n";
    return res;
};
bbUnparse.rxText = /[\[©®™]/g;
bbUnparse.textReplacer = function(x, o, s) {
    switch (x) {
        case '©': return "(c)";
        case '®': return "(r)";
        case '™': return "(tm)";
    }
    var c = s.charAt(o + 1), b = true;
    if (c == '_' || s.substr(o + 1, 3) == "img") {
        c = s.charAt(o + 2 + ((c != '_') << 1));
        if (c == '=' || c == ']' || c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\u00A0')
            return x + " ";
        return x;
    } else if (c == '/')
        b = false;
    if (s.substr(o + 2 - b, 6) == "plain]")
        bbUnparse.pl = b;
    return x;
};

function bbProcessPosts(tag, nms) {
    var posts = document.getElementsByTagName(tag),
        len = posts.length,
        last, i, cur, p, next, s, e, j, k, w;
    for (i = 0; i < len; i++)
        if (posts[i].className in nms) {
            cur = posts[i];
            p = cur.parentNode;
            next = cur.nextSibling;
            cur.innerHTML = cur.innerHTML.replace(bbProcessPosts.rx, bbProcessPosts.replacer);
            s = bbUnparse(cur);
            p.removeChild(cur);
            while (last = cur.lastChild)
                cur.removeChild(last);
            if (e = bb.parse(s))
                cur.appendChild(e);
            for (j = 0; j < bb.warnings.length; j++) {
                w = cur.appendChild(document.createElement("div"));
                w.className = "bbWarning";
                w.appendChild(document.createTextNode(bb.warnings[j]));
            }
            next ? p.insertBefore(cur, next) : p.appendChild(cur);
            len = posts.length;
        }
}
bbProcessPosts.rx = /<\/?p>/g;
bbProcessPosts.replacer = function(s) {
    return s.length == 3 ? "<br /><br />" : "";
};

(function(f) { window.chrome ? f() : document.addEventListener("DOMContentLoaded", f, false); } )(
    function() {
        if (window.self == window.top) {
            //var w1, w = new Date;
            //Стили BB-кодов.
            var css = document.createElement("style");
            css.innerHTML = ".bbWarning{font-style:italic;color:gray;}\
            .bbHr{border:none;background-color:#E4B214;color:#E4B214;}\
            .bbUrl{}\
            .bbGoTo{}\
            .bbImg{}\
            .bbFloat{padding:5px 5px 2px 5px;}\
            .bbQuoteContainer{}\
            .bbQuoteHeader{margin-top:5px;padding:2px 2px 2px 5px;font-size:9px;color:#E4B214;}\
            .bbQuoteQuote{font-weight:bold;}\
            .bbQuoteAuthor{}\
            .bbQuoteMessage{margin-bottom:5px;border-style:solid;border-top:1px solid#916C0F!important;border-bottom:1px solid#916C0F!important;border-left:none!important;border-right:none!important;border:1px inset;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':this.scrollHeight+5+'px');max-height:200px;padding:5px 5px 5px 10px;background-color:transparent;color:#BFB792;}\
            .bbSpoilerContainer{}\
            .bbSpoilerButton{vertical-align:middle;font-family:Tahoma;font-size:11px;}\
            .bbSpoilerText{padding-left:7px;}\
            .bbList{}\
            .bbListItem{margin-left:-10px!important;}\
            .bbCodeContainer{}\
            .bbCodeTitle{padding-left:5px;font-size:10px;}\
            .bbCode{text-align:left;padding-left:1px;background-color:#FFF;color:#000;font:13px Courier New,monospace;border:1px inset;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>300?'300px':this.scrollHeight+5+'px');max-height:300px;}\
            .bbTable{}\
            .bbTr{}\
            .bbTh{font-weight:bold;font-size:12px;padding:3px;}\
            .bbTd{padding:3px;}\
            .jass{font:13px Courier New,monospace;white-space:pre-wrap;text-align:left;background-color:#FFF;color:#000;padding-left:1px;}\
            .jass-keyword-0{font-weight:bold;}\
            .jass-keyword-1{font-weight:bold;color:#0055AA;}\
            .jass-keyword-2{color:#0000AA;}\
            .jass-keyword-3{color:#800080;}\
            .jass-keyword-4{color:red;}\
            .jass-oper{font-weight:bold;color:#AA5500;}\
            .jass-string{font-style:italic;color:#0000AA;}\
            .jass-char{font-weight:bold;font-style:italic;text-decoration:underline;}\
            .jass-comment{color:#008000;}\
            .jass-pre{color:gray;}\
            .jass-macro-arg{color:#555;}\
            .jass-macro-string,.jass-number{color:#0000AA;}";
            document.body.appendChild(css);
            if (document.head.firstChild.innerHTML == "Предварительный просмотр сообщения")
                bbProcessPosts("td", { "posttdMessage": 1 } );
            else {
                bbProcessPosts("span", { "ucoz-forum-post": 1, "signatureView": 1 } );
                bbProcessPosts("div", { "eMessage": 1, "cMessage": 1 } );
                bbProcessPosts("td", { "eMessage": 1 } );
            }
            //w1 = new Date;
            //alert(w1 - w + "ms");
        }
    }
);
