//============================================================================== // MpiSwapArea //============================================================================== /*: * @plugindesc マップの内容を部分的に入れ替える機能を提供します。 * @author 奏ねこま(おとぶき ねこま) * * @param Disable Transfer Position Swapping Switch ID * @type switch * @desc 場所移動時、移動先の入れ替えを無効化するスイッチの番号を指定してください。 * @default 0 * * @help * [説明] * メモ欄に指定された条件に基づいて、マップの内容を部分的に入れ替えます。 * (制限事項あり。[制限事項]を参照) * * [プラグインパラメータ] * Disable Transfer Position Swapping Switch ID * 場所移動時、移動先の入れ替えを無効化するスイッチの番号を指定します。 * * - このパラメータで指定した番号のスイッチがOFFの場合(デフォルト) - * 場所移動によってプレイヤーが移動する先のエリアが他の場所と入れ替わっていた * 場合、移動先もそれに合わせて入れ替わります。例えば指定した移動先が(10,10)の * とき、その位置が(20,20)と入れ替わっていた場合、移動先は(20,20)になります。 * * - このパラメータで指定した番号のスイッチがONの場合 - * エリアの入れ替わりに関わらず、指定した座標に移動します。例えば指定した移動 * 先が(10,10)のとき、エリア入れ替え後のマップにおいても(10,10)に移動します。 * * [使用方法] * マップのメモ欄に、入れ替え条件を指定したタグを記述します。 * * ---- * 指定した二か所の範囲を入れ替えるタグ(複数記述可) * * * 例:x=5,y=10から横幅10マス、縦幅20マスを、x=20,y=25の場所と入れ替える * * * 例:スイッチ99番がONのとき、入れ替える * * * ---- * マップを指定数で分割し、ランダムで入れ替えるタグ(複数記述可) * * * 例:マップ全体を縦4つ、横6つに分割し、分割したエリアをランダムで入れ替える * * * 例:スイッチ99番がONのとき、ランダムに入れ替える * * * ---- * 入れ替え状態に合わせて遠景画像も入れ替えるタグ * * * 遠景画像を一枚絵のマップ画像として使用している場合、上記タグを指定すること * で入れ替え状態に合わせて遠景画像も入れ替わります。 * * ---- * 座標や範囲、スイッチ番号には、変数を指定することもできます。 * \v[変数番号]と記述することで、その変数の値が使用されます。 * * 例:入れ替え元座標、入れ替え範囲、入れ替え先座標、スイッチ番号を変数で指定 * * * 例:分割数、スイッチ番号を変数で指定 * * * [制限事項] * 座標などの指定に変数やスイッチを指定した場合、「変数やスイッチの最新の状態」 * がマップに反映されるのは、「別のマップからそのマップに移動してきたとき」にな * ります。マップ表示中に変数やスイッチの状態を変更しても、別のマップから再びそ * のマップに移動してくるまでは、表示に反映されません。同一マップ内での移動につ * いても同様に反映されませんので、変数やスイッチの状態をすぐに反映させたい場合 * は「一度別のマップに移動してから戻ってくる処理」を入れるようにしてください。 * * [利用規約] .................................................................. * - 本プラグインの利用は、RPGツクールMV/RPGMakerMVの正規ユーザーに限られます。 * - 商用、非商用、有償、無償、一般向け、成人向けを問わず、利用可能です。 * - 利用の際、連絡や報告は必要ありません。また、製作者名の記載等も不要です。 * - プラグインを導入した作品に同梱する形以外での再配布、転載はご遠慮ください。 * - 本プラグインにより生じたいかなる問題についても、一切の責任を負いかねます。 * [改訂履歴] .................................................................. * Version 1.02 2018/04/08 場所移動先の切り替え機能を追加。 * Version 1.01 2018/04/05 遠景画像の入れ替えに対応。 * Version 1.00 2018/04/01 First edition. * -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- * Web Site: http://makonet.sakura.ne.jp/rpg_tkool/ * Twitter : https://twitter.com/koma_neko * Copylight (c) 2018 Nekoma Otobuki */ var Imported = Imported || {}; var Makonet = Makonet || {}; (function(){ 'use strict'; var plugin = 'MpiSwapArea'; Imported[plugin] = true; Makonet[plugin] = {}; var MPI = Makonet[plugin]; MPI.parameters = PluginManager.parameters(plugin); MPI.DisableTransferPositionSwappingSwitchID = Number(MPI.parameters['Disable Transfer Position Swapping Switch ID']) || 0; //============================================================================== // Private Methods //============================================================================== // 文字列中の \v[n] を変数の値に変換する関数 function convertVariables(text) { if (typeof(text) !== 'string') return text; var pattern = '\\\\v\\[(\\d+)\\]'; while (text.match(RegExp(pattern, 'i'))) { text = text.replace(RegExp(pattern, 'gi'), function(){ return $gameVariables.value(+arguments[1]); }); } return text; } // 入れ替え処理メイン function swapArea(x1, y1, width, height, x2, y2) { // マップタイル他、マップ情報の入れ替え for (var i = 0; i < 6; i++) { var data1 = Array.apply(null, new Array(height)).map(function(){ return Array.apply(null, new Array(width)).map(function(){ return 0 }) }); var data2 = Array.apply(null, new Array(height)).map(function(){ return Array.apply(null, new Array(width)).map(function(){ return 0 }) }); var offset = i * $dataMap.width * $dataMap.height; var x, y; // 入れ替え元の情報を取得 for (y = 0; y < height && (y + y1) < $dataMap.height; y++) { for (x = 0; x < width && (x + x1) < $dataMap.width; x++) { data1[y][x] = $dataMap.data[offset + (y + y1) * $dataMap.width + (x + x1)]; } } for (y = 0; y < height && (y + y2) < $dataMap.height; y++) { for (x = 0; x < width && (x + x2) < $dataMap.width; x++) { data2[y][x] = $dataMap.data[offset + (y + y2) * $dataMap.width + (x + x2)]; } } // 入れ替え先に情報を反映 for (y = 0; y < height && (y + y1) < $dataMap.height; y++) { for (x = 0; x < width && (x + x1) < $dataMap.width; x++) { $dataMap.data[offset + (y + y1) * $dataMap.width + (x + x1)] = data2[y][x]; } } for (y = 0; y < height && (y + y2) < $dataMap.height; y++) { for (x = 0; x < width && (x + x2) < $dataMap.width; x++) { $dataMap.data[offset + (y + y2) * $dataMap.width + (x + x2)] = data1[y][x]; } } } // イベント位置の入れ替え $dataMap.events.forEach(function(event) { if (event) { var ex = event.x; var ey = event.y; if (ex >= x1 && ex < (x1 + width) && ey >= y1 && ey < (y1 + height)) { ex = x2 + (ex - x1); ey = y2 + (ey - y1); } else if (ex >= x2 && ex < (x2 + width) && ey >= y2 && ey < (y2 + height)) { ex = x1 + (ex - x2); ey = y1 + (ey - y2); } event.x = ex; event.y = ey; } }); // プレイヤー位置の入れ替え if (MPI.DisableTransferPositionSwappingSwitchID === 0 || $gameSwitches.value(MPI.DisableTransferPositionSwappingSwitchID) === false) { var px = $gamePlayer._newX; var py = $gamePlayer._newY; if (px >= x1 && px < (x1 + width) && py >= y1 && py < (y1 + height)) { px = x2 + (px - x1); py = y2 + (py - y1); } else if (px >= x2 && px < (x2 + width) && py >= y2 && py < (y2 + height)) { px = x1 + (px - x2); py = y1 + (py - y2); } $gamePlayer._newX = px; $gamePlayer._newY = py; } }; // 遠景画像の入れ替え function swapAreaParallax(parallax) { if (parallax.bitmap.isReady()) { var bitmap1 = parallax.bitmap; var bitmap2 = new Bitmap(bitmap1.width, bitmap1.height); // 遠景画像をまるごとコピー bitmap2.bltImage(bitmap1, 0, 0, bitmap1.width, bitmap2.height, 0, 0); $gameMap.__swapArea__.list.forEach(function(swap_area) { var tileWidth = $gameMap.tileWidth(); var tileHeight = $gameMap.tileHeight(); var x1 = swap_area.x1 * tileWidth; var y1 = swap_area.y1 * tileHeight; var width = swap_area.width * tileWidth; var height = swap_area.height * tileHeight; var x2 = swap_area.x2 * tileWidth; var y2 = swap_area.y2 * tileHeight; if (x1 + width > bitmap1.width || x2 + width > bitmap1.width) { width = Math.min(bitmap1.width - x1, bitmap1.width - x2); } if (y1 + height > bitmap1.height || y2 + height > bitmap1.height) { height = Math.min(bitmap1.height - y1, bitmap1.height - y2); } // 入れ替え部分の画像をコピー bitmap2.bltImage(bitmap1, x1, y1, width, height, x2, y2); bitmap2.bltImage(bitmap1, x2, y2, width, height, x1, y1); }); // 遠景画像を差し替え parallax.bitmap = bitmap2; } else { parallax.bitmap.addLoadListener(swapAreaParallax.bind(this, parallax)); } } // 入れ替え範囲の設定(位置、範囲指定) function setSwapArea(x1, y1, width, height, x2, y2, switchId) { if (switchId > 0 && !$gameSwitches.value(switchId)) { return; } if (width <= 0 || height <= 0) { return; } $gameMap.__swapArea__.list.push({ x1: x1, y1: y1, width: width, height: height, x2: x2, y2: y2 }); }; // 入れ替え範囲の設定(位置ランダム) function randomSetSwapArea(rows, cols, switchId) { if (switchId > 0 && !$gameSwitches.value(switchId)) { return; } var width = $dataMap.width / cols; var height = $dataMap.height / rows; var areas = Array.apply(null, new Array(rows * cols)).map(function(v,i) { var x = (i % cols) * width; var y = Math.floor(i / cols) * height; return { x: x, y: y }; }); var random_areas = []; while (areas.length > 0) { random_areas.push(areas.splice(Math.floor(Math.random() * areas.length), 1)[0]); } for (var i = 0; i < random_areas.length; i += 2) { $gameMap.__swapArea__.list.push({ x1: random_areas[i].x, y1: random_areas[i].y, width: width, height: height, x2: random_areas[i+1].x, y2: random_areas[i+1].y }); } }; //============================================================================== // Scene_Map //============================================================================== // Scene_Map.prototype.onMapLoaded (function(o,p){ var f=o[p];o[p]=function(){ $gameMap.__swapArea__ = $gameMap.__swapArea__ || { list: [], parallax: false }; // マップのリロード時に、入れ替え位置、範囲を設定 if (this._transfer && ($gamePlayer._newMapId !== $gameMap.mapId() || $gamePlayer._needsMapReload)) { var regexp = new RegExp(/<(swap_area|random_swap_area):(.+?)>/gi); var result; $gameMap.__swapArea__ = { list: [], parallax: !!$dataMap.meta['swap_area_parallax'] }; while (result = regexp.exec($dataMap.note)) { var params = [0, 0, 0, 0, 0, 0, 0]; result[2].trim().split(/ *, */).forEach(function(param, index) { params[index] = Number(convertVariables(param)) || 0; }); if (result[1].toLowerCase() === 'swap_area') { setSwapArea(params[0], params[1], params[2], params[3], params[4], params[5], params[6]); } else { randomSetSwapArea(params[0], params[1], params[2]); } } } // 入れ替え実行 $gameMap.__swapArea__.list.forEach(function(swap_area) { swapArea(swap_area.x1, swap_area.y1, swap_area.width, swap_area.height, swap_area.x2, swap_area.y2); }); return f.apply(this,arguments); }; }(Scene_Map.prototype,'onMapLoaded')); //============================================================================== // Spriteset_Map //============================================================================== // Spriteset_Map.prototype.updateParallax (function(o,p){ var f=o[p];o[p]=function(){ var update = (this._parallaxName !== $gameMap.parallaxName()); f.apply(this,arguments); if (update) { if ($gameMap.__swapArea__ && $gameMap.__swapArea__.parallax && $gameMap.__swapArea__.list.length > 0) { swapAreaParallax(this._parallax); } } }; }(Spriteset_Map.prototype,'updateParallax')); }());