// DarkPlasma_CharacterAfterimage 1.0.1 // Copyright (c) 2024 DarkPlasma // This software is released under the MIT license. // http://opensource.org/licenses/mit-license.php /** * 2024/03/07 1.0.1 特定のプラグインと併用するとエラーが発生する不具合を修正 * 2024/03/01 1.0.0 公開 */ /*: @target MZ @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release @plugindesc Display afterimages on characters on the map @author DarkPlasma @license MIT @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/DarkPlasma-MZ-Plugins ). Original plugin by DarkPlasma. Please check the latest official version at: https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release ----- version: 1.0.1 Displays afterimages for characters on the map. This plugin extends save data. For each character displaying afterimages on the map, the display status is added to the save data. @param duration @text Display time (number of frames) @type number @default 30 @param generationInterval @text Generation interval (number of frames) @type number @default 4 @param opacity @text Opacity @type number @default 255 @max 255 @param colorTone @text tone @type struct @default {"red":"0","blue":"0","green":"0","alpha":"0"} @param blendMode @text Synthesis method @type select @default 0 @option usually @value 0 @option Addition @value 1 @option Multiplication @value 2 @option screen @value 3 @command startAfterimage @text Afterimage Display @desc Displays an afterimage for a player or event. @arg target @text subject @desc Select the object for which you want to display the afterimage. @type select @default player @option Player @value player @option This event @value thisEvent @option Other events @value otherEvent @arg eventId @text Event ID @desc If the target is another event, specify the event ID. @type number @default 0 @command clearAfterimage @text Removing afterimages @desc Clears any afterimages displayed to players or events. @arg target @text subject @desc Select the object for which you want to display the afterimage. @type select @default player @option Player @value player @option This event @value thisEvent @option Other events @value otherEvent @arg eventId @text Event ID @desc If the target is another event, specify the event ID. @type number @default 0 */ /*:ja @plugindesc マップ上のキャラクターに残像を表示する @author DarkPlasma @license MIT @target MZ @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release @param duration @text 表示時間(フレーム数) @type number @default 30 @param generationInterval @text 生成間隔(フレーム数) @type number @default 4 @param opacity @text 不透明度 @type number @max 255 @default 255 @param colorTone @text 色調 @type struct @default {"red":"0","blue":"0","green":"0","alpha":"0"} @param blendMode @text 合成方法 @type select @option 通常 @value 0 @option 加算 @value 1 @option 乗算 @value 2 @option スクリーン @value 3 @default 0 @command startAfterimage @text 残像の表示 @desc プレイヤーまたはイベントに対して残像を表示します。 @arg target @desc 残像の表示対象を選択します。 @text 対象 @type select @option プレイヤー @value player @option このイベント @value thisEvent @option 他のイベント @value otherEvent @default player @arg eventId @desc 対象が他のイベントの場合に、イベントIDを指定します。 @text イベントID @type number @default 0 @command clearAfterimage @text 残像の消去 @desc プレイヤーまたはイベントに対して表示している残像を消去します。 @arg target @desc 残像の表示対象を選択します。 @text 対象 @type select @option プレイヤー @value player @option このイベント @value thisEvent @option 他のイベント @value otherEvent @default player @arg eventId @desc 対象が他のイベントの場合に、イベントIDを指定します。 @text イベントID @type number @default 0 @help version: 1.0.1 マップ上のキャラクターに残像を表示します。 本プラグインはセーブデータを拡張します。 マップ上の残像を表示している各キャラクターについて、 その表示状態をセーブデータに追加します。 */ (() => { 'use strict'; const pluginName = document.currentScript.src.replace(/^.*\/(.*).js$/, function () { return arguments[1]; }); const pluginParametersOf = (pluginName) => PluginManager.parameters(pluginName); const pluginParameters = pluginParametersOf(pluginName); const settings = { duration: Number(pluginParameters.duration || 30), generationInterval: Number(pluginParameters.generationInterval || 4), opacity: Number(pluginParameters.opacity || 255), colorTone: pluginParameters.colorTone ? ((parameter) => { const parsed = JSON.parse(parameter); return { red: Number(parsed.red || 0), green: Number(parsed.green || 0), blue: Number(parsed.blue || 0), alpha: Number(parsed.alpha || 0), }; })(pluginParameters.colorTone) : { red: 0, blue: 0, green: 0, alpha: 0 }, blendMode: Number(pluginParameters.blendMode || 0), }; function parseArgs_startAfterimage(args) { return { target: String(args.target || `player`), eventId: Number(args.eventId || 0), }; } const command_startAfterimage = 'startAfterimage'; const command_clearAfterimage = 'clearAfterimage'; PluginManager.registerCommand(pluginName, command_startAfterimage, function (args) { const parsedArgs = parseArgs_startAfterimage(args); const target = (() => { switch (parsedArgs.target) { case 'player': return $gamePlayer; case 'thisEvent': return this.character(0); case 'otherEvent': return this.character(parsedArgs.eventId); default: return null; } })(); target?.requestStartAfterimage(); }); PluginManager.registerCommand(pluginName, command_clearAfterimage, function (args) { const parsedArgs = parseArgs_startAfterimage(args); const target = (() => { switch (parsedArgs.target) { case 'player': return $gamePlayer; case 'thisEvent': return this.character(0); case 'otherEvent': return this.character(parsedArgs.eventId); default: return null; } })(); target?.clearAfterimage(); }); function Game_CharacterBase_AfterimageMixIn(gameCharacterBase) { const _initMembers = gameCharacterBase.initMembers; gameCharacterBase.initMembers = function () { _initMembers.call(this); this._afterimage = undefined; }; gameCharacterBase.hasAfterimage = function () { return !!this._afterimage; }; gameCharacterBase.afterimage = function () { return this._afterimage; }; gameCharacterBase.requestStartAfterimage = function () { this._afterimage = new Game_CharacterAfterimage(); }; gameCharacterBase.clearAfterimage = function () { this._afterimage = undefined; }; const _update = gameCharacterBase.update; gameCharacterBase.update = function () { _update.call(this); this._afterimage?.update(); }; } Game_CharacterBase_AfterimageMixIn(Game_CharacterBase.prototype); class Game_CharacterAfterimage { constructor() { this._interval = settings.generationInterval; this._generateAfterimageFrameCount = settings.generationInterval; this._duration = settings.duration; this._initialOpacity = settings.opacity; this._colorTone = [ settings.colorTone.red, settings.colorTone.green, settings.colorTone.blue, settings.colorTone.alpha, ]; this._blendMode = settings.blendMode; } update() { this._generateAfterimageFrameCount++; } resetGenerationFrameCount() { this._generateAfterimageFrameCount = 0; } mustGenerateSprite() { return this._generateAfterimageFrameCount >= this._interval; } duration() { return this._duration; } initialOpacity() { return this._initialOpacity; } colorTone() { return this._colorTone; } blendMode() { return this._blendMode; } } function Spriteset_Map_AfterimageMixIn(spritesetMap) { const _update = spritesetMap.update; spritesetMap.update = function () { _update.call(this); this._characterSprites.forEach((character) => character.clearReservedAfterimages()); }; } Spriteset_Map_AfterimageMixIn(Spriteset_Map.prototype); function Sprite_Character_AfterimageMixIn(spriteCharacter) { const _initialize = spriteCharacter.initialize; spriteCharacter.initialize = function (character) { _initialize.call(this, character); this._afterimageSprites = []; this._clearReservedAfterimageSprites = []; }; spriteCharacter.createAfterimage = function () { const afterimage = new Sprite_CharacterAfterimage(this._character) .withPosition(this.x, this.y, this.z - 0.1) .withScale(this.scale) .withRotation(this.rotation) .withAnchor(this.anchor.x, this.anchor.y); this._afterimageSprites.push(afterimage); this.parent.addChild(afterimage); }; spriteCharacter.clearAfterimage = function () { this._afterimageSprites.forEach((afterimage) => this.parent.removeChild(afterimage)); this._afterimageSprites = []; }; const _update = spriteCharacter.update; spriteCharacter.update = function () { _update.call(this); this.updateAfterimage(); }; spriteCharacter.updateAfterimage = function () { /** * ここでremoveChildしてしまうとtilemapの子spriteの数が変動し、updateがスキップされてしまうspriteが現れる * そのため、removeChildの予約だけしておく */ this._clearReservedAfterimageSprites = this._afterimageSprites.filter((afterimage) => afterimage.opacity <= 0); this._afterimageSprites = this._afterimageSprites.filter((afterimage) => afterimage.opacity > 0); if (this._character.afterimage()?.mustGenerateSprite()) { this.createAfterimage(); this._character.afterimage()?.resetGenerationFrameCount(); } }; spriteCharacter.clearReservedAfterimages = function () { this._clearReservedAfterimageSprites.forEach((sprite) => this.parent.removeChild(sprite)); this._clearReservedAfterimageSprites = []; }; } Sprite_Character_AfterimageMixIn(Sprite_Character.prototype); class Sprite_CharacterAfterimage extends Sprite_Character { constructor(character) { super(character); const afterimage = character.afterimage(); if (!afterimage) { throw new Error(`対象キャラクターに残像情報が存在しません。`); } /** * この時点でのキャラクター情報をコピーしておく */ this._character = JsonEx.makeDeepCopy(character); this._afterimage = afterimage; this.setColorTone(afterimage.colorTone()); this.blendMode = afterimage.blendMode(); this.updateBitmap(); this.updateFrame(); } withPosition(x, y, z) { this.x = x; this.y = y; this.z = z; return this; } withScale(scale) { this.scale = scale; return this; } withRotation(rotation) { this.rotation = rotation; return this; } withAnchor(x, y) { this.anchor.x = x; this.anchor.y = y; return this; } update() { this.opacity -= this._afterimage.initialOpacity() / this._afterimage.duration(); this.updatePosition(); } updatePosition() { super.updatePosition(); this.z -= 0.1; } } globalThis.Game_CharacterAfterimage = Game_CharacterAfterimage; })();