/*============================================================================= PhantomEvent.js ---------------------------------------------------------------------------- (C)2018 Triacontane This software is released under the MIT License. http://opensource.org/licenses/mit-license.php ---------------------------------------------------------------------------- Version 1.6.0 2023/02/26 プレイヤー以外にも光源イベントを作成できる機能を追加 1.5.1 2021/05/11 1.5.0の修正により、パーティメンバーが0人になるとエラーになる問題を修正 1.5.0 2021/05/04 アクターごとに可視距離のレートを指定できる機能を追加 1.4.1 2020/12/09 マップ改編系プラグインとの一般的な競合対策を追加 1.4.0 2019/01/27 本来の設定とは逆に、近づくほど透明度を上げられる機能を追加 1.3.0 2018/11/18 イベントとの距離が一定以内の場合にセルフスイッチをONにする機能を追加 1.2.1 2018/11/11 一部、無駄な処理を行っていたのを修正 1.2.0 2018/11/11 全イベントの不可視化を無効にできるスイッチの追加 1.1.0 2018/11/11 最小不透明度を設定できる機能を追加 1.0.0 2018/11/11 初版 ---------------------------------------------------------------------------- [Blog] : https://triacontane.blogspot.jp/ [Twitter]: https://twitter.com/triacontane/ [GitHub] : https://github.com/triacontane/ =============================================================================*/ /*: @url https://triacontane.blogspot.com/ @plugindesc Phantom Event Plugin @author Triacontane @license MIT License @help English Help Translator: munokura This is an unofficial English translation of the plugin help, created to support global RPG Maker users. Feedback is welcome to improve translation quality (see: https://github.com/munokura/triacontane-MV-plugins ). Original plugin by Triacontane. Please check the latest official version at: https://triacontane.blogspot.com ----- PhantomEvent.js Gradually reduces the transparency of events beyond the specified range, eventually making them invisible. No other changes occur except for the screen display. Enter the following in the event's Note field: // Invisible if more than 3 blocks away. // Self-switch turns on if more than 2 blocks away. // Opposite of the default setting, the closer the event, the more opacity increases. You can change the visibility rate depending on the leading actor. Specify the following in a database with Traits (*): // Visible distance is multiplied by 1.5. * Applies to actors, jobs, weapons, armor, and states. This plugin does not have plugin commands. Terms of Use: You may modify and redistribute this plugin without permission from the author, and there are no restrictions on its use (commercial, 18+, etc.). This plugin is now yours. @param invisibleDistance @text Invisibility Distance @desc The number of squares from when the specified range is exceeded until it becomes completely invisible. @type number @default 3 @min 1 @param visibleSelfSwitch @text Visualization Self-Switch @desc When the specified self switch is ON, event invisibility is disabled. @type select @option none @value @option A @option B @option C @option D @param visibleSwitch @text Visualization Switch @desc When the switch with the specified ID is ON, invisibility of all events will be disabled. @type switch @default 0 @param minimumOpacity @text minimum opacity @desc No matter how far away you are, it will maintain a minimum opacity of (0-255). @type number @default 0 @min 0 @max 255 @param distanceTriggerSelfSwitch @text Distance Trigger Self Switch @desc This is the self-switch number that will automatically turn on when you get closer than the distance specified in the event Note field. @type select @option none @value @option A @option B @option C @option D @param visibleRate @text Visible Rate Target @desc This is the target to obtain when you specify a visibility rate for each actor. @type select @default leader @option First only @value leader @option Everyone @value all @param commandPrefix @text Note field prefix @desc This is the prefix to specify when the name of the Note field or plugin command overlaps with that of another plugin. Normally, it is not necessary to specify this. */ /*:ja @plugindesc ファントムイベントプラグイン @author トリアコンタン @param invisibleDistance @text 不可視距離 @desc 指定範囲を超えてから完全に見えなくなるまでのマス数です。 @default 3 @type number @min 1 @param visibleSelfSwitch @text 可視化セルフスイッチ @desc 指定したセルフスイッチがONのとき、イベントの不可視化が無効になります。 @default @type select @option none @value @option A @option B @option C @option D @param visibleSwitch @text 可視化スイッチ @desc 指定したIDのスイッチがONのとき、全イベントの不可視化が無効になります。 @default 0 @type switch @param minimumOpacity @text 最小不透明度 @desc どれだけ離れても最低限、以下の不透明度を保ちます。(0-255) @default 0 @type number @min 0 @max 255 @param distanceTriggerSelfSwitch @text 距離トリガーセルフスイッチ @desc イベントのメモ欄で指定した距離より近づいたときに自動でONになるセルフスイッチ番号です。 @default @type select @option none @value @option A @option B @option C @option D @param visibleRate @text 可視レート対象 @desc アクターごとの可視レートを指定した場合の取得対象です。 @default leader @type select @option 先頭のみ @value leader @option 全員 @value all @param commandPrefix @text メモ欄接頭辞 @desc 他のプラグインとメモ欄もしくはプラグインコマンドの名称が被ったときに指定する接頭辞です。通常は指定不要です。 @default @help PhantomEvent.js 指定範囲より遠くにあるイベントの透明度を徐々に下げて最終的に不可視にします。 画面表示以外は特に変化はありません。 イベントのメモ欄に以下の通り入力してください。 <可視距離:3> // 3マス以上離れると見えなくなります。 // 同上 <トリガー距離:2> // 2マス以上離れるとセルフスイッチがONになります。 // 同上 <透明度反転> // 本来の設定とは逆に近づくほど透明度が上がります。 // 同上 先頭のアクターによって可視距離のレートを変えられます。 特徴を有するデータベース(※)に以下の通り指定してください。 <可視距離倍率:150> // 可視距離が1.5倍になります。 + // 同上 ※ アクター、職業、武器、防具、ステートが該当します。 このプラグインにはプラグインコマンドはありません。 利用規約: 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) についても制限はありません。 このプラグインはもうあなたのものです。 */ (function () { 'use strict'; /** * Get database meta information. * @param object Database item * @param name Meta name * @returns {String} meta value */ var getMetaValue = function (object, name) { var tagName = param.commandPrefix + name; return object.meta.hasOwnProperty(tagName) ? convertEscapeCharacters(object.meta[tagName]) : null; }; /** * Get database meta information.(for multi language) * @param object Database item * @param names Meta name array (for multi language) * @returns {String} meta value */ var getMetaValues = function (object, names) { if (!object || !object.meta) { return undefined; } var metaValue; names.some(function (name) { metaValue = getMetaValue(object, name); return metaValue !== null; }); return metaValue; }; /** * Convert escape characters.(require any window object) * @param text Target text * @returns {String} Converted text */ var convertEscapeCharacters = function (text) { var windowLayer = SceneManager._scene._windowLayer; return windowLayer ? windowLayer.children[0].convertEscapeCharacters(text.toString()) : text; }; /** * Create plugin parameter. param[paramName] ex. param.commandPrefix * @param pluginName plugin name(EncounterSwitchConditions) * @returns {Object} Created parameter */ var createPluginParameter = function (pluginName) { var paramReplacer = function (key, value) { if (value === 'null') { return value; } if (value[0] === '"' && value[value.length - 1] === '"') { return value; } try { return JSON.parse(value); } catch (e) { return value; } }; var parameter = JSON.parse(JSON.stringify(PluginManager.parameters(pluginName), paramReplacer)); PluginManager.setParameters(pluginName, parameter); return parameter; }; var param = createPluginParameter('PhantomEvent'); /** * Game_Map * ピクセル単位での距離を取得します。 */ Game_Map.prototype.realDistance = function (x1, y1, x2, y2) { return Math.abs(this.realDeltaX(x1, x2)) + Math.abs(this.realDeltaY(y1, y2)); }; Game_Map.prototype.realDeltaX = function (x1, x2) { var result = (x1 - x2) * this.tileWidth(); var realWidth = this.width() * this.tileWidth(); if (this.isLoopHorizontal() && Math.abs(result) > realWidth / 2) { if (result < 0) { result += realWidth; } else { result -= realWidth; } } return result; }; Game_Map.prototype.realDeltaY = function (y1, y2) { var result = (y1 - y2) * this.tileHeight(); var realHeight = this.height() * this.tileHeight(); if (this.isLoopVertical() && Math.abs(result) > realHeight / 2) { if (result < 0) { result += realHeight; } else { result -= realHeight; } } return result; }; Game_Map.prototype.findLightSource = function () { if (this._lights) { return this._lights; } var light = this.events().filter(function (e) { return e.isLight(); }); light.push($gamePlayer); this._lights = light; return light; }; Game_Actor.prototype.findVisibleDistanceRate = function () { var result = 0; this.traitObjects().forEach(function (obj) { var rate = parseInt(getMetaValues(obj, ['可視距離倍率', 'VisibleDistanceRate'])); if (rate) { result = Math.max(result, rate); } }); return result / 100; }; Game_Party.prototype.findVisibleDistanceRate = function () { var actors = param.visibleRate === 'leader' ? this.members().filter((a, i) => i === 0) : this.members(); var result = 0; actors.forEach(function (actor) { result = Math.max(result, actor.findVisibleDistanceRate()); }); return result || 1; }; /** * Game_CharacterBase * 不透明度に不可視情報を反映させます。 */ var _Game_CharacterBase_opacity = Game_CharacterBase.prototype.opacity; Game_CharacterBase.prototype.opacity = function () { var opacity = _Game_CharacterBase_opacity.apply(this, arguments); var phantomOpacity = this.getPhantomOpacity(); return phantomOpacity !== 1 ? Math.max(Math.floor(opacity * phantomOpacity), param.minimumOpacity) : opacity; }; Game_CharacterBase.prototype.getPhantomOpacity = function () { return 1; }; /** * Game_Event * イベントの不可視距離を取得します。 */ var _Game_Event_initialize = Game_Event.prototype.initialize; Game_Event.prototype.initialize = function () { _Game_Event_initialize.apply(this, arguments); this._visibleDistance = parseInt(getMetaValues(this.event(), ['可視距離', 'VisibleDistance'])) * $gameMap.tileWidth() || 0; this._triggerDistance = parseInt(getMetaValues(this.event(), ['トリガー距離', 'TriggerDistance'])) * $gameMap.tileWidth() || 0; this._opacityReverse = !!getMetaValues(this.event(), ['透明度反転', 'OpacityReverse']); this._lightSource = !!getMetaValues(this.event(), ['光源', 'Light']); }; Game_Event.prototype.isLight = function () { return this._lightSource; }; Game_Event.prototype.getDistanceFromPlayer = function () { var dList = $gameMap.findLightSource().map(e => { return $gameMap.realDistance(this._realX, this._realY, e._realX, e._realY); }); return Math.min(...dList); }; Game_Event.prototype.isPhantom = function () { return this._visibleDistance > 0 && !this.isValidVisibleSelfSwitch() && !this.isValidVisibleSwitch(); }; Game_Event.prototype.isValidVisibleSelfSwitch = function () { var key = [$gameMap.mapId(), this.eventId(), param.visibleSelfSwitch]; return param.visibleSelfSwitch && $gameSelfSwitches.value(key); }; Game_Event.prototype.isValidVisibleSwitch = function () { return param.visibleSwitch && $gameSwitches.value(param.visibleSwitch); }; Game_Event.prototype.getPhantomOpacity = function () { if (!this.isPhantom()) { return 1; } var distanceFromPlayer = this.getDistanceFromPlayer(); this.updateDistanceTrigger(distanceFromPlayer); var d = distanceFromPlayer - Math.floor(this._visibleDistance * $gameParty.findVisibleDistanceRate()); if (this._opacityReverse) { d *= -1; } return Math.min(1 - d / ((param.invisibleDistance || 1) * $gameMap.tileWidth()), 1); }; Game_Event.prototype.updateDistanceTrigger = function (distanceFromPlayer) { var switchId = param.distanceTriggerSelfSwitch; if (switchId && this._triggerDistance > 0) { var key = [$gameMap.mapId(), this.eventId(), switchId]; var oldValue = $gameSelfSwitches.value(key); var newValue = distanceFromPlayer <= this._triggerDistance; if (oldValue !== newValue) { $gameSelfSwitches.setValue(key, newValue); } } }; })();