divagate/www/js/plugins/NpcFollower.js
2023-08-31 14:59:34 -05:00

294 lines
12 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// NpcFollower.js
// ----------------------------------------------------------------------------
// (C) 2016 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 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/
//=============================================================================
/*:
* @plugindesc NPC Follower plugin
* @author triacontane
*
* @param MaxNpcNumber
* @desc 同時に隊列に存在できるNPCの最大数です。
* @default 1
*
* @param HideNormalFollower
* @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...バトルメンバー数)を指定してください。
*
* This plugin is released under the MIT License.
*/
/*: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...バトルメンバー数)を指定してください。
*
* 利用規約:
* 作者に無断で改変、再配布が可能で、利用形態商用、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;
}
};
//=============================================================================
// 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.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;
};
})();