prison-brave/js/plugins/RegionSetting.js
2025-08-28 10:38:20 -05:00

458 lines
15 KiB
JavaScript

//=============================================================================
// RPG Maker MZ - RegionSetting
//
// Copyright 2024 Panzer-IV. All rights reserved.
// This source code or any portion thereof must not be
// reproduced or used without licensed in any manner whatsoever.
//=============================================================================
/*:
* @target MZ
* @plugindesc リージョン設定プラグイン
* @author 四号戦車
* @base PluginCommonBase
* @base DebugSwitch
* @base TextResource
* @base PluginUtils
* @orderAfter PluginCommonBase
* @orderAfter DebugSwitch
* @orderAfter TextResource
* @orderAfter PluginUtils
*
* @param regions
* @text リージョン設定
* @desc リージョンと効果の指定です。
* @type struct<RegionSetting>[]
* @default []
*
* @param passageSetting
* @text 通行不可デフォルト設定
* @desc 通行不可リージョンが設定されていない
* タイルの通行設定
* @type select
* @default default_passage
* @option ツクールの設定に従う
* @value default_passage
* @option 全て通行可
* @value all_passible
* @option 全て通行不可
* @value all_not_passible
*
*
* @help RegionSetting.js
*
* Version: 0.0.3
*
* マップリージョンに特殊処理を持たせる設定プラグイン
*
*/
/*~struct~RegionSetting:
*
* @param name
* @text 設定名
* @desc 設定用の名前です。
* 入力時識別用にお使い下さい。
* @type string
* @default
*
* @param region
* @text リージョン番号
* @desc 指定リージョンの番号です。
* @type number
* @min 0
* @default 0
*
* @param effect
* @text 効果
* @desc 指定リージョンに付与する効果を指定します。
* @type select
* @default none
* @option なし
* @value none
* @option 通行不可
* @value blockPassible
* @option 左方向だけ移動不可
* @value onlyLeftBlock
* @option 上方向だけ移動不可
* @value onlyUpBlock
* @option 右方向だけ移動不可
* @value onlyRightBlock
* @option 下方向だけ移動不可
* @value onlyDownBlock
* @option 上下のみ移動可能
* @value onlyVirtical
* @option 左右のみ移動可能
* @value onlyHorizontal
* @option 左と上だけ移動不可
* @value onlyUpLeftBlock
* @option 上と右だけ移動不可
* @value onlyUpRightBlock
* @option 右と下だけ移動不可
* @value onlyDownRightBlock
* @option 下と左だけ移動不可
* @value onlyDownLeftBlock
* @option 強制通行
* @value forcePassible
* @option 通行不可(キャラクターの描画をマップより上に)
* @value blockPassibleWithOverlayTile
* @option 強制的にマップより優先表示(☆無視)
* @value overlayTile
*
* @param maskOnFarPlayer
* @text 近づくと消える壁設定
* @text ONにすると「近づくと消える壁」に出来ます。
* @type boolean
* @default false
*
*/
(() => {
"use strict";
//========================================================================
// プラグイン定義
//========================================================================
const pluginName = "RegionSetting";
const script = document.currentScript;
const param = PluginUtils.reparseParameter(script);
//========================================================================
// 定数定義
//========================================================================
const DIRECTION_UP = 8;
const DIRECTION_LEFT = 4;
const DIRECTION_RIGHT = 6;
const DIRECTION_DOWN = 2;
const checkDirection = (direction, ...blockdirections) => {
return !blockdirections.some(dir => dir === direction);
};
//========================================================================
// クラス定義 (Sprite_MapMask)
//========================================================================
class Sprite_MapMask extends Sprite {
constructor(mask) {
super(new Bitmap($gameMap.tileWidth(), $gameMap.tileHeight()));
this._mapMask = mask;
this.bitmap.fillAll('#000000');
}
get group() {
return this._mapMask?.group;
}
set maskVisible(value) {
if (!!this._mapMask) {
this._mapMask.visible = value;
}
}
update() {
super.update();
this.updatePosition();
this.updateOpacity();
}
updatePosition() {
if (!!this._mapMask) {
this.x = this._mapMask.screenX();
this.y = this._mapMask.screenY();
this.z = 6;
}
}
isNearThePlayer() {
if (!!this._mapMask) {
return this._mapMask.isNearThePlayer();
}
return false;
}
updateOpacity() {
if (!!this._mapMask) {
if (this._mapMask.isVisible()) {
if (this.opacity < 255) {
this.opacity += 10;
if (this.opacity >= 255) {
this.opacity = 255;
}
}
} else {
if (this.opacity > 0) {
this.opacity -= 10;
if (this.opacity < 0) {
this.opacity = 0;
}
}
}
}
}
};
//========================================================================
// クラス定義 (Game_MapMask)
//========================================================================
class Game_MapMask {
constructor(mask) {
this._realX = mask.x;
this._realY = mask.y;
this._effect = mask.effect;
this._group = mask.group;
this._visible = true;
}
get x() {
return this._realX;
}
get y() {
return this._realY;
}
get group() {
return this._group;
}
set visible(value) {
this._visible = value;
}
screenX() {
const tw = $gameMap.tileWidth();
const scrolledX = $gameMap.adjustX(this._realX);
return Math.floor(scrolledX * tw);
}
screenY() {
const th = $gameMap.tileHeight();
const scrolledY = $gameMap.adjustY(this._realY);
return Math.floor(scrolledY * th);
}
isNearThePlayer() {
const sx = Math.abs($gameMap.deltaX(this._realX, $gamePlayer.x));
const sy = Math.abs($gameMap.deltaY(this._realY, $gamePlayer.y));
return sx + sy < 5;
}
show() {
this._visible = true;
}
hide() {
this._visible = false;
}
isVisible() {
return this._visible;
}
}
//========================================================================
// コアスクリプト変更部 (Game_Map)
//========================================================================
const _Game_Map_prototype_setup = Game_Map.prototype.setup;
Game_Map.prototype.setup = function(mapId) {
_Game_Map_prototype_setup.apply(this, arguments);
const width = $dataMap.width;
const height = $dataMap.height;
const masks = [];
for (let y = 1; y <= height; y++) {
for (let x = 1; x <= width; x++) {
const regionId = this.regionId(x, y);
const setting = param.regions.find(region => {
return region.region === regionId && region.maskOnFarPlayer;
});
if (!!setting) {
masks.push({
x: x,
y: y,
effect: setting.effect, regionId,
group: regionId,
visible: true,
});
}
}
}
this._maskGroups = masks.map(mask => {
return mask.group;
}).filter((group, index, self) => {
return self.indexOf(group) === index;
});
this._mapMasks = masks;
};
Game_Map.prototype.mapMasks = function() {
return this._mapMasks;
};
Game_Map.prototype.mapMaskGroups = function() {
return this._maskGroups;
};
//========================================================================
// コアスクリプト変更部 (Spriteset_Map)
//========================================================================
const _Spriteset_Map_prototype_createCharacters = Spriteset_Map.prototype.createCharacters;
Spriteset_Map.prototype.createCharacters = function() {
_Spriteset_Map_prototype_createCharacters.apply(this, arguments);
this._mapMaskSprites = [];
for (const mask of $gameMap.mapMasks()) {
this._mapMaskSprites.push(new Sprite_MapMask(new Game_MapMask(mask)));
}
this._mapMaskSprites.forEach(sprite => {
this._tilemap.addChild(sprite);
});
};
const _Spriteset_Map_prototype_update = Spriteset_Map.prototype.update;
Spriteset_Map.prototype.update = function() {
if (!!this._mapMaskSprites) {
const maskGroups = $gameMap.mapMaskGroups();
maskGroups.forEach(group => {
const groups = this._mapMaskSprites.filter(maskSprite => {
return maskSprite.group === group;
});
const visible = groups.every(maskSprite => {
return !maskSprite.isNearThePlayer();
})
groups.forEach(maskSprite => {
maskSprite.maskVisible = visible;
});
});
}
_Spriteset_Map_prototype_update.apply(this, arguments);
};
//========================================================================
// コアスクリプト変更部 (Game_Map)
//========================================================================
const _Game_Map_prototype_isPassable = Game_Map.prototype.isPassable;
Game_Map.prototype.isPassable = function(x, y, d) {
const regionId = this.regionId(x, y);
const setting = param.regions.find(region => {
return region.region === regionId;
});
const passageSeeting = param.passageSetting;
const defaultPassible = () => {
switch (passageSeeting) {
case 'all_passible':
return true;
case 'all_not_passible':
return false;
case 'default_passage':
default:
return _Game_Map_prototype_isPassable.apply(this, arguments);
} // switch
};
if (!!setting) {
switch (setting.effect) {
case 'blockPassible':
case 'blockPassibleWithOverlayTile':
return false;
case 'forcePassible':
return true;
case 'onlyLeftBlock':
return checkDirection(d, DIRECTION_LEFT);
case 'onlyUpBlock':
return checkDirection(d, DIRECTION_UP);
case 'onlyRightBlock':
return checkDirection(d, DIRECTION_RIGHT);
case 'onlyDownBlock':
return checkDirection(d, DIRECTION_DOWN);
case 'onlyVirtical':
return checkDirection(d, DIRECTION_LEFT, DIRECTION_RIGHT);
case 'onlyHorizontal':
return checkDirection(d, DIRECTION_UP, DIRECTION_DOWN);
case 'onlyUpLeftBlock':
return checkDirection(d, DIRECTION_UP, DIRECTION_LEFT);
case 'onlyUpRightBlock':
return checkDirection(d, DIRECTION_UP, DIRECTION_RIGHT);
case 'onlyDownRightBlock':
return checkDirection(d, DIRECTION_DOWN, DIRECTION_RIGHT);
case 'onlyDownLeftBlock':
return checkDirection(d, DIRECTION_DOWN, DIRECTION_LEFT);
default:
return defaultPassible();
} // switch
} else {
return defaultPassible();
}
};
Game_Map.prototype.isOverlayTile = function(x, y) {
const regionId = this.regionId(x, y);
const setting = param.regions.find(region => {
return region.region === regionId;
});
return !!setting && [
'blockPassibleWithOverlayTile',
'overlayTile',
].some(effect => setting.effect === effect);
};
Game_Map.prototype.isBlockPassible = function(x, y) {
const regionId = this.regionId(x, y);
const setting = param.regions.find(region => {
return region.region === regionId;
});
return !!setting && setting.effect === 'blockPassible';
};
//========================================================================
// コアスクリプト変更部 (Game_Event)
//========================================================================
const _Game_Event_start = Game_Event.prototype.start;
Game_Event.prototype.start = function() {
if (this.isTriggerIn([0, 1])) {
// プレイヤーが侵入できない箇所にいるイベントはインタラクトもさせない
const x = $gamePlayer.x;
const y = $gamePlayer.y;
const d = $gamePlayer.direction();
if (!$gameMap.isPassable(x, y, d)) {
return;
}
} else if (this.isTriggerIn([2])) {
// イベント側からプレイヤーのいる箇所に侵入不可ならインタラクトさせない
const x = $gamePlayer.x;
const y = $gamePlayer.y;
const d = this.reverseDir(this.direction());
if (!$gameMap.isPassable(x, y, d)) {
return;
}
}
_Game_Event_start.apply(this, arguments);
};
//========================================================================
// コアスクリプト変更部 (Game_Event)
//========================================================================
const _Game_CharacterBase_screenZ = Game_CharacterBase.prototype.screenZ;
Game_CharacterBase.prototype.screenZ = function() {
const z = _Game_CharacterBase_screenZ.apply(this, arguments);
if ($gameMap.isOverlayTile(this.x, this.y)) {
return z + 3;
}
if ($gameMap.isBlockPassible(this.x, this.y - 1)) {
return z + 3;
}
return z;
};
//========================================================================
// プラグインコマンド
//========================================================================
})();