I18n
//=============================================================================
// i18n.js
//=============================================================================

/*:
 * @plugindesc Module for i18n.
 * @author taroxd
 *
 * @param Default Locale
 * @desc The language used when the language detected is not supported.
 * @default en-US
 *
 * @param Resource Folder
 * @desc The folder where resource files are put in.
 * @default data/i18n
 *
 * @help
 *
 * Prefix any string in the RPGMV editor with "__ " to enable i18n for it.
 *
 * Plugin Command:
 *   i18n en-US      # set language to en-US
 */

window.i18n = function() {

    var parameters = PluginManager.parameters('i18n');
    var defaultLocale = parameters['Default Locale'];
    var supportedLocale = parameters['Supported Locale'];
    var resourceFolder = parameters['Resource Folder'];

    function i18n(string) {
        return (i18n[i18n.language] || {})[string] || string;
    }

    Object.defineProperty(i18n, 'language', {
        get: function() { return i18n._language; },
        set: function(lang) {
            if (lang == null) lang = navigator.language;
            lang = lang.substr(0, 3).toLowerCase() + lang.substr(3).toUpperCase();
            loadI18nResources(lang,
                function() { i18n._language = lang; },
                function() { i18n._language = defaultLocale; }
            );
        }
    });

    function loadI18nResources(language, onload, onerror) {
        if (i18n[language]) return onload();
        var xhr = new XMLHttpRequest();
        var url = resourceFolder + '/' + language + '.json';
        xhr.open('GET', url);
        xhr.overrideMimeType('application/json');
        xhr.onload = function() {
            if (xhr.status < 400) {
                i18n[language] = JSON.parse(xhr.responseText);
                onload();
            }
        };
        xhr.onerror = onerror;
        xhr.send();
    };

    function overrideObj(obj) {
        if (obj == null) return obj;
        Object.keys(obj).forEach(function(key) {
            var value = obj[key];
            switch(typeof value) {
            case 'string':
                if (value.startsWith('__ ')) {
                    value = value.substr(3);
                    Object.defineProperty(obj, key, {
                        get: function() { return i18n(value); },
                        set: function(v) { value = v; },
                        enumerable: true,
                        configurable: true
                    });
                }
                break;
            case 'object':
                overrideObj(value);
                break;
            }
        });
        return obj;
    }

    // override method
    DataManager.loadDataFile = function(name, src) {
        var xhr = new XMLHttpRequest();
        var url = 'data/' + src;
        xhr.open('GET', url);
        xhr.overrideMimeType('application/json');
        xhr.onload = function() {
            if (xhr.status < 400) {
                window[name] = overrideObj(JSON.parse(xhr.responseText));
                DataManager.onLoad(window[name]);
            }
        };
        xhr.onerror = function() {
            DataManager._errorUrl = DataManager._errorUrl || url;
        };
        window[name] = null;
        xhr.send();
    };

    Object.defineProperty(ConfigManager, 'language', {
        get: function() { return this._language; },
        set: function(lang) {
            this._language = lang;
            i18n.language = lang;
        },
        configurable: true
    });

    var makeData = ConfigManager.makeData;
    ConfigManager.makeData = function() {
        var config = makeData.call(this);
        config.language = this.language;
        return config;
    };

    var applyData = ConfigManager.applyData;
    ConfigManager.applyData = function(config) {
        applyData.call(this, config);
        this.language = config.language;
    };

    var pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        pluginCommand.call(this, command, args);
        if (command === 'i18n') {
            ConfigManager.language = args[0];
            ConfigManager.save();
        }
    };

    return i18n;
}();

Ulds
//=============================================================================
// ULDS.js
//=============================================================================

/*:
 * @plugindesc Unlimited Layer Display System.
 * @author taroxd
 *
 * @param Default Path
 * @desc The default path where pictures are stored.
 * @default parallaxes
 *
 * @param Default Z
 * @desc The default Z coordinate for sprites.
 * @type number
 * @decimals 2
 * @min -15
 * @max 15
 * @default 0.5
 *
 * @help This plugin does not provide plugin commands.
 *
 * Map Note: <ulds> JSON </ulds>
 * "name": picture filename
 * "path": picture path (default to Default Path)
 * "loop": true/false
 *    Whether the picture should loop.
 * "hue"/"smooth": the attribute of a Bitmap.
 * <attribute>: the attribute of a Sprite.
 *
 * A string can be used as a value to be interpreted as a formula.
 * In the formula, 't' refers to frame count.
 *                 's' refers to $gameSwitches.
 *                 'v' refers to $gameVaribles.
 *
 * Also, various helpers are available, defined in Helper.
 *
 * If a string is used as a formula of the attribute,
 * the attribute will be updated every frame.
 *
 * By the way, attributes such as "anchor.x" is also available.
 *
 *
 * Here is an example:
 *
   <ulds> {
     "name": "BlueSky",
     "x": "this.rx(t)",
     "y": 50,
     "loop": true
   } </ulds>
 *
 */


void function() {

    var assign = Object.assign || function(target) {
        for (var i = 1; i < arguments.length; i++) {
            var source = arguments[i];
            for (var key in source) {
                target[key] = source[key];
            }
        }
        return target;
    };

    var RE = /<ulds>([^]*?)<\/ulds>/ig;
    var parameters = PluginManager.parameters('ULDS');
    var DEFAULT_SETTINGS = {
        z: parseFloat(parameters['Default Z']),
        path: parameters['Default Path'],
        smooth: true
    };

    // Feel free to add your own helper.
    var Helper = {
        t: 0,

        // Converts a coordinate on the map to the corresponding coordinate on the screen.
        rx: function(x, scrollRate) {
            if (scrollRate == null) {
                scrollRate = $gameMap.tileWidth();
            }

            if (scrollRate === 0) {
                return x;
            } else {
                return $gameMap.adjustX(x / scrollRate) * scrollRate;
            }
        },

        ry: function(y, scrollRate) {
            if (scrollRate == null) {
                scrollRate = $gameMap.tileHeight();
            }

            if (scrollRate === 0) {
                return y;
            } else {
                return $gameMap.adjustY(y / scrollRate) * scrollRate;
            }
        },

        update: function() {
            ++this.t;
            this._updater(this.t, $gameSwitches, $gameVariables);
        },

        assignSettings: function(settings) {
            var code = '';
            for (var key in settings) {
                var value = settings[key];
                if (typeof(value) === 'string') {
                    // this.x = (formula);
                    // this.scale.x = (formula); // key is "scale.x"
                    code += 'this.' + key + ' = (' + value + ');\n';
                } else {
                    // if key is "scale.x"
                    // keys is ["scale", "x"]
                    var keys = key.split('.');
                    // set key to "x"
                    key = keys.pop();

                    var target = this;
                    keys.forEach(function(k) {
                        if (typeof(target) !== 'object') {
                            target[k] = {};
                        }
                        target = target[k];
                    });

                    target[key] = value;
                }
            }
            // You may log the code for debugging purpose.
            // console.log(code);
            this._updater = new Function('t', 's', 'v', code);
        }
    };

    // NOT a class constructor
    function ULDS(settings) {
        settings = assign({}, DEFAULT_SETTINGS, settings);
        var spriteClass = settings.loop ? ULDS.TilingSprite : ULDS.Sprite;
        var bitmap = ImageManager.loadBitmap('img/' + settings.path + '/',
            settings.name, settings.hue, settings.smooth);
        var sprite = new spriteClass(bitmap);

        delete settings.path;
        delete settings.name;
        delete settings.loop;
        delete settings.hue;
        delete settings.smooth;

        sprite.assignSettings(settings);

        return sprite;
    }

    ULDS.Sprite = function(bitmap) {
        Sprite.call(this, bitmap);
    };

    ULDS.Sprite.prototype = Object.create(Sprite.prototype);
    ULDS.Sprite.prototype.constructor = ULDS.Sprite;
    assign(ULDS.Sprite.prototype, Helper);

    ULDS.TilingSprite = function(bitmap) {
        TilingSprite.call(this, bitmap);
        bitmap.addLoadListener(function() {
            this.move(0, 0, bitmap.width, bitmap.height);
        }.bind(this));
    };

    ULDS.TilingSprite.prototype = Object.create(TilingSprite.prototype);
    ULDS.TilingSprite.prototype.constructor = ULDS.TilingSprite;
    assign(ULDS.TilingSprite.prototype, Helper);

    Object.defineProperties(ULDS.TilingSprite.prototype, {
        x: {
            get: function() { return -this.origin.x; },
            set: function(x) { this.origin.x = -x; }
        },
        y: {
            get: function() { return -this.origin.y; },
            set: function(y) { this.origin.y = -y; }
        }
    });

    var ct = Spriteset_Map.prototype.createTilemap;
    Spriteset_Map.prototype.createTilemap = function() {
        ct.call(this);
        $dataMap.note.replace(RE, function(_match, settings) {
            var isValid = false;
            try {
                settings = JSON.parse(settings);
                isValid = typeof(settings) === 'object';
                if (!isValid) {
                    throw 'ULDS settings should be an object';
                }
            } catch (e) {
                console.error(e);
                console.log(settings);
            }
            if (isValid) {
                this._tilemap.addChild(ULDS(settings));
            }
        }.bind(this));
    };
}();

Skiptitle
//=============================================================================
// SkipTitle.js
//=============================================================================

/*:
 * @plugindesc Skip Title.
 * @author taroxd
 *
 * @param Test Only
 * @desc Whether to skip title only in playtest. true/false
 * @default true
 *
 * @help This plugin does not provide plugin commands.
 */

void function() {

    var parameters = PluginManager.parameters('SkipTitle');
    var testOnly = parameters['Test Only'] !== 'false';
    var enable = !testOnly || location.search === '?test';

    if (enable) {
        Scene_Boot.prototype.start = function() {
            Scene_Base.prototype.start.call(this);
            SoundManager.preloadImportantSounds();
            this.checkPlayerLocation();
            DataManager.setupNewGame();
            SceneManager.goto(Scene_Map);
        };
    }

}();