//============================================================================= // NpcFollower.js // ---------------------------------------------------------------------------- // (C) 2016 Triacontane // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // ---------------------------------------------------------------------------- // Version // 1.2.0 2022/09/17 アクターIDを指定してNPCを削除できるコマンドを追加 // 1.1.2 2022/05/10 パラメータの説明文を修正 // 1.1.1 2019/11/02 1.1.0の修正でメンバーの入れ替えを実施すると表示が不正になる場合がある問題を修正 // 1.1.0 2019/01/27 通常のフォロワーを表示せず、NPCフォロワーのみを表示できる機能を追加 // 1.0.3 2018/08/06 コアスクリプトが1.6.0より古い場合にエラーになる記述を修正 // 1.0.2 2017/01/17 プラグインコマンドが小文字でも動作するよう修正(byこまちゃん先輩) // 1.0.1 2016/07/17 セーブデータをロードした際のエラーになる現象の修正 // 1.0.0 2016/07/14 初版 // ---------------------------------------------------------------------------- // [Blog] : https://triacontane.blogspot.jp/ // [Twitter]: https://twitter.com/triacontane/ // [GitHub] : https://github.com/triacontane/ //============================================================================= /*: @url https://triacontane.blogspot.com/ @plugindesc NPC Follower 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 ----- Adds a non-party NPC to any position in the map formation. NPCs are defined as actors in the database and can be added or removed using plugin commands. Since they are not combatants, they do not affect the menu or battle screen. Also, nothing is displayed if the formation is not displayed. You can also add multiple actors with the same ID. Plugin Command Details Execute from the "Plugin Command" event command. (Parameters are separated by a space.) NF_ADD_NPC 4 1 # Add actor ID [4] as an NPC after the [1]th NPC in the party. NF_ADD_NPC 5 3 # Add actor ID [5] as an NPC after the [3]th NPC in the party. NF_REM_NPC 1 # Delete all NPCs added in [1]th position. NF_REM_NPC 3 # Delete all NPCs added in [3]th position. The index you specify is independent of the added NPC. Please specify the party order (1...number of battle members). If you want to delete an NPC by ID rather than by order, use the following command: NF_REM_NPC_ID # Delete the NPC with actor ID [4] 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 最大同時NPC数 @text Maximum number of simultaneous NPCs @desc The maximum number of NPCs that can be in the formation at the same time. @type number @default 1 @min 1 @param 通常フォロワーを表示しない @text Do not display regular followers @desc Do not display any regular followers, only NPC followers. Enable column walking in the database. @type boolean @default false */ /*:ja @plugindesc NPCフォロワープラグイン @author トリアコンタン @param 最大同時NPC数 @desc 同時に隊列に存在できるNPCの最大数です。 @default 1 @type number @min 1 @param 通常フォロワーを表示しない @desc 通常のフォロワーを一切表示せず、NPCフォロワーのみを表示します。データベースの隊列歩行は有効にしてください。 @default false @type boolean @help マップ上の隊列の好きな位置にパーティメンバー以外のNPCを追加します。 NPCはデータベース上はアクターで定義してプラグインコマンドから追加、削除します。 戦闘員ではないので、メニュー画面や戦闘画面には影響を与えません。 また、隊列表示していない場合は何も表示されません。 同一IDのアクターを複数追加することもできます。 プラグインコマンド詳細 イベントコマンド「プラグインコマンド」から実行。 (パラメータの間は半角スペースで区切る) NF_NPC追加 4 1 # アクターID[4]をNPCとしてパーティの[1]番目の後ろに追加 NF_ADD_NPC 5 3 # アクターID[5]をNPCとしてパーティの[3]番目の後ろに追加 NF_NPC削除 1 # [1]番目に追加したNPCを全て削除 NF_REM_NPC 3 # [3]番目に追加したNPCを全て削除 インデックスの指定は追加したNPCとは関係なく、 パーティの並び順(1...バトルメンバー数)を指定してください。 並び順ではなくIDを指定したNPCを削除したい場合、以下のコマンドです。 NF_NPC_ID削除 4 # アクターID[4]のNPCを削除 NF_REM_NPC_ID 4 # 同上 利用規約: 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) についても制限はありません。 このプラグインはもうあなたのものです。 */ (function () { 'use strict'; var pluginName = 'NpcFollower'; var metaTagPrefix = 'NF'; var getCommandName = function (command) { return (command || '').toUpperCase(); }; var getParamOther = function (paramNames) { if (!Array.isArray(paramNames)) paramNames = [paramNames]; for (var i = 0; i < paramNames.length; i++) { var name = PluginManager.parameters(pluginName)[paramNames[i]]; if (name) return name; } return null; }; var getParamBoolean = function (paramNames) { var value = getParamOther(paramNames); return (value || '').toUpperCase() === 'TRUE'; }; var getParamNumber = function (paramNames, min, max) { var value = getParamOther(paramNames); if (arguments.length < 2) min = -Infinity; if (arguments.length < 3) max = Infinity; return (parseInt(value, 10) || 0).clamp(min, max); }; var getArgNumberWithEval = function (arg, min, max) { if (arguments.length < 2) min = -Infinity; if (arguments.length < 3) max = Infinity; return (parseInt(eval(convertEscapeCharacters(arg)), 10) || 0).clamp(min, max); }; var convertEscapeCharacters = function (text) { if (text == null) text = ''; var windowLayer = SceneManager._scene._windowLayer; return windowLayer ? windowLayer.children[0].convertEscapeCharacters(text) : text; }; //============================================================================= // パラメータの取得と整形 //============================================================================= var paramMaxNpcNumber = getParamNumber(['MaxNpcNumber', '最大同時NPC数']); var paramHideNormalFollower = getParamBoolean(['HideNormalFollower', '通常フォロワーを表示しない']); //============================================================================= // Game_Interpreter // プラグインコマンドを追加定義します。 //============================================================================= var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand; Game_Interpreter.prototype.pluginCommand = function (command, args) { _Game_Interpreter_pluginCommand.apply(this, arguments); this.pluginCommandNpcFollower(command.replace(new RegExp(metaTagPrefix, 'i'), ''), args); }; Game_Interpreter.prototype.pluginCommandNpcFollower = function (command, args) { switch (getCommandName(command)) { case '_NPC追加': case '_ADD_NPC': var actorId = getArgNumberWithEval(args[0]); $gameParty.addNpc(actorId, getArgNumberWithEval(args[1], 1)); break; case '_NPC削除': case '_REM_NPC': $gameParty.removeNpc(getArgNumberWithEval(args[0], 1)); break; case '_NPC_ID削除': case '_REM_NPC_ID': var removeActorId = getArgNumberWithEval(args[0]); $gameParty.removeNpcById(removeActorId); } }; //============================================================================= // Game_Party // NPCの追加と削除を追加定義します。 //============================================================================= var _Game_Party_initialize = Game_Party.prototype.initialize; Game_Party.prototype.initialize = function () { _Game_Party_initialize.apply(this, arguments); this.initNpc(); }; Game_Party.prototype.initNpc = function () { this._npcs = []; this._npcIndexes = []; }; Game_Party.prototype.isNpcInvalid = function () { return !this._npcs; }; Game_Party.prototype.initNpcIfNeed = function () { if (this.isNpcInvalid()) { this.initNpc(); $gamePlayer.followers().initNpc(); } }; Game_Party.prototype.addNpc = function (actorId, index) { if (this._npcs.length < paramMaxNpcNumber) { this._npcs.push(actorId); this._npcIndexes.push(index); $gamePlayer.refresh(); $gameMap.requestRefresh(); } else { throw new Error('登録可能な最大数を超えています。'); } }; Game_Party.prototype.removeNpc = function (index) { for (var i = 0, n = this._npcs.length; i < n; i++) { if (this._npcIndexes[i] === index) { this._npcs.splice(i, 1); this._npcIndexes.splice(i, 1); i--; } } $gamePlayer.refresh(); $gameMap.requestRefresh(); }; Game_Party.prototype.removeNpcById = function (id) { for (var i = 0, n = this._npcs.length; i < n; i++) { if (this._npcs[i] === id) { this._npcs.splice(i, 1); this._npcIndexes.splice(i, 1); i--; } } $gamePlayer.refresh(); $gameMap.requestRefresh(); }; Game_Party.prototype.npcMembers = function () { return this._npcs.map(function (id) { return $gameActors.actor(id); }); }; Game_Party.prototype.visibleMembers = function () { return this._visibleMembers; }; Game_Party.prototype.makeVisibleMembers = function () { var battleMembers = this.battleMembers(); var npcMembers = this.npcMembers(); var visibleMembers = []; for (var i = 0, n = this.maxBattleMembers() + 1; i < n; i++) { for (var j = 0, m = npcMembers.length; j < m; j++) { if (this._npcIndexes[j] === i) { visibleMembers.push(npcMembers[j]); } } if (battleMembers.length > i && !paramHideNormalFollower) { visibleMembers.push(battleMembers[i]); } } this._visibleMembers = visibleMembers; }; //============================================================================= // Game_Followers // NPCの最大数ぶんだけ余分にGame_Followerを作成します。 //============================================================================= var _Game_Followers_initialize = Game_Followers.prototype.initialize; Game_Followers.prototype.initialize = function () { _Game_Followers_initialize.apply(this, arguments); if (paramHideNormalFollower) { this._data = []; } this.initNpc(); }; Game_Followers.prototype.initNpc = function () { var memberLength = this._data.length > 0 ? this._data.length + 1 : 0; for (var i = 0; i < paramMaxNpcNumber; i++) { this._data.push(new Game_Follower(memberLength + i)); } }; //============================================================================= // Game_Follower // NPC判定を追加定義します。 //============================================================================= var _Game_Follower_actor = Game_Follower.prototype.actor; Game_Follower.prototype.actor = function () { _Game_Follower_actor.apply(this, arguments); return $gameParty.visibleMembers()[this._memberIndex]; }; //============================================================================= // Game_Player // リフレッシュまえに表示メンバーを更新します。 //============================================================================= var _Game_Player_refresh = Game_Player.prototype.refresh; Game_Player.prototype.refresh = function () { $gameParty.makeVisibleMembers(); _Game_Player_refresh.apply(this, arguments); }; //============================================================================= // DataManager // プラグイン未適用のデータをロードした場合に必要なデータを初期化します。 //============================================================================= var _DataManager_loadGame = DataManager.loadGame; DataManager.loadGame = function (saveFileId) { var result = _DataManager_loadGame.apply(this, arguments); $gameParty.initNpcIfNeed(); return result; }; })();