Sphinx-Maplink

Sphinx-Maplink

Comme tous mes plugins, ce script est publié sous licence CC BY 4.0.

//=============================================================================
// Sphinx-Maplink.js
//=============================================================================

/*:
 * @plugindesc Système de jointure de cartes
 * @author Sphinx
 * 
 * @param Taille jointure horizontale
 * @desc Nombre de colonnes des cartes jointes à gauche ou à droite affichées sur la carte courante (par défaut : 9)
 * @default 9
 * 
 * @param Taille jointure verticale
 * @desc Nombre de lignes des cartes jointes au dessus ou en dessous affichées sur la carte courante (par défaut : 7)
 * @default 7
 * 
 * @help
 * //==========================================================================
 * // Plugin : Sphinx-Maplink
 * // Date   : 10 mars 2016
 * // Auteur : Sphinx
 * //==========================================================================
 * Ce plugin permet de joindre les maps entre elles. Une map jointe est en
 * partie affichée sur le côté de la map courante.
 * 
 * Conditions pour être utilisable :
 *     - Les 2 maps jointes doivent utiliser des tilesets compatibles (chaque élément
 *       affiché dans la jointure devra donc être à la même place dans les 2 tilesets
 *       concernés si ceux-ci sont différents)
 *     - Les 2 maps jointes doivent avoir le côté en contact de la même dimension
 * 
 * Pour activer le maplink sur une carte, ajoutez dans ses remarques les jointures
 * nécessaires :
 *     - <linkLeft:ID_MAP> : pour que la carte ID_MAP soit affichée à gauche de la
 *                           carte courante)
 *     - <linkRight:ID_MAP> : pour que la carte ID_MAP soit affichée à droite de la
 *                            carte courante
 *     - <linkTop:ID_MAP> : pour que la carte ID_MAP soit affichée au dessus de la
 *                          carte courante
 *     - <linkBottom:ID_MAP> : pour que la carte ID_MAP soit affichée en dessous de
 *                             la carte courante
 * 
 * Lorsqu'une map est jointe à une autre et que le joueur dépasse la jointure, il est
 * automatiquement téléporté sur la map jointe.
 * 
 * Les évènements présents sur les parties affichées des maps jointes seront
 * eux aussi affichés. Cependant, aucun de ces évènements ajoutés ne sera
 * exécutable : ils seront simplement affichés.
 * L'apparence des évents des maps jointes tient compte des conditions des pages de
 * ces évents. Les évents des maps jointes n'ayant aucune apparence sur aucune page
 * ne seront pas importés dans la map courante.
 * 
 * Dépendances :
 *     Aucune
 */
(function() {
    Game_Map.prototype.resetMapLink = function() {
        var parameters = PluginManager.parameters("Sphinx-Maplink");
        this.offsetH = (parseInt(parameters["Taille jointure horizontale"], 10) || 9);
        this.offsetV = (parseInt(parameters["Taille jointure verticale"], 10) || 7);
        this._dataLikedMaps = {};
        this._dataCornerLinks = {};
    };

    Scene_Map.prototype.aliasMaplinkCreate = Scene_Map.prototype.create;
    Scene_Map.prototype.create = function() {
        Scene_Map.prototype.aliasMaplinkCreate.call(this);
        this._links = [];
        this._corners = [];
        this._waitingLinks = 0;
        this._waitingCorners = 0;
        $gameMap.resetMapLink();
    };

    Scene_Map.prototype.aliasMaplinkOnMapLoaded = Scene_Map.prototype.onMapLoaded;
    Scene_Map.prototype.onMapLoaded = function() {
        if($dataMap.meta.linkLeft) {
            this._links.push("Left");
        }
        if($dataMap.meta.linkRight) {
            this._links.push("Right");
        }
        if($dataMap.meta.linkTop) {
            this._links.push("Top");
        }
        if($dataMap.meta.linkBottom) {
            this._links.push("Bottom");
        }
        this._waitingLinks = this._links.length;
        if(this._waitingLinks > 0) {
            return this.loadLinkedMaps();
        } else {
            return Scene_Map.prototype.aliasMaplinkOnMapLoaded.call(this);
        }
    };

    Scene_Map.prototype.aliasMaplinkIsReady = Scene_Map.prototype.isReady;
    Scene_Map.prototype.isReady = function() {
        return Scene_Map.prototype.aliasMaplinkIsReady.call(this) && this._waitingLinks === 0 && this._waitingCorners === 0;
    };

    Scene_Map.prototype.loadLinkedMaps = function() {
        this._waitingLinks = this._links.length;
        if(this._waitingLinks == 0) {
            return this.onLinksLoaded();
        } else {
            return this.loadLink(this._links.pop());
        }
    };

    Scene_Map.prototype.loadLink = function(dir) {
        var mapId = 0;
        switch(dir) {
            case "Left":
                mapId = parseInt($dataMap.meta.linkLeft, 10);
                break;
            case "Right":
                mapId = parseInt($dataMap.meta.linkRight, 10);
                break;
            case "Top":
                mapId = parseInt($dataMap.meta.linkTop, 10);
                break;
            case "Bottom":
                mapId = parseInt($dataMap.meta.linkBottom, 10);
                break;
        }
        if(mapId > 0 && !!$dataMapInfos[mapId]) {
            var scene = this;
            var xhr = new XMLHttpRequest();
            var filename = "Map%1.json".format(mapId.padZero(3));
            var url = "data/" + filename;
            xhr.open("GET", url);
            xhr.overrideMimeType("application/json");
            xhr.onload = function() {
                if(xhr.status < 400) {
                    try {
                        var dataMap = JSON.parse(xhr.responseText);
                        DataManager.extractMetadata(dataMap);
                        $gameMap._dataLikedMaps[dir] = dataMap;
                    } finally {
                        scene.loadLinkedMaps();
                    }
                }
            };
            xhr.onerror = function() {
                DataManager._errorUrl = DataManager._errorUrl || url;
            };
            xhr.send();
        } else {
            this.loadLinkedMaps();
        }
    };

    Scene_Map.prototype.onLinksLoaded = function() {
        if(!!$gameMap._dataLikedMaps.Left && !!$gameMap._dataLikedMaps.Top) {
            this._corners.push("TopLeft");
        }
        if(!!$gameMap._dataLikedMaps.Left && !!$gameMap._dataLikedMaps.Bottom) {
            this._corners.push("BottomLeft");
        }
        if(!!$gameMap._dataLikedMaps.Right && !!$gameMap._dataLikedMaps.Top) {
            this._corners.push("TopRight");
        }
        if(!!$gameMap._dataLikedMaps.Right && !!$gameMap._dataLikedMaps.Bottom) {
            this._corners.push("BottomRight");
        }
        this._waitingCorners = this._corners.length;
        
        if(this._waitingCorners > 0) {
            return this.loadCornerLinks();
        } else {
            return this.linkMaps();
        }
    }

    Scene_Map.prototype.loadCornerLinks = function() {
        this._waitingCorners = this._corners.length;
        if(this._waitingCorners == 0) {
            return this.onCornersLoaded();
        } else {
            return this.loadCorner(this._corners.pop());
        }
    };

    Scene_Map.prototype.loadCorner = function(dir) {
        var mapId = 0;
        switch(dir) {
            case "TopLeft":
                if($gameMap._dataLikedMaps.Left.meta.linkTop === $gameMap._dataLikedMaps.Top.meta.linkLeft) {
                    mapId = parseInt($gameMap._dataLikedMaps.Left.meta.linkTop, 10);
                }
                break;
            case "TopRight":
                if($gameMap._dataLikedMaps.Right.meta.linkTop === $gameMap._dataLikedMaps.Top.meta.linkRight) {
                    mapId = parseInt($gameMap._dataLikedMaps.Right.meta.linkTop, 10);
                }
                break;
            case "BottomLeft":
                if($gameMap._dataLikedMaps.Left.meta.linkBottom === $gameMap._dataLikedMaps.Bottom.meta.linkLeft) {
                    mapId = parseInt($gameMap._dataLikedMaps.Left.meta.linkBottom, 10);
                }
                break;
            case "BottomRight":
                if($gameMap._dataLikedMaps.Right.meta.linkBottom === $gameMap._dataLikedMaps.Bottom.meta.linkRight) {
                    mapId = parseInt($gameMap._dataLikedMaps.Right.meta.linkBottom, 10);
                }
                break;
        }
        if(mapId > 0 && !!$dataMapInfos[mapId]) {
            var scene = this;
            var xhr = new XMLHttpRequest();
            var filename = "Map%1.json".format(mapId.padZero(3));
            var url = "data/" + filename;
            xhr.open("GET", url);
            xhr.overrideMimeType("application/json");
            xhr.onload = function() {
                if(xhr.status < 400) {
                    try {
                        var dataMap = JSON.parse(xhr.responseText);
                        DataManager.extractMetadata(dataMap);
                        $gameMap._dataCornerLinks[dir] = dataMap;
                    } finally {
                        scene.loadCornerLinks();
                    }
                }
            };
            xhr.onerror = function() {
                DataManager._errorUrl = DataManager._errorUrl || url;
            };
            xhr.send();
        } else {
            this.loadCornerLinks();
        }
    };

    Scene_Map.prototype.onCornersLoaded = function() {
        this.linkMaps();
    };
    
    Scene_Map.prototype.linkMaps = function() {
        var newMap = {
            data: [],
            width: $dataMap.width,
            height: $dataMap.height,
        }
        
        if(!!$gameMap._dataLikedMaps.Left) {
            newMap.width += $gameMap.offsetH;
        }
        if(!!$gameMap._dataLikedMaps.Right) {
            newMap.width += $gameMap.offsetH;
        }
        if(!!$gameMap._dataLikedMaps.Top) {
            newMap.height += $gameMap.offsetV;
        }
        if(!!$gameMap._dataLikedMaps.Bottom) {
            newMap.height += $gameMap.offsetV;
        }
        
        // Fusion des cartes
        for(var z = 0; z < 6; ++z) {
            for(var y = 0; y < newMap.height; ++y) {
                for(var x = 0; x < newMap.width; ++x) {
                    var indexTileNewMap = (z * newMap.height * newMap.width) + (y * newMap.width) + x;
                    var indexTile = 0;
                    var valueTile = 0;
                    
                    if(!!$gameMap._dataCornerLinks.TopLeft) { // Si coin haut gauche
                        if(x < $gameMap.offsetH && y < $gameMap.offsetV) { // Si on est dans la partie à joindre
                            indexTile = (z * $gameMap._dataCornerLinks.TopLeft.height * $gameMap._dataCornerLinks.TopLeft.width) + (($gameMap._dataCornerLinks.TopLeft.height - $gameMap.offsetV + y) * $gameMap._dataCornerLinks.TopLeft.width) + ($gameMap._dataCornerLinks.TopLeft.width - $gameMap.offsetH + x);
                            valueTile = $gameMap._dataCornerLinks.TopLeft.data[indexTile];
                        }
                    }
                    
                    if(!!$gameMap._dataCornerLinks.TopRight) { // Si coin haut droit
                        if(x >= newMap.width - $gameMap.offsetH && y < $gameMap.offsetV) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                indexTile = (z * $gameMap._dataCornerLinks.TopRight.height * $gameMap._dataCornerLinks.TopRight.width) + (($gameMap._dataCornerLinks.TopRight.height - $gameMap.offsetV + y) * $gameMap._dataCornerLinks.TopRight.width) + (x - $dataMap.width);
                                valueTile = $gameMap._dataCornerLinks.TopRight.data[indexTile];
                            } else { // S'il y a une jointure à gauche
                                indexTile = (z * $gameMap._dataCornerLinks.TopRight.height * $gameMap._dataCornerLinks.TopRight.width) + (($gameMap._dataCornerLinks.TopRight.height - $gameMap.offsetV + y) * $gameMap._dataCornerLinks.TopRight.width) + (x - $dataMap.width - $gameMap.offsetH);
                                valueTile = $gameMap._dataCornerLinks.TopRight.data[indexTile];
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataCornerLinks.BottomLeft) { // Si coin bas gauche
                        if(x < $gameMap.offsetH && y >= newMap.height - $gameMap.offsetV) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                indexTile = (z * $gameMap._dataCornerLinks.BottomLeft.height * $gameMap._dataCornerLinks.BottomLeft.width) + ((y - $dataMap.height) * $gameMap._dataCornerLinks.BottomLeft.width) + ($gameMap._dataCornerLinks.BottomLeft.width - $gameMap.offsetH + x);
                                valueTile = $gameMap._dataCornerLinks.BottomLeft.data[indexTile];
                            } else { // S'il n'y a pas de jointure au dessus
                                indexTile = (z * $gameMap._dataCornerLinks.BottomLeft.height * $gameMap._dataCornerLinks.BottomLeft.width) + ((y - $dataMap.height - $gameMap.offsetV) * $gameMap._dataCornerLinks.BottomLeft.width) + ($gameMap._dataCornerLinks.BottomLeft.width - $gameMap.offsetH + x);
                                valueTile = $gameMap._dataLikedMaps.Bottom.data[indexTile];
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataCornerLinks.BottomRight) { // Si coin bas droite
                        if(x >= newMap.width - $gameMap.offsetH && y >= newMap.height - $gameMap.offsetV) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                    indexTile = (z * $gameMap._dataCornerLinks.BottomRight.height * $gameMap._dataCornerLinks.BottomRight.width) + ((y - $dataMap.height) * $gameMap._dataCornerLinks.BottomRight.width) + (x - $dataMap.width);
                                    valueTile = $gameMap._dataCornerLinks.BottomRight.data[indexTile];
                                } else { // S'il y a une jointure à gauche
                                    indexTile = (z * $gameMap._dataCornerLinks.BottomRight.height * $gameMap._dataCornerLinks.BottomRight.width) + ((y - $dataMap.height) * $gameMap._dataCornerLinks.BottomRight.width) + (x - $dataMap.width - $gameMap.offsetH);
                                    valueTile = $gameMap._dataCornerLinks.BottomRight.data[indexTile];
                                }
                            } else { // S'il n'y a pas de jointure au dessus
                                if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                    indexTile = (z * $gameMap._dataCornerLinks.BottomRight.height * $gameMap._dataCornerLinks.BottomRight.width) + ((y - $dataMap.height - $gameMap.offsetV) * $gameMap._dataCornerLinks.BottomRight.width) + (x - $dataMap.width);
                                    valueTile = $gameMap._dataCornerLinks.BottomRight.data[indexTile];
                                } else { // S'il y a une jointure à gauche
                                    indexTile = (z * $gameMap._dataCornerLinks.BottomRight.height * $gameMap._dataCornerLinks.BottomRight.width) + ((y - $dataMap.height - $gameMap.offsetV) * $gameMap._dataCornerLinks.BottomRight.width) + (x - $dataMap.width - $gameMap.offsetH);
                                    valueTile = $gameMap._dataCornerLinks.BottomRight.data[indexTile];
                                }
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataLikedMaps.Left) { // Si jointure à gauche
                        if(x < $gameMap.offsetH) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                if(!$gameMap._dataLikedMaps.Bottom || y < newMap.height - $gameMap.offsetV) { // S'il n'y a pas de jointure en dessous ou qu'on se trouve au dessus
                                    indexTile = (z * $gameMap._dataLikedMaps.Left.height * $gameMap._dataLikedMaps.Left.width) + (y * $gameMap._dataLikedMaps.Left.width) + ($gameMap._dataLikedMaps.Left.width - $gameMap.offsetH + x);
                                    valueTile = $gameMap._dataLikedMaps.Left.data[indexTile];
                                }
                            } else if(y >= $gameMap.offsetV) { // Si on est en dessous de la jointure au dessus
                                if(!$gameMap._dataLikedMaps.Bottom || y < newMap.height - $gameMap.offsetV) { // S'il n'y a pas de jointure en dessous ou qu'on se trouve au dessus
                                    indexTile = (z * $gameMap._dataLikedMaps.Left.height * $gameMap._dataLikedMaps.Left.width) + ((y - $gameMap.offsetV) * $gameMap._dataLikedMaps.Left.width) + ($gameMap._dataLikedMaps.Left.width - $gameMap.offsetH + x);
                                    valueTile = $gameMap._dataLikedMaps.Left.data[indexTile];
                                }
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataLikedMaps.Right) { // Si jointure à droite
                        if(x >= newMap.width - $gameMap.offsetH) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                if(!$gameMap._dataLikedMaps.Bottom || y < newMap.height - $gameMap.offsetV) { // S'il n'y a pas de jointure en dessous ou qu'on se trouve au dessus
                                    if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                        indexTile = (z * $gameMap._dataLikedMaps.Right.height * $gameMap._dataLikedMaps.Right.width) + (y * $gameMap._dataLikedMaps.Right.width) + (x - $dataMap.width);
                                        valueTile = $gameMap._dataLikedMaps.Right.data[indexTile];
                                    } else { // S'il y a une jointure à gauche
                                        indexTile = (z * $gameMap._dataLikedMaps.Right.height * $gameMap._dataLikedMaps.Right.width) + (y * $gameMap._dataLikedMaps.Right.width) + (x - $dataMap.width - $gameMap.offsetH);
                                        valueTile = $gameMap._dataLikedMaps.Right.data[indexTile];
                                    }
                                }
                            } else if(y >= $gameMap.offsetV) { // Si on est en dessous de la jointure au dessus
                                if(!$gameMap._dataLikedMaps.Bottom || y < newMap.height - $gameMap.offsetV) { // S'il n'y a pas de jointure en dessous ou qu'on se trouve au dessus
                                    if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                        indexTile = (z * $gameMap._dataLikedMaps.Right.height * $gameMap._dataLikedMaps.Right.width) + ((y - $gameMap.offsetV) * $gameMap._dataLikedMaps.Right.width) + (x - $dataMap.width);
                                        valueTile = $gameMap._dataLikedMaps.Right.data[indexTile];
                                    } else { // S'il y a une jointure à gauche
                                        indexTile = (z * $gameMap._dataLikedMaps.Right.height * $gameMap._dataLikedMaps.Right.width) + ((y - $gameMap.offsetV) * $gameMap._dataLikedMaps.Right.width) + (x - $dataMap.width - $gameMap.offsetH);
                                        valueTile = $gameMap._dataLikedMaps.Right.data[indexTile];
                                    }
                                }
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataLikedMaps.Top) { // Si jointure au dessus
                        if(y < $gameMap.offsetV) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                    indexTile = (z * $gameMap._dataLikedMaps.Top.height * $gameMap._dataLikedMaps.Top.width) + (($gameMap._dataLikedMaps.Top.height - $gameMap.offsetV + y) * $gameMap._dataLikedMaps.Top.width) + x;
                                    valueTile = $gameMap._dataLikedMaps.Top.data[indexTile];
                                }
                            } else if(x >= $gameMap.offsetH) { // Si on est après la jointure à gauche
                                if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                    indexTile = (z * $gameMap._dataLikedMaps.Top.height * $gameMap._dataLikedMaps.Top.width) + (($gameMap._dataLikedMaps.Top.height - $gameMap.offsetV + y) * $gameMap._dataLikedMaps.Top.width) + (x - $gameMap.offsetH);
                                    valueTile = $gameMap._dataLikedMaps.Top.data[indexTile];
                                }
                            }
                        }
                    }
                    
                    if(!!$gameMap._dataLikedMaps.Bottom) { // Si jointure en dessous
                        if(y >= newMap.height - $gameMap.offsetV) { // Si on est dans la partie à joindre
                            if(!$gameMap._dataLikedMaps.Left) { // S'il n'y a pas de jointure à gauche
                                if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                    if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                        indexTile = (z * $gameMap._dataLikedMaps.Bottom.height * $gameMap._dataLikedMaps.Bottom.width) + ((y - $dataMap.height) * $gameMap._dataLikedMaps.Bottom.width) + x;
                                        valueTile = $gameMap._dataLikedMaps.Bottom.data[indexTile];
                                    }
                                } else { // S'il n'y a pas de jointure au dessus
                                    if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                        indexTile = (z * $gameMap._dataLikedMaps.Bottom.height * $gameMap._dataLikedMaps.Bottom.width) + ((y - $dataMap.height - $gameMap.offsetV) * $gameMap._dataLikedMaps.Bottom.width) + x;
                                        valueTile = $gameMap._dataLikedMaps.Bottom.data[indexTile];
                                    }
                                }
                            } else if(x >= $gameMap.offsetH) { // Si on est après la jointure à gauche
                                if(!$gameMap._dataLikedMaps.Top) { // S'il n'y a pas de jointure au dessus
                                    if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                        indexTile = (z * $gameMap._dataLikedMaps.Bottom.height * $gameMap._dataLikedMaps.Bottom.width) + ((y - $dataMap.height) * $gameMap._dataLikedMaps.Bottom.width) + (x - $gameMap.offsetH);
                                        valueTile = $gameMap._dataLikedMaps.Bottom.data[indexTile];
                                    }
                                } else { // S'il n'y a pas de jointure au dessus
                                    if(!$gameMap._dataLikedMaps.Right || x < newMap.width - $gameMap.offsetH) { // S'il n'y a pas de jointure à droite ou qu'on se trouve avant
                                        indexTile = (z * $gameMap._dataLikedMaps.Bottom.height * $gameMap._dataLikedMaps.Bottom.width) + ((y - $dataMap.height - $gameMap.offsetV) * $gameMap._dataLikedMaps.Bottom.width) + (x - $gameMap.offsetH);
                                        valueTile = $gameMap._dataLikedMaps.Bottom.data[indexTile];
                                    }
                                }
                            }
                        }
                    }
                    
                    if(valueTile === 0) { // Si le tile n'a pas été défini avant
                        if(!$gameMap._dataLikedMaps.Top && !$gameMap._dataLikedMaps.Left) { // Si aucune jointure à gauche ou au dessus
                            if((!$gameMap._dataLikedMaps.Right || x < (newMap.width - $gameMap.offsetH)) && (!$gameMap._dataLikedMaps.Bottom || y < (newMap.height - $gameMap.offsetV))) { // Si on ne se trouve pas dans la jointure à droite ou en bas
                                indexTile = (z * $dataMap.height * $dataMap.width) + (y * $dataMap.width) + x;
                                valueTile = $dataMap.data[indexTile];
                            }
                        } else if(!$gameMap._dataLikedMaps.Top && !!$gameMap._dataLikedMaps.Left && x >= $gameMap.offsetH) { // Si jointure à gauche mais pas au dessus et si on est pas dans la zone à joindre
                            if((!$gameMap._dataLikedMaps.Right || x < (newMap.width - $gameMap.offsetH)) && (!$gameMap._dataLikedMaps.Bottom || y < (newMap.height - $gameMap.offsetV))) { // Si on ne se trouve pas dans la jointure à droite ou en bas
                                indexTile = (z * $dataMap.height * $dataMap.width) + (y * $dataMap.width) + (x - $gameMap.offsetH);
                                valueTile = $dataMap.data[indexTile];
                            }
                        } else if(!!$gameMap._dataLikedMaps.Top && !$gameMap._dataLikedMaps.Left && y >= $gameMap.offsetV) { // Si jointure au dessus mais pas à gauche et si on est pas dans la zone à joindre
                            if((!$gameMap._dataLikedMaps.Right || x < (newMap.width - $gameMap.offsetH)) && (!$gameMap._dataLikedMaps.Bottom || y < (newMap.height - $gameMap.offsetV))) { // Si on ne se trouve pas dans la jointure à droite ou en bas
                                indexTile = (z * $dataMap.height * $dataMap.width) + ((y - $gameMap.offsetV) * $dataMap.width) + x;
                                valueTile = $dataMap.data[indexTile];
                            }
                        } else if(!!$gameMap._dataLikedMaps.Top && !!$gameMap._dataLikedMaps.Left && y >= $gameMap.offsetV && x >= $gameMap.offsetH) { // Si jointures à gauche et au dessus et si on est pas dans la zone à joindre
                            if((!$gameMap._dataLikedMaps.Right || x < (newMap.width - $gameMap.offsetH)) && (!$gameMap._dataLikedMaps.Bottom || y < (newMap.height - $gameMap.offsetV))) { // Si on ne se trouve pas dans la jointure à droite ou en bas
                                indexTile = (z * $dataMap.height * $dataMap.width) + ((y - $gameMap.offsetV) * $dataMap.width) + (x - $gameMap.offsetH);
                                valueTile = $dataMap.data[indexTile];
                            }
                        }
                    }
                    
                    newMap.data[indexTileNewMap] = valueTile;
                }
            }
        }
        
        // Si jointure en haut ou à gauche, coordonnées du joueur et des évènements décalées
        if(!!$gameMap._dataLikedMaps.Top || !!$gameMap._dataLikedMaps.Left) {
            // Actualisation des coordonnées du joueur
            $gamePlayer._newX += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0);
            $gamePlayer._newY += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0);
            
            // Actualisation des coordonnées des évents
            for(e = 1; e < $dataMap.events.length; ++e) {
                if(!!$dataMap.events[e]) {
                    $dataMap.events[e].x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0);
                    $dataMap.events[e].y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0);
                }
            }
        }
        
        // Affichage des évents des maps jointes qui sont sur les parties affichées (ceux ci sont au préalable vidés de leurs commandes et ne s'exécuteront pas)
        if(!!$gameMap._dataCornerLinks.TopLeft) {
            for(e = 1; e < $gameMap._dataCornerLinks.TopLeft.events.length; ++e) {
                var event = $gameMap._dataCornerLinks.TopLeft.events[e];
                var ajouterEvent = false;
                if(!!event && event.x >= $gameMap._dataCornerLinks.TopLeft.width - $gameMap.offsetH && event.y >= $gameMap._dataCornerLinks.TopLeft.height - $gameMap.offsetV) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x -= ($gameMap._dataCornerLinks.TopLeft.width - $gameMap.offsetH);
                        event.y -= ($gameMap._dataCornerLinks.TopLeft.height - $gameMap.offsetV);
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataCornerLinks.TopRight) {
            for(e = 1; e < $gameMap._dataCornerLinks.TopRight.events.length; ++e) {
                var event = $gameMap._dataCornerLinks.TopRight.events[e];
                var ajouterEvent = false;
                if(!!event && event.x < $gameMap.offsetH && event.y >= $gameMap._dataCornerLinks.TopRight.height - $gameMap.offsetV) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0) + $dataMap.width;
                        event.y -= ($gameMap._dataCornerLinks.TopRight.height - $gameMap.offsetV);
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataCornerLinks.BottomLeft) {
            for(e = 1; e < $gameMap._dataCornerLinks.BottomLeft.events.length; ++e) {
                var event = $gameMap._dataCornerLinks.BottomLeft.events[e];
                var ajouterEvent = false;
                if(!!event && event.x >= $gameMap._dataCornerLinks.BottomLeft.width - $gameMap.offsetH && event.y < $gameMap.offsetV) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x -= ($gameMap._dataCornerLinks.BottomLeft.width - $gameMap.offsetH);
                        event.y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0) + $dataMap.height;
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataCornerLinks.BottomRight) {
            for(e = 1; e < $gameMap._dataCornerLinks.BottomRight.events.length; ++e) {
                var event = $gameMap._dataCornerLinks.BottomRight.events[e];
                var ajouterEvent = false;
                if(!!event && event.x < $gameMap.offsetH && event.y < $gameMap.offsetV) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0) + $dataMap.width;
                        event.y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0) + $dataMap.height;
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataLikedMaps.Left) {
            for(e = 1; e < $gameMap._dataLikedMaps.Left.events.length; ++e) {
                var event = $gameMap._dataLikedMaps.Left.events[e];
                var ajouterEvent = false;
                if(!!event && event.x >= $gameMap._dataLikedMaps.Left.width - $gameMap.offsetH && event.y < $dataMap.height) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x -= ($gameMap._dataLikedMaps.Left.width - $gameMap.offsetH);
                        event.y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0);
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataLikedMaps.Right) {
            for(e = 1; e < $gameMap._dataLikedMaps.Right.events.length; ++e) {
                var event = $gameMap._dataLikedMaps.Right.events[e];
                var ajouterEvent = false;
                if(!!event && event.x < $gameMap.offsetH && event.y < $dataMap.height) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0) + $dataMap.width;
                        event.y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0);
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataLikedMaps.Top) {
            for(e = 1; e < $gameMap._dataLikedMaps.Top.events.length; ++e) {
                var event = $gameMap._dataLikedMaps.Top.events[e];
                var ajouterEvent = false;
                if(!!event && event.y >= $gameMap._dataLikedMaps.Top.height - $gameMap.offsetV && event.x < $dataMap.width) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0);
                        event.y -= ($gameMap._dataLikedMaps.Top.height - $gameMap.offsetV);
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        if(!!$gameMap._dataLikedMaps.Bottom) {
            for(e = 1; e < $gameMap._dataLikedMaps.Bottom.events.length; ++e) {
                var event = $gameMap._dataLikedMaps.Bottom.events[e];
                var ajouterEvent = false;
                if(!!event && event.y < $gameMap.offsetV && event.x < $dataMap.width) {
                    for(p = 0; p < event.pages.length; ++p) {
                        event.pages[p].list = [];
                        event.pages[p].trigger = 0;
                        ajouterEvent = ajouterEvent || !!event.pages[p].image.characterName || !!event.pages[p].image.tileId;
                    }
                    if(ajouterEvent) {
                        event.id = $dataMap.events.length;
                        event.x += (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0);
                        event.y += (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0) + $dataMap.height;
                        $dataMap.events.push(event);
                    }
                }
            }
        }
        
        $dataMap.width = newMap.width;
        $dataMap.height = newMap.height;
        $dataMap.data = newMap.data;
        
        return Scene_Map.prototype.aliasMaplinkOnMapLoaded.call(this);
    };
    
    Game_Player.prototype.aliasMaplinkUpdate = Game_Player.prototype.update;
    Game_Player.prototype.update = function(sceneActive) {
        Game_Player.prototype.aliasMaplinkUpdate.call(this, sceneActive);
        if (!this.isMoving()) {
            this.checkMapLink();
        }
    };

    Game_Player.prototype.checkMapLink = function() {
        var newMapId = 0;
        if(!!$gameMap._dataLikedMaps.Left && this.direction() === 4 && this.x < $gameMap.offsetH) { // Jointure à gauche
            this.reserveTransfer(parseInt($dataMap.meta.linkLeft, 10), $gameMap._dataLikedMaps.Left.width - 1, this.y - (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0), 4, 2);
			if($gameTemp.isDestinationValid()) {
				var x = $gameMap._dataLikedMaps.Left.width + $gameTemp.destinationX() - $gameMap.offsetH;
				$gameTemp.setDestination(x, $gameTemp.destinationY());
			}
        } else if(!!$gameMap._dataLikedMaps.Right && this.direction() === 6 && this.x >= ($dataMap.width - $gameMap.offsetH)) { // Jointure à droite
            this.reserveTransfer(parseInt($dataMap.meta.linkRight, 10), 0, this.y - (!!$gameMap._dataLikedMaps.Top ? $gameMap.offsetV : 0), 6, 2);
			if($gameTemp.isDestinationValid()) {
				var x = $gameTemp.destinationX() - $dataMap.width + $gameMap.offsetH
				x += (!!$gameMap._dataLikedMaps.Right && !!$gameMap._dataLikedMaps.Right.meta && !!$gameMap._dataLikedMaps.Right.meta.linkLeft ? $gameMap.offsetH : 0);
				$gameTemp.setDestination(x, $gameTemp.destinationY());
			}
        } else if(!!$gameMap._dataLikedMaps.Top && this.direction() === 8 && this.y < $gameMap.offsetV) { // Jointure au dessus
            this.reserveTransfer(parseInt($dataMap.meta.linkTop, 10), this.x - (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0), $gameMap._dataLikedMaps.Top.height - 1, 8, 2);
			if($gameTemp.isDestinationValid()) {
				var y = $gameMap._dataLikedMaps.Top.height + $gameTemp.destinationY() - $gameMap.offsetV;
				$gameTemp.setDestination($gameTemp.destinationX(), y);
			}
        } else if(!!$gameMap._dataLikedMaps.Bottom && this.direction() === 2 && this.y >= ($dataMap.height - $gameMap.offsetV)) { // Jointure en dessous
            this.reserveTransfer(parseInt($dataMap.meta.linkBottom, 10), this.x - (!!$gameMap._dataLikedMaps.Left ? $gameMap.offsetH : 0), 0, 2, 2);
			if($gameTemp.isDestinationValid()) {
				var y = $gameTemp.destinationY() - $dataMap.height + $gameMap.offsetV
				y += (!!$gameMap._dataLikedMaps.Bottom && !!$gameMap._dataLikedMaps.Bottom.meta && !!$gameMap._dataLikedMaps.Bottom.meta.linkTop ? $gameMap.offsetV : 0);
				$gameTemp.setDestination($gameTemp.destinationX(), y);
			}
        }
    };
	
	Game_Temp.prototype.setDestination = function(x, y) {
		console.log(x, y);
		this._destinationX = x;
		this._destinationY = y;
	};
	
	Sprite_Destination.prototype.update = function() {
		Sprite.prototype.update.call(this);
		if(!$gamePlayer.isTransferring() && $gameTemp.isDestinationValid()){
			this.updatePosition();
			this.updateAnimation();
			this.visible = true;
		} else {
			this._frameCount = 0;
			this.visible = false;
		}
	};
})();

L’utilisation est assez simple. Cependant, pour que le maplink fonctionne, il est nécessaire que les deux cartes à joindre utilisent le même tileset, ou au moins que tous les éléments de chaque carte affichée sur l’autre soient placés de facon identique sur les 2 tilesets.
Une fois jointes, les lignes (pour les maps au dessus et en dessous)/colonnes (pour les maps à gauche et à droite) à proximité de la jointure seront affichées sur la map courante.

Les remarques à insérer dans les propriétés des cartes sont les suivantes :

  • <linkLeft:ID_CARTE> : Pour joindre la carte ID_CARTE à gauche
  • <linkRight:ID_CARTE> : Pour joindre la carte ID_CARTE à droite
  • <linkTop:ID_CARTE> : Pour joindre la carte ID_CARTE au dessus
  • <linkBottom:ID_CARTE> : Pour joindre la carte ID_CARTE en dessous

Voilà un premier schéma expliquant comment joindre différentes cartes ensemble, la map courante étant celle sur laquelle se trouve le joueur.

Un maximum de 4 cartes peuvent être jointes : une au dessus (linkTop), une en dessous (linkBottom), une à gauche (linkLeft) et une à droite (linkRight).

Il n’est pas nécessaire que les cartes jointes fassent la même dimension, mais le côté en commun devrait être de même taille sur les deux cartes pour éviter l’apparition de tiles noirs au niveau de la jointure.

En outre, actuellement, les jointures sont alignées à partir de la gauche de chaque carte pour les jointures horizontales (linkLeft et linkRight) et à partir du haut pour les jointures verticales (linkTop et linkBottom).

Dans l’exemple ci-dessus, le coin en haut à gauche serait rempli de tiles vides. Une solution pourrait être alors d’empêcher le joueur d’approcher de ce coin. Cependant, le maplink peut également remplir ce vide automatiquement, si les cartes 2 et 3 sont elles même jointes à une même carte comme dans le schéma ci-dessous :

En outre, les évents présents dans les zones affichées des cartes jointes seront aussi affichés si ceux-ci ont une apparence sur au moins une page. Les évènements ainsi ajoutés ne seront pas exécutés (dans le cas où ceux-ci sont en démarrage automatique ou en processus parallèle) et leur apparence sur la carte sera conditionné aux mêmes règles que sur leur propre carte.

Ce plugin intègre 2 paramètres :

  • Taille jointure horizontale : Nombre de colonnes de tiles affichées des cartes jointes à gauche ou à droite (par défaut : 9)
  • Taille jointure verticale : Nombre de lignes de tiles affichées des cartes jointes au dessus ou en dessous (par défaut : 7)

Le choix des valeurs par défaut s’explique ainsi : dans le cas de la résolution par défaut des jeux RMMV (soit 17×13 tiles) c’est le nombre de lignes/colonnes qu’il faut ajouter à la carte courante pour que le joueur ait l’impression de se déplacer sur une seule et même carte plutôt que sur plusieurs morceaux de plus petite taille.

Pour un rendu optimal, il est évidemment recommandé de bien penser à faire les jointures sur les 2 cartes (sans quoi, au moment de la téléportation de la première carte à la seconde, le joueur se retrouve totalement au bord de la carte).

Ce plugin est actuellement destiné à être utilisé pour remplacer de grandes cartes (connues pour lagguer) comme de grandes villes ou de longues routes/grottes/… par de plus petites assemblées les unes aux autres.

Ce qui reste à intégrer/améliorer :

  • Fluidifier la transition entre 2 cartes (actuellement, si le joueur se déplace avant la fin de sa téléportation – s’il maintient une touche de déplacement par exemple -, il y a comme un effet saccadé au moment de la transition)
  • Intégrer la possibilité d’un décalage dans la jointure
  • Joindre des maps utilisant des tilesets différents
  • Mettre un tile par défaut pour remplacer les tiles vides

Voici une vidéo montrant ce qu’on peut obtenir avec ce système :

Remerciements

Je dois remercier Tonyryu pour ses notes (disponibles à cette adresse : https://www.rpgmakervx-fr.com/t19192-note-technique-les-tile-id-et-leur-decodage-pour-affichage) sur la gestion des tiles.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.