1800 lines
No EOL
74 KiB
JavaScript
1800 lines
No EOL
74 KiB
JavaScript
//========================================
|
||
// TF_LayeredMap.js
|
||
// Version :1.0.4.0
|
||
// For : RPGツクールMV (RPG Maker MV)
|
||
// -----------------------------------------------
|
||
// Copyright : Tobishima-Factory 2018 - 2020
|
||
// Website : http://tonbi.jp
|
||
//
|
||
// This software is released under the MIT License.
|
||
// http://opensource.org/licenses/mit-license.php
|
||
//========================================
|
||
/*:
|
||
* @plugindesc Upper[☆]tile display like billboard.
|
||
* @author Tonbi@Tobishima-Factory
|
||
*
|
||
*
|
||
* @param BillboardPriority
|
||
* @type select
|
||
* @option Put it front
|
||
* @value front
|
||
* @option Put it back
|
||
* @value back
|
||
* @desc Put billboard in front or back.
|
||
* @default back
|
||
*
|
||
*
|
||
* @param Autotile
|
||
*
|
||
* @param FillWithNeighborTile
|
||
* @type boolean
|
||
* @on Fill with neighbor tile
|
||
* @off Default lower tile
|
||
* @desc Fill with neighbor tile.It is function for A3 or A4 tile.
|
||
* @default true
|
||
* @parent Autotile
|
||
*
|
||
* @param DefaultLowerTile
|
||
* @type number
|
||
* @min 0
|
||
* @max 127
|
||
* @desc If FillWithNeighborTile option is OFF, fill with this tile.
|
||
* Start with 0 at upper left A5 to right.
|
||
* @default 16
|
||
* @parent Autotile
|
||
*
|
||
* @param UseLayeredCounter
|
||
* @type boolean
|
||
* @on Layered counter
|
||
* @off Normal
|
||
* @desc Counter becomes layered.
|
||
* A2 counter tile can layered like billboard.
|
||
* (HalfMove.js is needed)
|
||
* @default true
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA2FullCollision
|
||
* @type boolean
|
||
* @on Full collision
|
||
* @off Closed and inside is accessible
|
||
* @desc Entire tile on the ground(A2) collision to activate.
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA3UpperOpen
|
||
* @type boolean
|
||
* @on Open
|
||
* @off Close
|
||
* @desc Remove the south collision of the roof(A3)?
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA4UpperOpen
|
||
* @type boolean
|
||
* @on Open
|
||
* @off Close
|
||
* @desc Remove the south collision of the wall top(A4)?
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
*
|
||
* @param Overpass
|
||
*
|
||
* @param OverpassTerrainTag
|
||
* @type number
|
||
* @min 0
|
||
* @max 7
|
||
* @desc Terraing tag for overpass tile.
|
||
* @default 3
|
||
* @parent Overpass
|
||
*
|
||
* @param CharacterSize
|
||
* @type select
|
||
* @option 1tile size
|
||
* @value 1
|
||
* @option 2tile size
|
||
* @value 2
|
||
* @desc Collision of overpass for.
|
||
* @default 1
|
||
* @parent Overpass
|
||
*
|
||
*
|
||
* @help
|
||
* Alert !!
|
||
* If you use HalfMove.js by Triacontane.Place HalfMove.js before TF_LayeredMap.js.
|
||
* And Place TF_LayeredMap.js before TF_Undulation.js.
|
||
*
|
||
* This plug-in provides the following functions.
|
||
* 1. [☆]+[4 direction pass] Billboard function for B〜E tile is added.
|
||
* 2. [TerrainTag] Crosspass function for B〜E tile is added.
|
||
* 3. [Counter] Billboard function for auto tile is added.
|
||
* 4. [TerrainTag] Auto tile collision and overpass function for bridge is added.
|
||
* 5. [Counter] [TerrainTag] Upper auto tile overpass function is added.
|
||
* 6. [TerrainTag] [×] The wall top that does not walk for A4 upper tile is added.
|
||
* 7. [TerrainTag] A5 tile up one layer.
|
||
* 8. <TF_zDef:Number> Put this tag in the note in event and adjust the overlap.
|
||
* 9. <TF_higherLevel:Boolean> Put this tag in the note in event and set overpass higher level.
|
||
*
|
||
* 1. set [☆] to BCDE tile, and set 4 direction setting.
|
||
* 0x0 ↑→←↓ : [☆] Same as no plugin.
|
||
* 0x1 ↑→←・ : billboard, ↑ ←→ pass, ground (for fence)
|
||
* 0x2 ↑→・↓ : billboard, ↑↓ → pass, ground (left side of fence)┃
|
||
* 0x3 ↑→・・ : billboard, ↑ → pass, ground (bottom left)┗
|
||
* 0x4 ↑・←↓ : billboard, ↑↓← pass, ground (right) ┃
|
||
* 0x5 ↑・←・ : billboard, ↑ ← pass, ground (bottom right) ┛
|
||
* 0x6 ↑・・↓ : billboard, ↑↓ pass, ground (both side)┃┃
|
||
* 0x7 ↑・・・ : billboard, ↑ pass, ground (like bartizan)┗┛
|
||
* 0x8 ・→←↓ : billboard, all directtion , ground (for bush)
|
||
* 0x9 ・→←・ : billboard, all directtion , 2nd floor
|
||
* 0xA ・→・↓ : billboard, all directtion , 3rd floor
|
||
* 0xB ・→・・ : Same as [○] and north half blocked (for lower shelf) (HalfMove.js is needed)
|
||
* 0xC ・・←↓ : Same as 0x1 and south half blocked (for Barrel) (HalfMove.js is needed)
|
||
* 0xD ・・←・ : Same as 0xB and collision is half (for lower tree) (HalfMove.js is needed)
|
||
* 0xE ・・・↓ : Same as 0xC and collision is half (for chair) (HalfMove.js is needed)
|
||
* 0xF ・・・・ : Same as 0x1 and collision is half (for peg)(HalfMove.js is needed)
|
||
*
|
||
* 2. Set TerrainTag to 3(default)
|
||
* If you enter from blocke direction, you can move under the tile.
|
||
* If you enter from pass direction, you can move over the tile.
|
||
*
|
||
* 3. For the clif.
|
||
* First, set [counter].
|
||
* A3・A4 odd line(roof・walltop)
|
||
* [○] All = upper[☆]
|
||
* A3・A4 even line(wallside)
|
||
* [○] All = billboard, South=can't pass.(floor height set automaticaly)
|
||
* Common to A3 and A4
|
||
* [×] North = billboard, Perimeter = can't pass.
|
||
*
|
||
* 4. For the bridge or the stairs.
|
||
* First, set [TerrainTag:3].
|
||
* A3 odd line(roof)
|
||
* [○] SouthNorth = can't pass, WestEast = pass.
|
||
* [×] SouthNorth = pass under、WestEast = pass over.
|
||
* A3・A4 even line(wallside)
|
||
* [○] SouthNorth = pass, WestEast = can't pass.
|
||
* [×] SouthNorth = pass over, WestEast = pass under.
|
||
*
|
||
* 5. For the overpass.
|
||
* First, set [counter][TerrainTag:3].
|
||
* A3・A4 odd line(roof・walltop)
|
||
* [○] All = overpass.
|
||
* [×] North = overpass, Perimeter = can't pass.
|
||
*
|
||
* 6. For the wall that does not walk on.
|
||
* A4 odd line(walltop)
|
||
* [TerrainTag:3][×] North = upper[☆], All = can't enter.
|
||
*
|
||
* 7. Move up one layer.
|
||
* Add [TerrainTag:3] to A5 tile, Set the tile at base layer and target tile up one layer.
|
||
* The overpass will not work. If the right side of A2 is on the target tile, it will gone.
|
||
*
|
||
* 8. adjust the overlap
|
||
* <TF_zDef:Number> Put this tag in the note in event.
|
||
* Add a number to the y position and set a virtual y position.
|
||
* Enter a number greater than 6 (default) to bring the character to the front.
|
||
*
|
||
* 9. set overpass higher level.
|
||
* <TF_higherLevel:Boolean> Put this tag in the note in event.
|
||
* true:front(upper)、false:back(lower)
|
||
* default:false
|
||
*
|
||
* Released under the MIT License.
|
||
*/
|
||
/*:ja
|
||
* @plugindesc 高層[☆]タイルを書き割り風に配置する
|
||
* @author とんび@鳶嶋工房
|
||
*
|
||
* @param BillboardPriority
|
||
* @type select
|
||
* @option 手前
|
||
* @value front
|
||
* @option 奥(規定値)
|
||
* @value back
|
||
* @text 奥行き優先度
|
||
* @desc 書き割りの奥・手前配置の設定
|
||
* @default back
|
||
*
|
||
*
|
||
* @param Autotile
|
||
* @text オートタイル
|
||
*
|
||
* @param FillWithNeighborTile
|
||
* @type boolean
|
||
* @on 周辺のタイル
|
||
* @off 補完用規定タイル
|
||
* @text 周辺のタイルでの補完
|
||
* @desc 低層(地面)を北(最南端は南)のタイルで補完するか
|
||
* @default true
|
||
* @parent Autotile
|
||
*
|
||
* @param DefaultLowerTile
|
||
* @type number
|
||
* @min 0
|
||
* @max 127
|
||
* @text 補完用規定タイル
|
||
* @desc [周辺のタイルでの補完]がOFFの場合に使う規定タイル
|
||
* 番号はA5左上を0として右への順。規定値:16(草原)
|
||
* @default 16
|
||
* @parent Autotile
|
||
*
|
||
* @param UseLayeredCounter
|
||
* @type boolean
|
||
* @text カウンター回り込み
|
||
* @on 回り込み
|
||
* @off 通常
|
||
* @desc A2のカウンターの後ろに回り込めるようにするか
|
||
* (HalfMove.js が必要)
|
||
* @default true
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA2FullCollision
|
||
* @type boolean
|
||
* @on 通行止め
|
||
* @off 閉じて内側は通行可
|
||
* @text タイル全体を通行不可にするか
|
||
* @desc A2(地面)のタイル全体を通行不可にするか
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA3UpperOpen
|
||
* @type boolean
|
||
* @on 南を開く
|
||
* @off 閉じて内側は通行可
|
||
* @text 屋根南を開くか
|
||
* @desc A3(屋根)[周囲=通行不可]の場合に、南の衝突判定をなくすか
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
* @param IsA4UpperOpen
|
||
* @type boolean
|
||
* @on 南を開く
|
||
* @off 閉じて内側は通行可
|
||
* @text 壁上面南を開くか
|
||
* @desc A4(壁上上面)[周囲=通行不可]の場合に、南の衝突判定をなくすか
|
||
* @default false
|
||
* @parent Autotile
|
||
*
|
||
*
|
||
* @param Overpass
|
||
* @text 立体交差
|
||
*
|
||
* @param OverpassTerrainTag
|
||
* @type number
|
||
* @min 0
|
||
* @max 7
|
||
* @text 立体交差の地形タグ
|
||
* @desc 立体交差不使用 : 0
|
||
* 立体交差をさせたいタイルに指定する地形タグ
|
||
* @default 3
|
||
* @parent Overpass
|
||
*
|
||
* @param CharacterSize
|
||
* @type select
|
||
* @option 1tile size
|
||
* @value 1
|
||
* @option 2tile size
|
||
* @value 2
|
||
* @desc Collision of overpass for.
|
||
* @text キャラのタイルサイズ
|
||
* @desc 立体交差の衝突判定用のキャラサイズ
|
||
* @default 1
|
||
* @parent Overpass
|
||
*
|
||
*
|
||
* @help
|
||
* 注意 : トリアコンタンさんの HalfMove.js を利用する場合は。
|
||
* TF_LayeredMap.js の前に HalfMove.js を配置するようにしてください。
|
||
* TF_Undulation.js と一緒の場合は、TF_LayeredMap.js が前です。
|
||
*
|
||
* このプラグインは以下の機能を提供します。
|
||
* 1. [☆]+[通行設定(4方向)]で、B〜Eタイルの重なり機能を追加。
|
||
* 2. [地形タグ]で、B〜Eタイルの立体交差機能を追加。
|
||
* 3. [カウンター]で、A3・A4タイルに回り込み機能を追加。
|
||
* 4. [地形タグ]で、A3・A4タイルに橋の衝突判定と立体交差機能を追加。
|
||
* 5. [カウンター] [地形タグ] で、A3・A4タイル上面に立体交差機能を追加。
|
||
* 6. [地形タグ] [×] で、A4上面タイルに上を歩かない壁用の設定。
|
||
* 7. [地形タグ]で、A5タイルをひとつ上のレイヤーに移動。
|
||
* 8. <TF_zDef:数値> をイベントのメモに記入して重なりの調整。
|
||
* 9. <TF_higherLevel:真偽値> をイベントのメモに記入して立体交差の奥手前の指定。
|
||
* 10. TF_HIGHER_LEVEL コマンドで立体交差の奥手前の指定。
|
||
*
|
||
* 1. B〜Eタイルに[☆]を指定したあと、[通行設定(4方向)]
|
||
* 0x0 ↑→←↓ : [☆] 設定、全方向に 通行可(プラグインなしと同じ)
|
||
* 0x1 ↑→←・ : 書き割り、北 西東 通行可、1階 【基本、柵とか】
|
||
* 0x2 ↑→・↓ : 書き割り、北南 東 通行可、1階 (柵の西側とか)┃
|
||
* 0x3 ↑→・・ : 書き割り、北 東 通行可、1階 (柵の西南とか)┗
|
||
* 0x4 ↑・←↓ : 書き割り、北南西 通行可、1階 (柵の東側とか) ┃
|
||
* 0x5 ↑・←・ : 書き割り、北 西 通行可、1階 (柵の東南とか) ┛
|
||
* 0x6 ↑・・↓ : 書き割り、北南 通行可、1階 (両脇に木とか)┃┃
|
||
* 0x7 ↑・・・ : 書き割り、北 通行可、1階 (張り出し的な)┗┛
|
||
* 0x8 ・→←↓ : 書き割り、全方向に 通行可、1階 (草むらなどに)
|
||
* 0x9 ・→←・ : 書き割り、全方向に 通行可、2階
|
||
* 0xA ・→・↓ : 書き割り、全方向に 通行可、3階
|
||
* 0xB ・→・・ : 地面[○] 設定かつ北半分通行不可 (棚などに)(HalfMove.js が必要)
|
||
* 0xC ・・←↓ : 0x1 と同じだが南半分が通行不可 (机などに)(HalfMove.js が必要)
|
||
* 0xD ・・←・ : 0xB と同じだが北の両脇が通行可 (根元とか)(HalfMove.js が必要)
|
||
* 0xE ・・・↓ : 0xC と同じだが南の両脇が通行可 (椅子とか)(HalfMove.js が必要)
|
||
* 0xF ・・・・ : 0x1 と同じだが南の両脇が通行可 (杭などに)(HalfMove.js が必要)
|
||
*
|
||
* 2. [地形タグ]を3(規定値)に設定
|
||
* 通行設定で侵入可の方向から入ると上を通ります。
|
||
* 侵入不可の方向から入ると下を通ります。
|
||
*
|
||
* 3. 崖など回り込み用
|
||
* [カウンター]設定
|
||
* A3・A4の奇数列(屋根・壁上面)
|
||
* [○] 全体=高層[☆]
|
||
* A3・A4の偶数列(壁)
|
||
* [○] 全体=回り込み、南方向は通行不可(壁の高さは自動調整)
|
||
* A3・A4に共通
|
||
* [×] 北=回り込み、周囲=通行不可
|
||
*
|
||
* 4. 橋の立体交差や階段用
|
||
* [地形タグ:3]設定
|
||
* A3の奇数列(屋根)
|
||
* [○]南北=通行不可、東西=通行
|
||
* [×]南北=下通行、東西=上通行(立体交差)
|
||
* A3・A4の偶数列(壁)
|
||
* [○]南北=通行、東西=通行不可
|
||
* [×]南北=上通行、東西=下通行(立体交差)
|
||
*
|
||
* 5. 立体交差
|
||
* [カウンター] [地形タグ:3] 設定
|
||
* A3・A4の奇数列(屋根・壁上面)
|
||
* [○]全面立体交差
|
||
* [×]北=立体交差、周囲=通行不可
|
||
*
|
||
* 6. 上を歩かない壁用の設定
|
||
* A4の奇数列(壁上面)
|
||
* [地形タグ:3][×] 北=高層[☆]、全面通行不可
|
||
*
|
||
* 7. ひとつ上のレイヤーに移動
|
||
* A5タイルに[地形タグ:3] で、背景を補完しA2右側レイヤーに移動。
|
||
* 立体交差は機能しないし、A2右側タイルがあれば消える。
|
||
*
|
||
* 8. 重ね合わせの順番を調節
|
||
* <TF_zDef:数値> をイベントのメモに入力。
|
||
* 数値はy位置に加えられて、仮想的にy位置をずらす。
|
||
* キャラ画像は標準環境でy方向に-6ずれているので、例えば8を入れると手前に表示される。
|
||
*
|
||
* 9. 立体交差の奥手前の指定
|
||
* <TF_higherLevel:真偽値> をイベントのメモに入力
|
||
* trueだと立体交差の手前(上)、falseだと奥(下)に配置される。
|
||
* 規定値はfalse。
|
||
*
|
||
* 10. プラグインコマンドで立体交差の奥手前の指定。
|
||
* TF_HIGHER_LEVEL 真偽値 対象(省略可)
|
||
* 対象は -2~-4:隊列キャラ、-1:プレイヤーキャラ、0:イベント自身(規定値)、1以降:イベントID
|
||
*
|
||
* 利用規約 : MITライセンス
|
||
*/
|
||
( function() {
|
||
'use strict';
|
||
const TF_HIGHER_LEVEL = 'TF_HIGHER_LEVEL';
|
||
|
||
// flag用定数
|
||
const FLAG_NORTH_DIR = 0x8; // 北の通行設定
|
||
const FLAG_UPPER = 0x10; // 高層[☆]
|
||
const FLAG_COUNTER = 0x80; // カウンター
|
||
// flagのマスク
|
||
const MASK_WITHOUT_DIR_UPPER = 0xFF60; // 方向と高層[☆]とカウンターを除いたもの用マスク
|
||
const MASK_WITHOUT_TAG_DIR_UPPER = 0xF60; // 方向と高層[☆]と地形タグとカウンターを除いたもの用マスク
|
||
const MASK_ALL_DIR = 0xF; // 通行設定用マスク
|
||
|
||
// 書割り設定
|
||
const FLOOR2_BOARD = 0x19; // 09 書き割り、全方向に 通行可、2階
|
||
const FLOOR3_BOARD = 0x1A; // 10 書き割り、全方向に 通行可、3階
|
||
|
||
const MASK_UPPER_DIR = 0x1F; // 高層[☆]と通行設定用マスク
|
||
const FLOOR1_N_FULL = 0x1B; // 11 棚
|
||
const FLOOR1_S_FULL = 0x1C; // 12 机
|
||
const FLOOR1_N_HALF = 0x1D; // 13 椅子(北)
|
||
const FLOOR1_S_HALF = 0x1E; // 14 椅子(南)
|
||
const FLOOR1_S_FLAT = 0x1F; // 15 杭
|
||
|
||
const AUTOTILE_BLOCK = 48; // オートタイル1ブロック分のパターン数
|
||
|
||
|
||
/*---- パラメータパース関数 ----*/
|
||
const PARAM_TRUE = 'true';
|
||
const PARAM_ON = 'on';
|
||
const TYPE_BOOLEAN = 'boolean';
|
||
const TYPE_NUMBER = 'number';
|
||
/**
|
||
* 指定したパラメータが、指定した値と同じか。
|
||
* @param {String} paramName パラメータ名
|
||
* @param {String} param 比較する値(小文字)
|
||
* @param {Boolean} defaultParam 規定値
|
||
* @returns {Boolean}
|
||
*/
|
||
function conpairPluginParam( paramName, param, defaultParam ) {
|
||
if( pluginParams[ paramName ] ) {
|
||
return pluginParams[ paramName ].toLowerCase() === param;
|
||
} else {
|
||
return defaultParam;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 与えられた文字列に変数が指定されていたら、変数の内容に変換して返す。
|
||
* @param {String} value 変換元の文字列( v[n]形式を含む )
|
||
* @return {String} 変換後の文字列
|
||
*/
|
||
function treatValue( value ) {
|
||
if( value === undefined || value === '' ) return '0';
|
||
const result = value.match( /v\[(.+)\]/i );
|
||
if( result === null ) return value;
|
||
const id = parseInt( result[ 1 ], 10 );
|
||
if( isNaN( id ) ) {
|
||
return $gameVariables.valueByName( id );
|
||
} else {
|
||
return $gameVariables.value( id );
|
||
}
|
||
}
|
||
/*--- Game_Variables ---*/
|
||
/**
|
||
* 変数を文字列で指定し、値を返す。
|
||
* @param {String} name 変数(ID, 名前, V[n]による指定が可能)
|
||
*/
|
||
Game_Variables.prototype.valueByName = function( name ) {
|
||
return this.value( stringToVariableId( name ) );
|
||
};
|
||
/**
|
||
* 指定された変数のIDを返す。
|
||
* @param {String} name 変数(ID, 名前, V[n]による指定が可能)
|
||
*/
|
||
function stringToVariableId( name ) {
|
||
name = treatValue( name );
|
||
let i = $dataSystem.variables.findIndex( i => i === name );
|
||
if( 0 <= i ) return i;
|
||
i = parseInt( name, 10 );
|
||
if( isNaN( i ) ) throw new Error( `I can't find the variable '${name}'` );
|
||
return i;
|
||
}
|
||
|
||
/**
|
||
* 文字列を整数に変換して返す。
|
||
* @param {String|Number} value
|
||
* @return {Number} 数値に変換した結果
|
||
*/
|
||
function parseIntStrict( value ) {
|
||
if( typeof value === TYPE_NUMBER ) return Math.floor( value );
|
||
const result = parseInt( treatValue( value ), 10 );
|
||
if( isNaN( result ) ) throw Error( '指定した値[' + value + ']が数値ではありません。' );
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 文字列を実数に変換して返す。
|
||
* @param {String|Number} value
|
||
* @return {Number} 数値に変換した結果
|
||
*/
|
||
function parseFloatStrict( value ) {
|
||
if( typeof value === 'number' ) return value;
|
||
const result = parseFloat( treatValue( value ) );
|
||
if( isNaN( result ) ) throw Error( '指定した値[' + value + ']が数値ではありません。' );
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 文字列を真偽値に変換して返す。
|
||
* @param {String|Boolean} value 変換元文字列
|
||
* @returns {Boolean}
|
||
*/
|
||
function parseBooleanStrict( value ) {
|
||
if( typeof value === TYPE_BOOLEAN ) return value;
|
||
value = treatValue( value );
|
||
const result = value.toLowerCase();
|
||
return ( result === PARAM_TRUE || result === PARAM_ON );
|
||
}
|
||
|
||
/**
|
||
* character を拡張して隊列メンバーも指定できるようにしたもの。
|
||
* @param {Game_Interpreter} interpreter インタプリタ
|
||
* @param {Number} id 拡張イベントID
|
||
* @returns {Game_CharacterBase}
|
||
*/
|
||
function getEventById( interpreter, id ) {
|
||
if( id < -1 ) {
|
||
return $gamePlayer.followers().follower( -2 - id ); // 隊列メンバー(0〜2)
|
||
} else {
|
||
return interpreter.character( id ); // プレイヤーキャラおよびイベント
|
||
}
|
||
}
|
||
|
||
const EVENT_THIS = 'this';
|
||
const EVENT_SELF = 'self';
|
||
const EVENT_PLAYER = 'player';
|
||
const EVENT_FOLLOWER0 = 'follower0';
|
||
const EVENT_FOLLOWER1 = 'follower1';
|
||
const EVENT_FOLLOWER2 = 'follower2';
|
||
/**
|
||
* 文字列をイベントIDへ変換
|
||
* @param {String} value イベントIDの番号か識別子
|
||
* @returns {Number} 拡張イベントID
|
||
*/
|
||
function stringToEventId( value ) {
|
||
value = treatValue( value );
|
||
const result = parseInt( value, 10 );
|
||
if( !isNaN( result ) ) return result;
|
||
|
||
const lowValue = value.toLowerCase();
|
||
switch( lowValue ) {
|
||
case EVENT_THIS:
|
||
case EVENT_SELF: return 0;
|
||
case EVENT_PLAYER: return -1;
|
||
case EVENT_FOLLOWER0: return -2;
|
||
case EVENT_FOLLOWER1: return -3;
|
||
case EVENT_FOLLOWER2: return -4;
|
||
}
|
||
|
||
// イベント名で指定できるようにする
|
||
const i = $gameMap._events.findIndex( event => {
|
||
if( event === undefined ) return false; // _events[0] が undefined なので無視
|
||
|
||
const eventId = event._eventId;
|
||
return $dataMap.events[ eventId ].name === value;
|
||
} );
|
||
if( i === -1 ) throw Error( `指定したイベント[${value}]がありません。` );
|
||
return i;
|
||
}
|
||
|
||
/**
|
||
* パラメータを受け取る
|
||
*/
|
||
const pluginParams = PluginManager.parameters( 'TF_LayeredMap' );
|
||
const TF_FillWithNeighborTile = parseBooleanStrict( pluginParams.FillWithNeighborTile );
|
||
const TF_DefaultLowerTileId = Tilemap.TILE_ID_A5 + parseIntStrict( pluginParams.DefaultLowerTile );
|
||
const TF_UseLayeredCounter = parseBooleanStrict( pluginParams.UseLayeredCounter );
|
||
const TF_BillboardPriority = conpairPluginParam( 'BillboardPriority', 'front', false ) ? Infinity : -Infinity;
|
||
const TF_IsA2FullCollision = parseBooleanStrict( pluginParams.IsA2FullCollision );
|
||
const TF_IsA3UpperOpen = parseBooleanStrict( pluginParams.IsA3UpperOpen );
|
||
const TF_IsA4UpperOpen = parseBooleanStrict( pluginParams.IsA4UpperOpen );
|
||
const TF_OverpassTerrainTag = parseIntStrict( pluginParams.OverpassTerrainTag );
|
||
const TF_CharacterSize = parseIntStrict( pluginParams.CharacterSize );
|
||
|
||
/*---- SceneManager ----*/
|
||
// URLでの指定がない限り、WebGL モードを採用する。
|
||
const MODE_CANVAS = 'canvas';
|
||
const MODE_WEBGL = 'webgl';
|
||
SceneManager.preferableRendererType = function() {
|
||
return ( Utils.isOptionValid( MODE_CANVAS ) ) ? MODE_CANVAS : MODE_WEBGL;
|
||
};
|
||
|
||
/*---- Game_Interpreter ----*/
|
||
/**
|
||
* プラグインコマンドの実行
|
||
*/
|
||
const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
|
||
Game_Interpreter.prototype.pluginCommand = function( command, args ) {
|
||
_Game_Interpreter_pluginCommand.apply( this, arguments );
|
||
|
||
// _higherLevel のON/OFF
|
||
if( command.toUpperCase() !== TF_HIGHER_LEVEL ) return;
|
||
|
||
const targetCharacter = getEventById( this, stringToEventId( args[ 1 ] ) );
|
||
targetCharacter._higherLevel = parseBooleanStrict( args[ 0 ] );
|
||
};
|
||
|
||
|
||
/*---- Tilemap ----*/
|
||
/**
|
||
* その位置が立体交差であるかチェック(地形タグで決定)
|
||
*/
|
||
const _Tilemap_isOverpassPosition = Tilemap.prototype._isOverpassPosition;
|
||
Tilemap.prototype._isOverpassPosition = function( x, y ) {
|
||
if( TF_OverpassTerrainTag !== 0 && $gameMap.terrainTag( x, y ) === TF_OverpassTerrainTag ) return true;
|
||
return _Tilemap_isOverpassPosition.apply( this, arguments );
|
||
};
|
||
|
||
/**
|
||
* イベントの重なりのソート用関数。
|
||
*/
|
||
Tilemap.prototype._compareChildOrder = function( a, b ) {
|
||
if( a.z !== b.z ) return a.z - b.z;
|
||
const zDefA = a._character ? a._character._TF_zDef : 0;
|
||
const zDefB = b._character ? b._character._TF_zDef : 0;
|
||
const ay = a.y + ( zDefA ? zDefA : 0 );
|
||
const by = b.y + ( zDefB ? zDefB : 0 );
|
||
if( ay !== by ) {
|
||
return ay - by;
|
||
}
|
||
return a.spriteId - b.spriteId;
|
||
};
|
||
|
||
/*---- ShaderTilemap ----*/
|
||
/**
|
||
* タイルセットの画像を設定する。
|
||
* マップ開始時に呼ばれる。
|
||
*/
|
||
const _ShaderTilemap_refreshTileset = ShaderTilemap.prototype.refreshTileset;
|
||
ShaderTilemap.prototype.refreshTileset = function() {
|
||
_ShaderTilemap_refreshTileset.call( this );
|
||
|
||
// BitmapをPIXI.Textureにコンバート
|
||
const bitmaps = this.bitmaps.map( function( x ) {
|
||
return x._baseTexture ? new PIXI.Texture( x._baseTexture ) : x;
|
||
} );
|
||
|
||
// 書き割りのタイルセットの画像をアップデート
|
||
for( let curItem of this.TF_billboards ) {
|
||
curItem.children[ 0 ].setBitmaps( bitmaps );
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 書き割りレイヤーの生成と追加。
|
||
*/
|
||
const _ShaderTilemap_createLayers = ShaderTilemap.prototype._createLayers;
|
||
ShaderTilemap.prototype._createLayers = function() {
|
||
_ShaderTilemap_createLayers.call( this );
|
||
|
||
// 書き割り風オブジェクトを生成
|
||
// +3 はスクロールの際にはみ出す部分と2・3階用
|
||
const th = this._tileHeight;
|
||
const tileRows = Math.ceil( this._height / th ) + 3;
|
||
|
||
if( !this.hasOwnProperty( 'TF_billboards' ) ) {
|
||
this.TF_billboards = [];
|
||
}
|
||
|
||
for( let i = 0; i < tileRows; i++ ) {
|
||
const billboard = new PIXI.tilemap.ZLayer( this, 3 );
|
||
billboard.spriteId = TF_BillboardPriority;
|
||
this.addChild( billboard );
|
||
this.TF_billboards.push( billboard );
|
||
const layer = new PIXI.tilemap.CompositeRectTileLayer( 0, [], 0 );
|
||
billboard.addChild( layer );
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 描画前に書き割りの中を空にしておく。
|
||
*/
|
||
const _ShaderTilemap_paintAllTiles = ShaderTilemap.prototype._paintAllTiles;
|
||
ShaderTilemap.prototype._paintAllTiles = function( startX, startY ) {
|
||
for( let curItem of this.TF_billboards ) {
|
||
curItem.clear();
|
||
}
|
||
|
||
_ShaderTilemap_paintAllTiles.apply( this, arguments );
|
||
};
|
||
|
||
/**
|
||
* タイルマップと書き割りの描画。
|
||
* 関数をまるっと書き換えているので
|
||
* 他のプラグインとコンフリクトを起こしてしまうので注意。
|
||
* @param {Number} startX 開始 マップ x座標(タイル数)
|
||
* @param {Number} startY 開始 マップ y座標(タイル数)
|
||
* @param {Number} x 画面上の x座標(タイル数)
|
||
* @param {Number} y 画面上の y座標(タイル数)
|
||
*/
|
||
ShaderTilemap.prototype._paintTiles = function( startX, startY, x, y ) {
|
||
const mx = startX + x; // 描画対象のマップ x座標(タイル数)
|
||
const my = startY + y; // 描画対象のマップ y座標(タイル数)
|
||
const dx = x * this._tileWidth; // 描画位置の x座標(ピクセル)
|
||
const dy = y * this._tileHeight; // 描画位置の y座標(ピクセル)
|
||
const tileId0 = this._readMapData( mx, my, 0 ); // 低層タイルA
|
||
const tileId1 = this._readMapData( mx, my, 1 ); // 低層タイルA2右側など
|
||
const tileId2 = this._readMapData( mx, my, 2 ); // B 〜 E タイル
|
||
const tileId3 = this._readMapData( mx, my, 3 ); // B 〜 E タイル
|
||
const shadowBits = this._readMapData( mx, my, 4 ); // 影ペン
|
||
const northTileId1 = this._readMapData( mx, my - 1, 1 ); // 北位置の低層タイルA
|
||
const lowerLayer = this.lowerLayer.children[ 0 ]; // 低層レイヤ( z: 0 )
|
||
const upperLayer = this.upperLayer.children[ 0 ]; // 高層レイヤ( z: 4 )
|
||
|
||
/**
|
||
* タイルを描画(upperLayer,lowerLayer,dx,dy は親の変数を使う)
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
const drawTile = ( tileId ) => {
|
||
if( !this._isHigherTile( tileId )
|
||
|| ( this.flags[ tileId ] & MASK_UPPER_DIR ) === FLOOR1_N_FULL
|
||
|| ( this.flags[ tileId ] & MASK_UPPER_DIR ) === FLOOR1_N_HALF
|
||
) {
|
||
// 高層タイルではない
|
||
this._drawTile( lowerLayer, tileId, dx, dy );
|
||
return;
|
||
}
|
||
|
||
// 優先階(priorityFloor)を設定
|
||
let priorityFloor;
|
||
if( ( this.flags[ tileId ] & MASK_UPPER_DIR ) === FLOOR2_BOARD ) {
|
||
priorityFloor = 2;
|
||
} else if( ( this.flags[ tileId ] & MASK_UPPER_DIR ) === FLOOR3_BOARD ) {
|
||
priorityFloor = 3;
|
||
} else {
|
||
priorityFloor = 1;
|
||
}
|
||
|
||
let floorNumber = 1;
|
||
if( priorityFloor === 2 || priorityFloor === 3 ) {
|
||
const wallSideType = getWallSideType( this._readMapData( mx, my + 1, 1 ) );
|
||
|
||
if( wallSideType === 1 ) {
|
||
floorNumber = 2;
|
||
} else if( wallSideType === 2 ) {
|
||
floorNumber = 3;
|
||
} else if( wallSideType === 3 ) {
|
||
floorNumber = priorityFloor;
|
||
} else {
|
||
// 壁ではない場合
|
||
floorNumber = priorityFloor;
|
||
// TODO : B〜E タイルのオート位置設定を行う…か?
|
||
}
|
||
}
|
||
|
||
if( floorNumber === 2 ) {
|
||
// 2階設定は、ひとつ下の書き割りに書き込む
|
||
this._drawTile( this.TF_billboards[ y + 1 ].children[ 0 ].children[ 0 ], tileId, dx, -this._tileHeight * 2 );
|
||
|
||
} else if( floorNumber === 3 ) {
|
||
// 3階設定は、ふたつ下の書き割りに書き込む
|
||
this._drawTile( this.TF_billboards[ y + 2 ].children[ 0 ].children[ 0 ], tileId, dx, -this._tileHeight * 3 );
|
||
|
||
} else if( this.flags[ tileId ] & MASK_ALL_DIR ) {
|
||
// 通行不可設定のどれかがONだと書き割り
|
||
this._drawTile( this.TF_billboards[ y ].children[ 0 ].children[ 0 ], tileId, dx, -this._tileHeight );
|
||
|
||
} else {
|
||
// 全方向通行可の場合は通常の高層[☆]表示
|
||
this._drawTile( upperLayer, tileId, dx, dy );
|
||
}
|
||
};
|
||
|
||
drawTile( tileId0 );
|
||
drawTile( tileId1 );
|
||
|
||
// 影の描画
|
||
this._drawShadow( lowerLayer, shadowBits, dx, dy );
|
||
|
||
// テーブルの描画
|
||
if( this._isTableTile( northTileId1 ) && !this._isTableTile( tileId1 ) ) {
|
||
if( !Tilemap.isShadowingTile( tileId0 ) && !Tilemap.isShadowingTile( tileId1 ) ) {
|
||
this._drawTableEdge( lowerLayer, northTileId1, dx, dy );
|
||
}
|
||
}
|
||
|
||
// 立体交差の描画
|
||
if( this._isOverpassPosition( mx, my ) ) {
|
||
this._drawTile( upperLayer, tileId2, dx, dy );
|
||
this._drawTile( upperLayer, tileId3, dx, dy );
|
||
} else {
|
||
drawTile( tileId2 );
|
||
drawTile( tileId3 );
|
||
}
|
||
|
||
/**
|
||
* 指定位置の壁の状態を調べる。
|
||
* @param {Number} tileId タイルID
|
||
* @returns {Number} 0:壁ではない, 1:下端, 2:上下に接続した壁, 3:上端
|
||
*/
|
||
function getWallSideType( tileId ) {
|
||
if( !Tilemap.isWallSideTile( tileId ) ) return 0; // 壁タイルではない
|
||
|
||
// autotileShape のビットは 下右上左 に対応しているので、それで判定
|
||
const autotileShape = Tilemap.getAutotileShape( tileId );
|
||
if( autotileShape & 2 ) return 3;
|
||
if( autotileShape & 8 ) return 1;
|
||
return 2;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* (スクロールに合わせて)書き割りの表示位置を変更。
|
||
* @param {Number} startX
|
||
* @param {Number} startY
|
||
*/
|
||
const _ShaderTilemap_updateLayerPositions = ShaderTilemap.prototype._updateLayerPositions;
|
||
ShaderTilemap.prototype._updateLayerPositions = function( startX, startY ) {
|
||
_ShaderTilemap_updateLayerPositions.apply( this, arguments );
|
||
|
||
let ox, oy;
|
||
if( this.roundPixels ) {
|
||
ox = Math.floor( this.origin.x );
|
||
oy = Math.floor( this.origin.y );
|
||
} else {
|
||
ox = this.origin.x;
|
||
oy = this.origin.y;
|
||
}
|
||
const th = this._tileHeight;
|
||
const tw = this._tileWidth;
|
||
const posX = startX * tw - ox;
|
||
const posY = startY * th - oy;
|
||
const l = this.TF_billboards.length;
|
||
for( let i = 0; i < l; i++ ) {
|
||
const curItem = this.TF_billboards[ i ];
|
||
curItem.position.x = posX;
|
||
curItem.position.y = posY + ( i + 1 ) * th;
|
||
};
|
||
};
|
||
|
||
/*---- DataManager ---*/
|
||
/**
|
||
* 読み込み直後に、タイルセットデータを書き換える。
|
||
* @param {Object} object 読み込んだデータ
|
||
*/
|
||
const _DataManager_onLoad = DataManager.onLoad;
|
||
DataManager.onLoad = function( object ) {
|
||
_DataManager_onLoad.apply( this, arguments );
|
||
if( object !== $dataTilesets ) return;
|
||
|
||
// 全タイルセットに対してflagの走査・変更
|
||
for( const curTileset of $dataTilesets ) {
|
||
if( !curTileset ) continue;
|
||
treatA2Tilesets( curTileset.flags );
|
||
treatA3Tilesets( curTileset.flags );
|
||
treatA4Tilesets( curTileset.flags );
|
||
}
|
||
};
|
||
/* ---- DataManager.onLoad 用ユーティリティ ---- */
|
||
// $gameMap が無い段階なので、必要な関数を代わりに定義したり、flags をまる渡ししたりしてる
|
||
|
||
const OPTT = ( TF_OverpassTerrainTag << 12 ); // 立体交差地形タグ
|
||
|
||
/**
|
||
* カウンター設定か。
|
||
* @param {Number} tileFlag タイルのフラグ情報
|
||
*/
|
||
function isCounterTile( tileFlag ) {
|
||
return ( tileFlag & FLAG_COUNTER ) === FLAG_COUNTER;
|
||
}
|
||
/**
|
||
* 指定タイルが立体交差地形タグを持っているか。
|
||
* @param {Number} tileFlag タイルのフラグ情報
|
||
*/
|
||
function isOverpassTile( tileFlag ) {
|
||
if( TF_OverpassTerrainTag === 0 ) return false;
|
||
return tileFlag >> 12 === TF_OverpassTerrainTag;
|
||
}
|
||
|
||
/**
|
||
* 指定タイルが全方位に衝突判定を持っているか。
|
||
* @param {Number} tileFlag タイルのフラグ情報
|
||
*/
|
||
function isFullCollisionTile( tileFlag ) {
|
||
return MASK_ALL_DIR === ( tileFlag & MASK_ALL_DIR );
|
||
}
|
||
/**
|
||
* 指定タイルが衝突判定を持っているか。
|
||
* @param {Number} tileFlag タイルのフラグ情報
|
||
*/
|
||
function isCollisionTile( tileFlag ) {
|
||
return 0 < ( tileFlag & MASK_ALL_DIR );
|
||
}
|
||
|
||
// A2タイルの走査・変更。
|
||
function treatA2Tilesets( flags ) {
|
||
for( let tileId = Tilemap.TILE_ID_A2; tileId < Tilemap.TILE_ID_A3; tileId += AUTOTILE_BLOCK ) {
|
||
const autotileFlags =
|
||
( isCounterTile( flags[ tileId ] ) ? 2 : 0 ) +
|
||
( isCollisionTile( flags[ tileId + 46 ] ) ? 1 : 0 );
|
||
switch( autotileFlags ) {
|
||
case 1: if( !TF_IsA2FullCollision ) { setEmptyLinePass( flags, tileId ); }; break; // [×]
|
||
case 3: if( TF_UseLayeredCounter ) { setCounterPass( flags, tileId ); }; break; // [×][♢]
|
||
}
|
||
}
|
||
}
|
||
|
||
// A3タイルの走査・変更。
|
||
function treatA3Tilesets( flags ) {
|
||
for( let tileId = Tilemap.TILE_ID_A3; tileId < Tilemap.TILE_ID_A4; tileId += AUTOTILE_BLOCK ) {
|
||
const autotileFlags =
|
||
( Tilemap.isRoofTile( tileId ) ? 8 : 0 ) +
|
||
( isOverpassTile( flags[ tileId ] ) ? 4 : 0 ) +
|
||
( isCounterTile( flags[ tileId ] ) ? 2 : 0 ) +
|
||
( isCollisionTile( flags[ tileId + 15 ] ) ? 1 : 0 );
|
||
switch( autotileFlags ) {
|
||
// 側面
|
||
case 2: setWallSidePass( flags, tileId ); break; // [○][♢]
|
||
case 3: setWallSideEdgePass( flags, tileId ); break; // [×][♢]
|
||
case 4: setBridgeSNPass( flags, tileId, false ); break; // [○][TT]
|
||
case 5: setBridgeSNPass( flags, tileId, true ); break; // [×][TT]
|
||
// case 6 : ; break; // [○][♢][TT]
|
||
// case 7 : ; break; // [×][♢][TT]
|
||
|
||
// 上面
|
||
case 9: setRoofBottomPass( flags, tileId ); break; // [×]
|
||
case 10: setAutoUpperPass( flags, tileId, 16 ); break; // [○][♢]
|
||
case 11: setRoofUpperPass( flags, tileId ); break; // [×][♢]
|
||
case 12: setBridgeWEPass( flags, tileId, false ); break; // [○][TT]
|
||
case 13: setBridgeWEPass( flags, tileId, true ); break; // [×][TT]
|
||
case 14: setEmptySquarePass( flags, tileId ); break; // [○][♢][TT]
|
||
case 15: setA3UpperOverPass( flags, tileId ); break; // [×][♢][TT]
|
||
}
|
||
}
|
||
}
|
||
|
||
// A4タイルの走査・変更。
|
||
function treatA4Tilesets( flags ) {
|
||
for( let tileId = Tilemap.TILE_ID_A4; tileId < Tilemap.TILE_ID_MAX; tileId += AUTOTILE_BLOCK ) {
|
||
const autotileFlags =
|
||
( Tilemap.isWallTopTile( tileId ) ? 8 : 0 ) +
|
||
( isOverpassTile( flags[ tileId ] ) ? 4 : 0 ) +
|
||
( isCounterTile( flags[ tileId ] ) ? 2 : 0 ) +
|
||
( isCollisionTile( flags[ tileId + 46 ] ) ? 1 : 0 );
|
||
switch( autotileFlags ) {
|
||
// 側面
|
||
case 2: setWallSidePass( flags, tileId ); break; // [○][♢]
|
||
case 3: setWallSideEdgePass( flags, tileId ); break; // [×][♢]
|
||
case 4: setBridgeSNPass( flags, tileId, false ); break; // [○][TT]
|
||
case 5: setBridgeSNPass( flags, tileId, true ); break; // [×][TT]
|
||
// case 6 : ; break; // [○][♢][TT]
|
||
// case 7 : ; break; // [×][♢][TT]
|
||
|
||
// 上面
|
||
case 9: if( !TF_IsA4UpperOpen ) { setEmptyLinePass( flags, tileId ); } break; // [×]
|
||
case 10: setAutoUpperPass( flags, tileId, 47 ); break; // [○][♢]
|
||
case 11: setA4UpperPass( flags, tileId ); break; // [×][♢]
|
||
// case 12 : ; break; // [○][TT]
|
||
case 13: setA4UpperStarPass( flags, tileId ); break; // [×][TT]
|
||
case 14: setEmptyLinePass( flags, tileId ); break; // [○][♢][TT]
|
||
case 15: setA4UpperOverPass( flags, tileId ); break; // [×][♢][TT]
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 衝突判定を指定した設定に変換。
|
||
* @param {Array} flags
|
||
* @param {Number} tileId
|
||
* @param {Number} mask flagのマスク
|
||
* @param {Array} collisionSetting 適用するflag設定
|
||
*/
|
||
function replaceCollision( flags, tileId, mask, collisionSetting ) {
|
||
const maxNum = collisionSetting.length;
|
||
for( let i = 0; i < maxNum; i++ ) {
|
||
flags[ tileId + i ] = flags[ tileId + i ] & mask | collisionSetting[ i ];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 高層[☆] 全通行に変更。
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
* @param {Number} maxNum 変更数
|
||
*/
|
||
function setAutoUpperPass( flags, tileId, maxNum ) {
|
||
for( let i = 0; i < maxNum; i++ ) {
|
||
flags[ tileId + i ] = flags[ tileId + i ] & MASK_WITHOUT_DIR_UPPER | FLAG_UPPER;
|
||
}
|
||
}
|
||
/**
|
||
* カウンター用に変更。
|
||
* 地面(カウンター) : 北が半分侵入可書き割り、■通行不可
|
||
* [A2 右側][×][♢][UseLayeredCounter:ON]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setCounterPass( flags, tileId ) {
|
||
const COUNTER_PASS = [
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 15, 15, 15, 28, 28, 28, 28,
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 28, 28, 28, 28, 28, 15, 15,
|
||
15, 15, 28, 28, 15, 28, 28, 28,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER | FLAG_COUNTER, COUNTER_PASS );
|
||
}
|
||
/**
|
||
* 中空の地形に変更。
|
||
* [A2][×][IsA2FullCollision:OFF] □周囲=通行不可
|
||
* [A4][○][♢][TT] □周囲=通行不可
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setEmptyLinePass( flags, tileId ) {
|
||
const EMPTY_PASS = [
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
2, 2, 2, 2, 8, 8, 8, 8,
|
||
4, 4, 4, 4, 1, 1, 1, 1,
|
||
6, 9, 10, 10, 12, 12, 5, 5,
|
||
3, 3, 14, 11, 7, 13, 15, 15
|
||
];
|
||
//if( isCrossPass ) EMPTY_PASS.map( v => OPTT + v );
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, EMPTY_PASS );
|
||
};
|
||
/**
|
||
* 屋根 : 北が立体交差、他は周囲通行不可に変更。
|
||
* [A3 奇数列][×][♢][TT]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setA3UpperOverPass( flags, tileId ) {
|
||
const A3_UPPER_OVERPASS = TF_IsA3UpperOpen ? [
|
||
0, 2, OPTT + 8, OPTT + 10,
|
||
4, 6, OPTT + 12, OPTT + 14,
|
||
0, 2, OPTT + 8, OPTT + 10,
|
||
4, 6, OPTT + 12, OPTT + 14,
|
||
] : [
|
||
0, 2, OPTT + 8, OPTT + 10,
|
||
4, 6, OPTT + 12, OPTT + 14,
|
||
1, 3, OPTT + 9, OPTT + 11,
|
||
5, 7, OPTT + 15, OPTT + 13,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_TAG_DIR_UPPER, A3_UPPER_OVERPASS );
|
||
}
|
||
/**
|
||
* 屋根 : 北が書き割り、他は周囲通行不可に変更。
|
||
* [A3 奇数列][×][カウンター]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setRoofUpperPass( flags, tileId ) {
|
||
const A3_UPPER_PASS = TF_IsA3UpperOpen ? [
|
||
0, 2, 17, 17,
|
||
4, 6, 17, 17,
|
||
0, 2, 17, 17,
|
||
4, 6, 17, 17,
|
||
] : [
|
||
0, 2, 17, 17,
|
||
4, 6, 17, 17,
|
||
1, 3, 17, 17,
|
||
5, 7, 17, 17,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, A3_UPPER_PASS );
|
||
}
|
||
/**
|
||
* 壁(上面) : 北が立体交差、他は周囲通行不可に変更。
|
||
* [A4 奇数列][×][カウンター][OverpassTerrainTag]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setA4UpperOverPass( flags, tileId ) {
|
||
const A4_UPPER_OVERPASS = TF_IsA4UpperOpen ? [
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
2, 2, 2, 2, OPTT + 8, OPTT + 8, OPTT + 8, OPTT + 8,
|
||
4, 4, 4, 4, 0, 0, 0, 0,
|
||
6, OPTT + 8, OPTT + 10, OPTT + 10, OPTT + 12, OPTT + 12, 4, 4,
|
||
2, 2, OPTT + 14, OPTT + 10, 6, OPTT + 12, OPTT + 14, OPTT + 15,
|
||
] : [
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0,
|
||
2, 2, 2, 2, OPTT + 8, OPTT + 8, OPTT + 8, OPTT + 8,
|
||
4, 4, 4, 4, 1, 1, 1, 1,
|
||
6, OPTT + 9, OPTT + 10, OPTT + 10, OPTT + 12, OPTT + 12, 5, 5,
|
||
3, 3, OPTT + 14, OPTT + 11, 7, OPTT + 13, OPTT + 15, OPTT + 15,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_TAG_DIR_UPPER, A4_UPPER_OVERPASS );
|
||
}
|
||
/**
|
||
* 壁(上面) : 北が書き割り、他は周囲通行不可に変更。
|
||
* [A4 奇数列][×][カウンター]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setA4UpperPass( flags, tileId ) {
|
||
const A4_UPPER_PASS = TF_IsA4UpperOpen ? [
|
||
0, 2, 4, 6, 0, 2, 4, 6,
|
||
0, 2, 4, 6, 0, 2, 4, 6,
|
||
2, 6, 2, 6, 17, 17, 17, 17,
|
||
4, 4, 6, 6, 0, 2, 4, 6,
|
||
6, 17, 17, 17, 17, 17, 4, 6,
|
||
2, 6, 17, 17, 6, 17, 17, 17,
|
||
] : [
|
||
0, 2, 4, 6, 0, 2, 4, 6,
|
||
0, 2, 4, 6, 0, 2, 4, 6,
|
||
2, 6, 2, 6, 17, 17, 17, 17,
|
||
4, 4, 6, 6, 1, 3, 5, 7,
|
||
6, 17, 17, 17, 17, 17, 5, 7,
|
||
3, 7, 17, 17, 7, 17, 17, 17,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, A4_UPPER_PASS );
|
||
}
|
||
/**
|
||
* 壁(上面) : 北が☆、他は通行不可に変更。
|
||
* [A4 奇数列][○][TT]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setA4UpperStarPass( flags, tileId ) {
|
||
const A4_UPPER_STAR_PASS = [
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 15, 15, 15, 16, 16, 16, 16,
|
||
15, 15, 15, 15, 15, 15, 15, 15,
|
||
15, 16, 16, 16, 16, 16, 15, 15,
|
||
15, 15, 16, 16, 15, 16, 16, 16,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_TAG_DIR_UPPER, A4_UPPER_STAR_PASS );
|
||
}
|
||
/**
|
||
* 壁(側面):南が書き割り、他は通行可に変更。
|
||
* [A3・A4 偶数列][○]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setWallSideEdgePass( flags, tileId ) {
|
||
const WALL_SIDE_PASS_EDGE = [
|
||
15, 15, 17, 17,
|
||
15, 15, 17, 17,
|
||
15, 15, 17, 17,
|
||
15, 15, 17, 17,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, WALL_SIDE_PASS_EDGE );
|
||
}
|
||
/**
|
||
* 壁(側面): 北が書き割り、他は全通行不可に変更。
|
||
* [A3・A4 偶数列][○][♢]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setWallSidePass( flags, tileId ) {
|
||
const WALL_SIDE_PASS = [
|
||
25, 25, 26, 26,
|
||
25, 25, 26, 26,
|
||
17, 17, 17, 17,
|
||
17, 17, 17, 17,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, WALL_SIDE_PASS );
|
||
}
|
||
/**
|
||
* 屋根 (地面) : 周囲通行不可に変更。
|
||
* [A3 奇数列][×]
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setRoofBottomPass( flags, tileId ) {
|
||
if( TF_IsA3UpperOpen ) {
|
||
setSquareOpenPass( flags, tileId );
|
||
} else {
|
||
setEmptySquarePass( flags, tileId );
|
||
}
|
||
}
|
||
/**
|
||
* 屋根 (地面) : 南以外通行不可に変更。
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setSquareOpenPass( flags, tileId ) {
|
||
const SQUARE_PASS = [
|
||
0, 2, 8, 10,
|
||
4, 6, 12, 14,
|
||
0, 2, 8, 10,
|
||
4, 6, 12, 14,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, SQUARE_PASS );
|
||
}
|
||
/**
|
||
* 屋根 (地面) : 全周通行不可に変更。
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setEmptySquarePass( flags, tileId ) {
|
||
const SQUARE_PASS = [
|
||
0, 2, 8, 10,
|
||
4, 6, 12, 14,
|
||
1, 3, 9, 11,
|
||
5, 7, 13, 15,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_DIR_UPPER, SQUARE_PASS );
|
||
}
|
||
/**
|
||
* 南北の橋設定に変更。
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
* @param {Boolean} isCrossPass 立体交差か
|
||
*/
|
||
function setBridgeSNPass( flags, tileId, isCrossPass ) {
|
||
const BRIDGE_SN_PASS = isCrossPass ? [
|
||
OPTT + 0, OPTT + 2, OPTT + 0, OPTT + 2,
|
||
OPTT + 4, OPTT + 6, OPTT + 4, OPTT + 6,
|
||
OPTT + 0, OPTT + 2, OPTT + 0, OPTT + 2,
|
||
OPTT + 4, OPTT + 6, OPTT + 4, OPTT + 6,
|
||
] : [
|
||
0, 2, 0, 2,
|
||
4, 6, 4, 6,
|
||
0, 2, 0, 2,
|
||
4, 6, 4, 6,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_TAG_DIR_UPPER, BRIDGE_SN_PASS );
|
||
}
|
||
/**
|
||
* 東西の橋設定に変更。
|
||
* @param {Array<Number>} flags 地形フラグの配列
|
||
* @param {Number} tileId タイルID
|
||
* @param {Boolean} isCrossPass 立体交差か
|
||
*/
|
||
function setBridgeWEPass( flags, tileId, isCrossPass ) {
|
||
const BRIDGE_WE_PASS = isCrossPass ? [
|
||
OPTT + 0, OPTT + 0, OPTT + 8, OPTT + 8,
|
||
OPTT + 0, OPTT + 0, OPTT + 8, OPTT + 8,
|
||
OPTT + 1, OPTT + 1, OPTT + 9, OPTT + 9,
|
||
OPTT + 1, OPTT + 1, OPTT + 9, OPTT + 9,
|
||
] : [
|
||
0, 0, 8, 8,
|
||
0, 0, 8, 8,
|
||
1, 1, 9, 9,
|
||
1, 1, 9, 9,
|
||
];
|
||
replaceCollision( flags, tileId, MASK_WITHOUT_TAG_DIR_UPPER, BRIDGE_WE_PASS );
|
||
}
|
||
|
||
|
||
|
||
/*---- Scene_Map ---*/
|
||
/**
|
||
* シーン表示前に、マップデータを書き換える。
|
||
*/
|
||
const _Scene_Map_onMapLoaded = Scene_Map.prototype.onMapLoaded;
|
||
Scene_Map.prototype.onMapLoaded = function() {
|
||
if( this._transfer ) $gamePlayer.performTransfer(); // シーン遷移時のマップデータ置き換え処理
|
||
treatDataMap();
|
||
_Scene_Map_onMapLoaded.call( this );
|
||
|
||
/**
|
||
* カウンター設定のA3・A4オートタイルの箇所に、低層の補完タイルを設定。
|
||
*/
|
||
function treatDataMap() {
|
||
const flags = $gameMap.tilesetFlags();
|
||
for( let y = 0; y < $dataMap.height; y++ ) {
|
||
for( let x = 0; x < $dataMap.width; x++ ) {
|
||
const tileId = getMapData( x, y, 0 );
|
||
|
||
// 対象タイルを上層へ
|
||
if( Tilemap.isTileA5( tileId ) && isOverpassTile( flags[ tileId ] ) ) {
|
||
setMapData( x, y, 1, tileId );
|
||
} else if( isA3A4Tile( tileId ) ) {
|
||
if( isOverpassTile( flags[ tileId ] ) ) {
|
||
setMapData( x, y, 2, tileId );
|
||
} else if( !isFullCollisionTile( flags[ tileId ] ) && isCollisionTile( flags[ tileId ] ) ) {
|
||
setMapData( x, y, 1, tileId );
|
||
} else continue; // 衝突判定が完全に[○]か[×]のタイルは通常処理(A2右タイルを上に置ける)
|
||
} else continue;
|
||
|
||
|
||
if( TF_FillWithNeighborTile ) {
|
||
// 北タイルで補完ただし、一番南は南で補完
|
||
const southTileId = getMapData( x, $gameMap.roundY( y + 1 ), 0 );
|
||
if( isA3A4Tile( southTileId ) || Tilemap.isTileA5( southTileId ) && isOverpassTile( flags[ southTileId ] ) ) {
|
||
const northTileId = getMapData( x, $gameMap.roundY( y - 1 ), 0 );
|
||
setMapData( x, y, 0, northTileId ? northTileId : TF_DefaultLowerTileId );
|
||
} else {
|
||
setMapData( x, y, 0, southTileId ? southTileId : TF_DefaultLowerTileId );
|
||
}
|
||
} else {
|
||
// 指定タイルで補完
|
||
setMapData( x, y, 0, TF_DefaultLowerTileId );
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* A3・A4タイルか。
|
||
* @param {Number} tileId タイルID
|
||
* @returns {Boolean}
|
||
*/
|
||
function isA3A4Tile( tileId ) {
|
||
return ( Tilemap.isTileA3( tileId ) || Tilemap.isTileA4( tileId ) );
|
||
}
|
||
/**
|
||
* 指定位置のタイルIDを返す。
|
||
* @param {Number} x x座標(タイル数)
|
||
* @param {Number} y y座標(タイル数)
|
||
* @param {*} z レイヤー位置
|
||
* @returns {Number} タイルID
|
||
*/
|
||
function getMapData( x, y, z ) {
|
||
return $dataMap.data[ x + ( $gameMap.roundY( y ) + z * $dataMap.height ) * $dataMap.width ];
|
||
}
|
||
/**
|
||
* マップデータにタイルIDを書き込む。
|
||
* @param {Number} x x座標(タイル数)
|
||
* @param {Number} y y座標(タイル数)
|
||
* @param {Number} z レイヤー位置
|
||
* @param {Number} tileId タイルID
|
||
*/
|
||
function setMapData( x, y, z, tileId ) {
|
||
$dataMap.data[ x + ( $gameMap.roundY( y ) + z * $dataMap.height ) * $dataMap.width ] = tileId;
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
|
||
/*---- Game_CharacterBase ----*/
|
||
/**
|
||
* レイヤー位置を返す。
|
||
* @returns {Number} レイヤー位置(立体交差上5、その他3)
|
||
*/
|
||
const _Game_CharacterBase_screenZ = Game_CharacterBase.prototype.screenZ;
|
||
Game_CharacterBase.prototype.screenZ = function() {
|
||
return this._higherLevel ? 5 : _Game_CharacterBase_screenZ.call( this );
|
||
};
|
||
|
||
/**
|
||
* 指定座標がイベントで塞がれているか。高さレベルを考慮する。
|
||
* TODO : HalfMove.js とコンフリクトするので、回避方法を探る
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @returns {Boolean}
|
||
*/
|
||
//const _Game_CharacterBase_isCollidedWithEvents = Game_CharacterBase.prototype.isCollidedWithEvents;
|
||
// Game_CharacterBase.prototype.isCollidedWithEvents = function( x, y ){
|
||
// const events = $gameMap.eventsXyNt( x, y );
|
||
// return events.some( event => Boolean( this._higherLevel ) === Boolean( event._higherLevel ) );
|
||
// };
|
||
|
||
/**
|
||
* 指定方向への移動が可能か
|
||
* キャラクタ半分の位置が関係するものは、ここで判定。
|
||
* @param {Number} halfX タイル数(0.5刻み)
|
||
* @param {Number} halfY タイル数(0.5刻み)
|
||
* @param {Number} d 向き(テンキー対応)
|
||
* @returns {Boolean} 移動可能か
|
||
*/
|
||
const _Game_CharacterBase_isMapPassable = Game_CharacterBase.prototype.isMapPassable;
|
||
Game_CharacterBase.prototype.isMapPassable = function( halfX, halfY, d ) {
|
||
const x = Math.floor( halfX + 0.5 );
|
||
const y = Math.floor( halfY + 0.5 );
|
||
const halfPos = getHalfPos( halfX, halfY );
|
||
const dx = getDx( d );
|
||
// const dy =getDy( d );
|
||
const rd = this.reverseDir( d );
|
||
const flags = $gameMap.tilesetFlags();
|
||
|
||
/**
|
||
* 指定位置に指定flagがあるか
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @param {Number} collisionType 調べるタイルのflag(高層[☆]と通行)
|
||
* @returns {Boolean}
|
||
*/
|
||
const checkCollision = ( x, y, collisionType ) => {
|
||
const tiles = $gameMap.allTiles( Math.floor( x ), Math.floor( y ) );
|
||
|
||
for( let i = 0; i < tiles.length; i++ ) {
|
||
if( ( flags[ tiles[ i ] ] & MASK_UPPER_DIR ) === collisionType ) return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
const isFurniturePassable = () => {
|
||
// FLOOR1_N_FULL
|
||
if( d === 2 ) {
|
||
if( ( halfPos === 2 || halfPos === 3 ) && checkCollision( x, y + 1, FLOOR1_N_FULL ) ) return false;
|
||
if( halfPos === 2 && checkCollision( x - 1, y + 1, FLOOR1_N_FULL ) ) return false;
|
||
} else if( d === 8 ) {
|
||
if( ( halfPos === 2 || halfPos === 3 ) && checkCollision( x, y, FLOOR1_N_FULL ) ) return false;
|
||
if( ( halfPos === 2 ) && checkCollision( x - 1, y, FLOOR1_N_FULL ) ) return false;
|
||
} else if( d === 4 || d === 6 ) {
|
||
if( halfPos === 1 && checkCollision( x + dx, y, FLOOR1_N_FULL ) ) return false;
|
||
}
|
||
|
||
//FLOOR1_S_FULL
|
||
if( d === 2 ) {
|
||
if( ( halfPos === 0 || halfPos === 1 ) && checkCollision( x, y, FLOOR1_S_FULL ) ) return false;
|
||
if( halfPos === 0 && checkCollision( x - 1, y, FLOOR1_S_FULL ) ) return false;
|
||
} else if( d === 8 ) {
|
||
if( ( halfPos === 0 || halfPos === 1 ) && checkCollision( x, y - 1, FLOOR1_S_FULL ) ) return false;
|
||
if( halfPos === 0 && checkCollision( x - 1, y - 1, FLOOR1_S_FULL ) ) return false;
|
||
} else if( d === 4 || d === 6 ) {
|
||
if( halfPos === 3 && checkCollision( x + dx, y, FLOOR1_S_FULL ) ) return false;
|
||
}
|
||
|
||
// FLOOR1_N_HALF
|
||
if( d === 2 ) {
|
||
if( halfPos === 3 && checkCollision( x, y + 1, FLOOR1_N_HALF ) ) return false;
|
||
} else if( d === 8 ) {
|
||
if( halfPos === 3 && checkCollision( x, y, FLOOR1_N_HALF ) ) return false;
|
||
} else if( d === 4 ) {
|
||
if( halfPos === 0 && checkCollision( x - 1, y, FLOOR1_N_HALF ) ) return false;
|
||
} else if( d === 6 ) {
|
||
if( halfPos === 0 && checkCollision( x, y, FLOOR1_N_HALF ) ) return false;
|
||
}
|
||
|
||
// FLOOR1_S_HALF
|
||
if( d === 2 ) {
|
||
if( halfPos === 1 && checkCollision( x, y, FLOOR1_S_HALF ) ) return false;
|
||
} else if( d === 8 ) {
|
||
if( halfPos === 1 && checkCollision( x, y - 1, FLOOR1_S_HALF ) ) return false;
|
||
} else if( d === 4 ) {
|
||
if( halfPos === 2 && checkCollision( x - 1, y, FLOOR1_S_HALF ) ) return false;
|
||
} else if( d === 6 ) {
|
||
if( halfPos === 2 && checkCollision( x, y, FLOOR1_S_HALF ) ) return false;
|
||
}
|
||
|
||
// FLOOR1_S_FLAT
|
||
if( d === 2 ) {
|
||
if( halfPos === 3 && checkCollision( x, y, FLOOR1_S_FLAT ) ) return false;
|
||
} else if( d === 8 ) {
|
||
if( halfPos === 1 && checkCollision( x, y - 1, FLOOR1_S_FLAT ) ) return false;
|
||
}
|
||
|
||
return null;
|
||
};
|
||
|
||
// Overpass タグが設定されていない
|
||
if( TF_OverpassTerrainTag === 0 ) {
|
||
const isFPassable = isFurniturePassable();
|
||
if( isFPassable !== null ) return isFPassable;
|
||
return _Game_CharacterBase_isMapPassable.apply( this, arguments );
|
||
}
|
||
|
||
|
||
/*---- Overpass 用のプログラム ----*/
|
||
|
||
// 立体交差の下では、家具の衝突判定は行わない
|
||
if( this._higherLevel || ( !this._higherLevel && !isOverpassTileAt( x, y ) ) ) {
|
||
const isFPassable = isFurniturePassable();
|
||
if( isFPassable !== null ) return isFPassable;
|
||
}
|
||
|
||
const isOverpassMapPassable = () => {
|
||
if( isOverpassTileAt( x, y ) ) {
|
||
// 下を潜っている状態は端の通行判定を逆転
|
||
if( d === 2 ) {
|
||
if( ( halfPos === 2 || halfPos === 3 ) &&
|
||
!isOverpassTileAt( x, y + 1 ) && checkOverpassCollision( x, y, 2 ) === false
|
||
) return false;
|
||
} else if( d === 8 ) {
|
||
if( halfPos === 2 || halfPos === 3 ) {
|
||
if( TF_CharacterSize === 2 ) {
|
||
if( !isOverpassTileAt( x, y - 2 ) && checkOverpassCollision( x, y - 1, 8 ) === false ) return false;
|
||
} else if( !isOverpassTileAt( x, y - 1 ) && checkOverpassCollision( x, y, 8 ) === false ) return false;
|
||
}
|
||
} else if( d === 4 || d === 6 ) {
|
||
if( ( halfPos === 1 || halfPos === 3 ) &&
|
||
!isOverpassTileAt( x + dx, y ) && checkOverpassCollision( x, y, d ) === false
|
||
) return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 東の境界
|
||
if( isOverpassTileAt( x - 1, y ) ) {
|
||
if( halfPos === 0 ) return true;
|
||
if( halfPos === 2 ) {
|
||
if( d === 2 ) {
|
||
if( !isOverpassTileAt( x - 1, y + 1 ) && checkOverpassCollision( x - 1, y, 2 ) === false ) return false;
|
||
} else if( d === 8 ) {
|
||
if( TF_CharacterSize === 2 ) {
|
||
if( !isOverpassTileAt( x - 1, y - 2 ) && checkOverpassCollision( x - 1, y - 1, 8 ) === false ) return false;
|
||
} else if( !isOverpassTileAt( x - 1, y - 1 ) && checkOverpassCollision( x - 1, y, 8 ) === false ) return false;
|
||
}
|
||
return true;
|
||
}
|
||
} else if( d === 8 && halfPos === 0 && checkOverpassCollisionBit( x - 1, y - 1, 5 ) ) return true; // 東の角┘
|
||
|
||
// 潜る
|
||
if( d === 2 ) {
|
||
if( halfPos === 2 ) {
|
||
if( checkOverpassCollisionBit( x - 1, y + 1, 12 ) ) return true; // 東の角┐
|
||
if( checkOverpassCollisionBit( x, y + 1, 9 ) ) return true; // 西の角┌
|
||
if( checkOverpassCollision( x, y + 1, 8 ) ) {
|
||
if( checkOverpassCollision( x - 1, y + 1, 8 ) ) return true;
|
||
}
|
||
} else if( halfPos === 3 ) {
|
||
if( checkOverpassCollision( x, y + 1, 8 ) ) return true;
|
||
}
|
||
} else if( d === 8 ) {
|
||
if( halfPos === 0 ) {
|
||
if( checkOverpassCollisionBit( x, y - 1, 3 ) ) return true; // 西の角└
|
||
if( checkOverpassCollision( x, y - 1, 2 ) && checkOverpassCollision( x - 1, y - 1, 2 ) ) return true;
|
||
} else if( halfPos === 1 ) {
|
||
if( checkOverpassCollision( x, y - 1, 2 ) ) return true;
|
||
}
|
||
} else if( d === 4 || d === 6 ) {
|
||
if( checkOverpassCollision( x + dx, y, rd ) ) {
|
||
if( checkOverpassCollision( x + dx, y - 1, rd ) ) {
|
||
if( halfPos === 3 ) return true;
|
||
if( halfPos === 1 && TF_CharacterSize === 1 || checkOverpassCollision( x + dx, y - 2, rd ) ) return true;
|
||
}
|
||
if( ( halfPos === 1 || halfPos === 3 ) && checkOverpassCollision( x + dx, y, 8 ) ) return true; // ┌西東┐の角
|
||
}
|
||
}
|
||
|
||
|
||
// 境界の北の衝突判定
|
||
if( d === 2 ) {
|
||
if( halfPos === 0 && !isOverpassTileAt( x, y ) && !isOverpassTileAt( x - 1, y ) ) {
|
||
if( !isOverpassTileAt( x - 1, y + 1 ) &&
|
||
checkOverpassCollision( x, y + 1, 4 ) === false &&
|
||
checkOverpassCollision( x, y + 1, 2 ) ) return false;
|
||
if( !isOverpassTileAt( x, y + 1 ) &&
|
||
checkOverpassCollision( x - 1, y + 1, 6 ) === false &&
|
||
checkOverpassCollision( x - 1, y + 1, 2 ) ) return false;
|
||
}
|
||
} else if( d === 4 || d === 6 ) {
|
||
if( halfPos === 3 && !isOverpassTileAt( x + dx, y ) ) {
|
||
if( !isOverpassTileAt( x + dx, y + 1 ) &&
|
||
checkOverpassCollision( x, y + 1, d ) === false &&
|
||
checkOverpassCollision( x, y + 1, 8 ) ) return false;
|
||
if( !isOverpassTileAt( x, y + 1 ) &&
|
||
checkOverpassCollision( x + dx, y + 1, rd ) === false &&
|
||
checkOverpassCollision( x + dx, y + 1, 8 ) ) return false;
|
||
}
|
||
}
|
||
|
||
// 境界の南の衝突判定
|
||
if( halfPos === 1 || ( TF_CharacterSize === 2 && halfPos === 3 ) ) {
|
||
if( ( d === 4 || d === 6 ) && !isOverpassTileAt( x + dx, y ) ) {
|
||
if( !isOverpassTileAt( x + dx, y - 1 ) &&
|
||
checkOverpassCollision( x, y - 1, d ) === false &&
|
||
checkOverpassCollision( x, y - 1, 2 ) ) return false;
|
||
if( !isOverpassTileAt( x, y - 1 ) &&
|
||
checkOverpassCollision( x + dx, y - 1, rd ) === false &&
|
||
checkOverpassCollision( x + dx, y - 1, 2 ) ) return false;
|
||
}
|
||
} else if( d === 8 ) {
|
||
if( TF_CharacterSize === 2 ) {
|
||
if( halfPos === 0 && !isOverpassTileAt( x, y - 1 ) && !isOverpassTileAt( x - 1, y - 1 ) ) {
|
||
if( !isOverpassTileAt( x - 1, y - 2 ) &&
|
||
checkOverpassCollision( x, y - 2, 4 ) === false &&
|
||
checkOverpassCollision( x, y - 2, 2 ) ) return false;
|
||
if( !isOverpassTileAt( x, y - 2 ) &&
|
||
checkOverpassCollision( x - 1, y - 2, 6 ) === false &&
|
||
checkOverpassCollision( x - 1, y - 2, 2 ) ) return false;
|
||
}
|
||
} else if( halfPos === 2 && !isOverpassTileAt( x, y ) && !isOverpassTileAt( x - 1, y ) ) {
|
||
if( !isOverpassTileAt( x - 1, y - 1 ) &&
|
||
checkOverpassCollision( x, y - 1, 4 ) === false &&
|
||
checkOverpassCollision( x, y - 1, 2 ) ) return false;
|
||
if( !isOverpassTileAt( x, y - 1 ) &&
|
||
checkOverpassCollision( x - 1, y - 1, 6 ) === false &&
|
||
checkOverpassCollision( x - 1, y - 1, 2 ) ) return false;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
|
||
// 乗る
|
||
const isGateway = isUp2Higher( x, y, d, halfPos );
|
||
if( isGateway ) this._higherLevel = true;
|
||
|
||
if( this._higherLevel ) {
|
||
if( isDownFromUpperTile( x, y, d, halfPos ) ) this._higherLevel = false;
|
||
return _Game_CharacterBase_isMapPassable.apply( this, arguments );
|
||
}
|
||
|
||
const isOPMapPassable = isOverpassMapPassable();
|
||
if( isOPMapPassable === null ) return _Game_CharacterBase_isMapPassable.apply( this, arguments );
|
||
if( isOPMapPassable === false ) return false;
|
||
|
||
const checkUnderpassCollision = ( x, y, d ) => {
|
||
const x2 = $gameMap.roundX( x + getDx( d ) );
|
||
const y2 = $gameMap.roundY( y + getDy( d ) );
|
||
if( isOverpassTileAt( x2, y2 ) ) {
|
||
if( isGateway ) return true;
|
||
if( ( flags[ $gameMap.tileId( x, y, 0 ) ] |
|
||
flags[ $gameMap.tileId( x, y, 1 ) ] ) &
|
||
getFlag( d )
|
||
) return false;
|
||
if( ( flags[ $gameMap.tileId( x2, y2, 0 ) ] |
|
||
flags[ $gameMap.tileId( x2, y2, 1 ) ] ) &
|
||
getFlag( rd )
|
||
) return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
// レイヤー0,1の衝突判定
|
||
if( !this._higherLevel &&
|
||
( ( halfPos === 1 || halfPos === 3 ) && ( d === 4 || d === 6 ) ) ||
|
||
( ( halfPos === 0 || halfPos === 1 ) && d === 8 ) ||
|
||
( ( halfPos === 2 || halfPos === 3 ) && d === 2 )
|
||
) {
|
||
if( checkUnderpassCollision( x, y, d ) ) {
|
||
if( ( halfPos === 0 && d === 8 ) || ( halfPos === 2 && d === 2 ) ) {
|
||
if( !checkUnderpassCollision( x - 1, y, d ) ) return false;
|
||
}
|
||
} else return false;
|
||
}
|
||
|
||
return isOPMapPassable;
|
||
};
|
||
|
||
/*---- Game_Follower ----*/
|
||
/**
|
||
* 指定位置の指定フラグビットが通行可か。
|
||
* @param {Number} character 追うキャラクタ
|
||
*/
|
||
const _Game_Follower_chaseCharacter = Game_Follower.prototype.chaseCharacter;
|
||
Game_Follower.prototype.chaseCharacter = function( character ) {
|
||
if( TF_OverpassTerrainTag === 0 ) {
|
||
_Game_Follower_chaseCharacter.apply( this, arguments );
|
||
return;
|
||
}
|
||
|
||
const sx = this.deltaXFrom( character.x );
|
||
const sy = this.deltaYFrom( character.y );
|
||
const d = 5 - Math.sign( sx ) + ( ( sx === 0 ) ? Math.sign( sy ) * 3 : 0 );
|
||
if( d === 5 ) {
|
||
_Game_Follower_chaseCharacter.apply( this, arguments );
|
||
return;
|
||
}
|
||
|
||
const x = Math.floor( this.x + 0.5 );
|
||
const y = Math.floor( this.y + 0.5 );
|
||
const halfPos = getHalfPos( this.x, this.x );
|
||
if( this._higherLevel ) {
|
||
if( isDownFromUpperTile( x, y, d, halfPos ) ) this._higherLevel = false;
|
||
} else {
|
||
if( isUp2Higher( x, y, d, halfPos ) ) this._higherLevel = true;
|
||
}
|
||
|
||
_Game_Follower_chaseCharacter.apply( this, arguments );
|
||
};
|
||
|
||
|
||
/*---- Game_Event ----*/
|
||
var _Game_Event_initialize = Game_Event.prototype.initialize;
|
||
Game_Event.prototype.initialize = function( mapId, eventId ) {
|
||
_Game_Event_initialize.apply( this, arguments );
|
||
|
||
const getMetaValue = ( object, name ) => {
|
||
const metaTagName = 'TF_' + name;
|
||
return object.meta.hasOwnProperty( metaTagName ) ? object.meta[ metaTagName ] : undefined;
|
||
};
|
||
|
||
const zDef = getMetaValue( this.event(), 'zDef' );
|
||
if( zDef !== undefined ) this._TF_zDef = parseFloat( zDef );
|
||
|
||
const higherLevel = getMetaValue( this.event(), 'higherLevel' );
|
||
if( higherLevel !== undefined ) this._higherLevel = ( higherLevel.toLowerCase() === PARAM_TRUE );
|
||
};
|
||
|
||
|
||
/*---- Game_Map ----*/
|
||
/**
|
||
* 指定位置の指定フラグビットが通行可か。
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @param {Number} bit {@link RPG.Tileset}の flagsチェック用ビット
|
||
* @returns {Boolean} 高層表示[☆]の4方向の通行設定については@helpを参照
|
||
*/
|
||
//const _Game_Map_checkPassage = Game_Map.prototype.checkPassage;
|
||
Game_Map.prototype.checkPassage = function( x, y, bit ) {
|
||
const flags = this.tilesetFlags();
|
||
const tiles = this.allTiles( x, y );
|
||
const isOverpass = isOverpassTileAt( x, y );
|
||
const lastIndex = tiles.length - ( ( $gamePlayer._higherLevel && isOverpass ) ? 2 : 0 );
|
||
for( let i = 0; i < lastIndex; i++ ) {
|
||
const tileId = tiles[ i ];
|
||
const flag = flags[ tileId ];
|
||
|
||
if( tileId === 0 || // Bタイルの左上は無視
|
||
( flag & FLAG_UPPER ) && ( // [☆]かつ
|
||
( flag & FLAG_NORTH_DIR ) || // ・北通行不可タイルは無視
|
||
!( flag & MASK_ALL_DIR ) // ・全通行可タイルは無視
|
||
)
|
||
) continue;
|
||
if( ( flag & bit ) === 0 ) return true;
|
||
if( ( flag & bit ) === bit ) return false;
|
||
}
|
||
return $gamePlayer._higherLevel && isOverpass;
|
||
//return _Game_Map_checkPassage.apply( this, arguments );
|
||
};
|
||
|
||
|
||
/**
|
||
* 指定位置の立体交差地形タグを持つタイルの通行判定(4方向)チェック
|
||
* @param {Number} ax タイル数
|
||
* @param {Number} ay タイル数
|
||
* @param {Number} d 通行設定(テンキー方向)
|
||
* @returns {Boolean} 立体交差タイルでない場合nullを返す
|
||
*/
|
||
function checkOverpassCollision( x, y, d ) {
|
||
return checkOverpassCollisionBit( x, y, getFlag( d ) );
|
||
}
|
||
|
||
/**
|
||
* 指定位置の立体交差地形タグを持つタイルの通行判定(ビットフラグ)チェック
|
||
* @param {Number} ax タイル数
|
||
* @param {Number} ay タイル数
|
||
* @param {Number} bit 通行設定(ビットフラグ)
|
||
* @returns {Boolean} 立体交差タイルでない場合nullを返す
|
||
*/
|
||
function checkOverpassCollisionBit( x, y, bit ) {
|
||
const flags = $gameMap.tilesetFlags();
|
||
const tiles = $gameMap.allTiles( Math.floor( $gameMap.roundX( x ) ), Math.floor( $gameMap.roundY( y ) ) );
|
||
|
||
for( let i = 0; i < tiles.length; i++ ) {
|
||
const flag = flags[ tiles[ i ] ];
|
||
if( flag >> 12 === TF_OverpassTerrainTag && !Tilemap.isTileA5( tiles[ i ] ) ) {
|
||
return ( flag & bit ) === bit;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 指定位置のタイルは立体交差地形タグを持つか
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @returns {Boolean} 立体交差タイルでない場合nullを返す
|
||
*/
|
||
function isOverpassTileAt( x, y ) {
|
||
const flags = $gameMap.tilesetFlags();
|
||
const tiles = $gameMap.layeredTiles( $gameMap.roundX( x ), $gameMap.roundY( y ) );
|
||
for( let i = 0; i < tiles.length; i++ ) {
|
||
if( flags[ tiles[ i ] ] >> 12 === TF_OverpassTerrainTag && !Tilemap.isTileA5( tiles[ i ] ) ) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
/**
|
||
* 高層へ上がるタイミングか
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @param {Number} d 通行設定(テンキー方向)
|
||
* @param {Number} halfPos タイル内での位置
|
||
* @returns {Boolean}
|
||
*/
|
||
function isUp2Higher( x, y, d, halfPos ) {
|
||
if( halfPos === 0 || halfPos === 2 ) {
|
||
if( !isOverpassTileAt( x - 1, y ) && checkOverpassCollision( x, y, 4 ) === false ) return true; // 西出入口境界
|
||
}
|
||
if( isOverpassTileAt( x, y ) ) return false; // 立体交差タイルの上は帰す
|
||
|
||
return (
|
||
checkOverpassCollision( x - 1, y, 6 ) === false || // 東出入口
|
||
checkOverpassCollision( x + 1, y, 4 ) === false || // 西出入口
|
||
checkOverpassCollision( x, y + 1, 8 ) === false || // 北入り口↓
|
||
( !isOverpassTileAt( x - 1, y ) && checkOverpassCollision( x - 1, y + 1, 8 ) === false ) ||
|
||
( !isOverpassTileAt( x, y - 1 ) && checkOverpassCollision( x, y - 2, 2 ) === false ) || // 南入口↓
|
||
( !isOverpassTileAt( x - 1, y ) && ( checkOverpassCollision( x - 1, y - 1, 2 ) === false ||
|
||
( !isOverpassTileAt( x - 1, y - 1 ) && checkOverpassCollision( x - 1, y - 2, 2 ) === false ) )
|
||
) ||
|
||
( !isOverpassTileAt( x + 1, y ) && checkOverpassCollision( x + 1, y - 1, 2 ) === false )
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 高層から降りるタイミングか
|
||
* @param {Number} x タイル数
|
||
* @param {Number} y タイル数
|
||
* @param {Number} d 通行設定(テンキー方向)
|
||
* @param {Number} halfPos タイル内での位置
|
||
* @returns {Boolean}
|
||
*/
|
||
function isDownFromUpperTile( x, y, d, halfPos ) {
|
||
if( isOverpassTileAt( x, y ) ) return false; // 立体交差タイルの上は帰す
|
||
if( checkOverpassCollision( x, y - 1, 2 ) === false ) return false; // 南入り口タイルは帰す
|
||
if( ( halfPos === 0 || halfPos === 2 ) && checkOverpassCollision( x - 1, y - 1, 2 ) === false ) return false;
|
||
|
||
// 全周に立体交差タイルの入り口がない
|
||
return checkOverpassCollision( x + 1, y, 4 ) !== false && // 東
|
||
checkOverpassCollision( x - 1, y, 6 ) !== false && // 西
|
||
checkOverpassCollision( x, y + 1, 8 ) !== false && // 南
|
||
checkOverpassCollision( x - 1, y + 1, 8 ) !== false && // 南西
|
||
checkOverpassCollision( x, y - 2, 2 ) !== false; // ふたつ北
|
||
}
|
||
|
||
/**
|
||
* タイル内の位置を返す( 0:左上, 1:上, 2:左下, 3:下 )
|
||
* @param {Number} x x座標(タイル数)
|
||
* @param {Number} y y座標(タイル数)
|
||
*/
|
||
function getHalfPos( x, y ) {
|
||
return ( ( ( x % 1 ) === 0 ) ? 1 : 0 ) + ( ( ( y % 1 ) === 0 ) ? 2 : 0 );
|
||
}
|
||
/**
|
||
* 指定方向のX要素を返す。
|
||
* @param {Number} d 方向(テンキー対応)
|
||
*/
|
||
function getDx( d ) {
|
||
return ( d === 6 ) ? 1 : ( d === 4 ) ? -1 : 0;
|
||
}
|
||
/**
|
||
* 指定方向のY要素を返す。
|
||
* @param {Number} d 方向(テンキー対応)
|
||
*/
|
||
function getDy( d ) {
|
||
return ( d === 2 ) ? 1 : ( d === 8 ) ? -1 : 0;
|
||
}
|
||
/**
|
||
* 指定方向をflagに変換して返す。
|
||
* @param {Number} d 方向(テンキー対応)
|
||
*/
|
||
function getFlag( d ) {
|
||
return 1 << ( d / 2 - 1 );
|
||
}
|
||
} )(); |