110 lines
4 KiB
JavaScript
110 lines
4 KiB
JavaScript
/*:
|
||
* @plugindesc MV専用:指定したマップのみ暗くし、灯りを表示するプラグイン
|
||
* @author 木星ペンギン(改変:魚雷城)
|
||
*
|
||
* @param Light Colors
|
||
* @desc 灯りの色をRGB形式で設定(例: ["255,255,255", "255,128,64"])
|
||
* @default ["255,255,255"]
|
||
*
|
||
* @param Darkness Opacity
|
||
* @desc マップの暗さ(0〜255)。数値が大きいほど暗い。
|
||
* @default 160
|
||
*
|
||
* @param Target Maps
|
||
* @desc 暗くする対象マップIDをカンマ区切りで指定(例: 1,3,5)
|
||
* @default 1
|
||
*
|
||
* @help
|
||
* プラグインコマンド:
|
||
* SetCharLight [キャラID] [半径] [色番号] [明滅幅]
|
||
* キャラに灯りを表示します。
|
||
* キャラID -1: プレイヤー, 0以上: イベントID
|
||
*/
|
||
|
||
(function() {
|
||
const parameters = PluginManager.parameters('MPP_MapLight');
|
||
const lightColors = JSON.parse(parameters['Light Colors'] || '["255,255,255"]');
|
||
const darknessOpacity = Number(parameters['Darkness Opacity'] || 160);
|
||
const targetMapIds = (parameters['Target Maps'] || '1').split(',').map(id => Number(id.trim()));
|
||
|
||
const _lightData = {};
|
||
|
||
// プラグインコマンド処理
|
||
const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
|
||
Game_Interpreter.prototype.pluginCommand = function(command, args) {
|
||
_Game_Interpreter_pluginCommand.call(this, command, args);
|
||
if (command === 'SetCharLight') {
|
||
const charId = Number(args[0]);
|
||
const radius = Number(args[1]);
|
||
const colorId = Number(args[2]);
|
||
const flick = Number(args[3]);
|
||
|
||
_lightData[charId] = {
|
||
radius: radius,
|
||
color: lightColors[colorId - 1] || "255,255,255",
|
||
flick: flick
|
||
};
|
||
}
|
||
};
|
||
|
||
// ライトレイヤー追加
|
||
const _Spriteset_Map_createUpperLayer = Spriteset_Map.prototype.createUpperLayer;
|
||
Spriteset_Map.prototype.createUpperLayer = function() {
|
||
_Spriteset_Map_createUpperLayer.call(this);
|
||
this.createLightLayer();
|
||
};
|
||
|
||
Spriteset_Map.prototype.createLightLayer = function() {
|
||
this._lightBitmap = new Bitmap(Graphics.width, Graphics.height);
|
||
this._lightSprite = new Sprite(this._lightBitmap);
|
||
this._lightSprite.blendMode = PIXI.BLEND_MODES.MULTIPLY;
|
||
this.addChild(this._lightSprite);
|
||
};
|
||
|
||
const _Spriteset_Map_update = Spriteset_Map.prototype.update;
|
||
Spriteset_Map.prototype.update = function() {
|
||
_Spriteset_Map_update.call(this);
|
||
this.updateLightLayer();
|
||
};
|
||
|
||
Spriteset_Map.prototype.updateLightLayer = function() {
|
||
const bitmap = this._lightBitmap;
|
||
bitmap.clear();
|
||
|
||
// 対象外マップなら return(暗くしない)
|
||
if (!targetMapIds.includes($gameMap.mapId())) return;
|
||
|
||
// 暗く塗る
|
||
bitmap.fillAll(`rgba(0, 0, 0, ${darknessOpacity / 255})`);
|
||
|
||
// 灯りを描画
|
||
for (const key in _lightData) {
|
||
const data = _lightData[key];
|
||
let chara = null;
|
||
if (Number(key) === -1) {
|
||
chara = $gamePlayer;
|
||
} else {
|
||
chara = $gameMap.event(Number(key));
|
||
}
|
||
if (chara) {
|
||
const x = chara.screenX();
|
||
const y = chara.screenY();
|
||
const r = data.radius * 48;
|
||
const color = data.color.split(',').map(Number);
|
||
const ctx = bitmap.context;
|
||
const gradient = ctx.createRadialGradient(x, y, 0, x, y, r);
|
||
gradient.addColorStop(0, `rgba(${color[0]},${color[1]},${color[2]},1.0)`);
|
||
gradient.addColorStop(1, `rgba(${color[0]},${color[1]},${color[2]},0.0)`);
|
||
|
||
ctx.save();
|
||
ctx.globalCompositeOperation = 'destination-out';
|
||
ctx.fillStyle = gradient;
|
||
ctx.beginPath();
|
||
ctx.arc(x, y, r, 0, Math.PI * 2, false);
|
||
ctx.fill();
|
||
ctx.restore();
|
||
bitmap._setDirty();
|
||
}
|
||
}
|
||
};
|
||
})();
|