RPGツクールMV

YEP_ItemCoreが競合する時の対策方法

RPGツクールMVのアイテム合成プラグインRTK_CompositeとYEP_ItemCoreが競合していたのを自力で対応してみました。

RTK_Core.jsの185行目付近にある RTK.hasId を修正。

RTK1_Core.js
(C) Toshio Yamashita (yamachan)

RTK.hasId = function(_id, _n) {
	_n = _n||1;
	if ("string" == typeof _id) {
		var a = _id.match(/^\s*([aiw])(\d+)\s*$/i);
		if (a) {
			var list = a[1] == "i" ? $gameParty._items : a[1] == "w" ? $gameParty._weapons : $gameParty._armors;
			var n = list[Number(a[2])];
			
			// YEP_ItemCoreのアイテム数を数える
			// nがundefinedだと足せないので0に変換
			if(n == null){
			    n = 0;
			}
			
			var itemList = a[1] == "i" ? $gameParty.items() : a[1] == "w" ? $gameParty.weapons() : $gameParty.armors();
			n += RTK.getIndependentItemCount(Number(a[2]),itemList);
			
			return n >= _n ? n : 0;
		}
	}
	return 0;
};

// YEP_ItemCore.js対策
var Imported = Imported || {};
RTK.getIndependentItemCount = function(itemId, list){
    var matchList = [];
    if(Imported.YEP_ItemCore){
        matchList = list.filter(function(item){
            return item.id > Yanfly.Param.ItemStartingId && item.baseItemId === itemId;
        });
    }
    return matchList.length;
}

RTK1_Composite.jsWindow_CompositeIndex.prototype.drawItem を修正。

RTK1_Composite.js
(C) Toshio Yamashita (yamachan)

    Window_CompositeIndex.prototype.drawItem = function(index) {
	var item = M._list[index];
	var rect = this.itemRect(index);
	var width = rect.width - this.textPadding();

	item[NK] = _convert(item);

	// YEP_ItemCoreを入れていると同じアイテムが重複して表示されるのを防ぐ
	if(Imported.YEP_ItemCore){
	    M._list = M._list.filter(function(item){
		return item.id <= Yanfly.Param.ItemStartingId;
	    });
	}	

	if (item[NK].f) {
	    this.drawItemName(item, rect.x, rect.y, width);
	} else {
	    this.changePaintOpacity(false);
	    this.drawItemName(item, rect.x, rect.y, width);
	    this.changePaintOpacity(true);
	}
    };

RTK_Compositeに限らずほかのアイテム系のプラグインとも競合しやすいと思うので、プラグイン製作者向けにYEP_ItemCoreの仕組みと競合した時のプラグインの修正方法を解説してみます。

YEP_ItemCoreの仕組み

YEP_ItemCoreは、アイテム系の拡張機能がつめこまれたプラグインです。

通常スタックできるアイテムをまとめて持てないようにして所持数に制限をかけることができたり、元が同じだけど能力値が微妙に違う装備が作れたりします。

いろいろと便利なのですが、YEP_ItemCoreを入れるとアイテムのidプロパティがデフォルトと変わります

そのため、idからアイテムオブジェクトを取得する処理が入っているプラグインと競合する可能性が高いです。

ふつう、アイテムのidはデータベースのIDの数値が入っています。
RPGツクールMV アイテムのID

YEP_ItemCoreを入れている状態だと、武器・防具のidはYEP_ItemCoreのプラグインパラメータStarting ID + 1番から連番でつけられます。

(装備以外のアイテムについては後述)

YEP_ItemCoreのStarting IDが3000(デフォルト)の時にid1の剣を2個手に入れると、idが3001の剣とidが3002の剣が手に入ります。

元となった装備のidはアイテムオブジェクトの baseItemId プロパティに代入されています。

剣のイラストid: 3001
baseItemId: 1
剣のイラストid: 3002
baseItemId: 1

baseItemIdはYEP_ItemCore側でアイテムオブジェクトに追加している独自のプロパティなので、YEP_ItemCoreを入れていない状態で参照するとundefinedが返ります。

ほかのプラグインからアイテムを持っているか判定をするとき、アイテムのidを使って判定を行うことが多いです。

しかしid1の武器を持っているか判定しようとしても、パーティの所持品にあるのはidが1ではないため「アイテムを持っていない」という風に判定されてしまいます。

そのため、YEP_ItemCoreが読み込まれている状態で所持判定をする場合はアイテムのidがStarting IDより大きく、baseItemIdが元のアイテムidのものも取得する必要があります。

装備以外のアイテムはデフォルトの状態ではidは変わらず、同種のアイテムはまとめられます。

ただしYEP_ItemCoreのプラグインパラメータ Max Items を設定している場合、装備と同じくidが変わります。

そのため、アイテムについても baseItemId でチェックした方がよいです。

対策が必要なのは、おもにアイテムの所持判定とアイテムを列挙する場合です。

アイテムを入手したり、減らしたりする場合はYEP_ItemCore側でidを変換してくれます。
ふつうに元のアイテムidを指定すればOKなので、特に気にする必要はありません。

ちなみにbaseItemIdが1の剣を2つ持っていて、id1の剣を減らした場合はidの小さい方から消えます。(idが3001と3002だったら、3001の方が消える)

<余談>

初期装備の武器は2回アイテムが生成され、あとの方の番号を装備しています。
防具は武器とは別に Starting ID + 1から連番になります。

初期装備がid1の剣とid1の鎧の場合、ゲーム開始時にid3001の剣、id3002の剣、id3001の鎧が作成されます。

アクターはid3002の剣とid3001の鎧を装備しています。

YEP_ItemCoreが読み込まれているか判定する

YEP_ItemCoreが読み込まれているかどうかは以下の方法で判定できます。

まず、即時関数の外(グローバル変数)で変数Importedを宣言します。

初期値はすでにImportedに値が入っている場合はImportedの値、undefinedの場合は空のオブジェクトです。

var Imported = Imported || {};

つぎに、YEP_ItemCoreが読み込まれているかで処理を分岐します。

YEP_ItemCoreが読み込まれている場合Imported.YEP_ItemCore はtrue、読み込まれていなければundefinedを返します。

if(Imported.YEP_ItemCore){
    // YEP_ItemCoreが入っている時の処理    
}

Starting IDの値は、 Yanfly.Param.ItemStartingId で取得できます。

YEP_ItemCoreが競合する時の対策方法まとめ

まとめ
  1. グローバル変数Importedを宣言
  2. YEP_ItemCoreが読み込まれているかチェック
  3. 読み込まれていたらアイテムのidとbaseItemIdで判定する

YEP_ItemCoreのIDの仕組みがわかっていれば対処はそれほど難しくないので、アイテム系プラグインを作成している人は対策を検討してもらえると嬉しいです。