219 lines
No EOL
7.9 KiB
JavaScript
219 lines
No EOL
7.9 KiB
JavaScript
//=============================================================================
|
||
// RPG Maker MZ - KN_Chest.js
|
||
//=============================================================================
|
||
|
||
/*:ja
|
||
* @target MZ
|
||
* @author kurogoma knights
|
||
* @base PluginCommonBase
|
||
* @plugindesc 宝箱からのアイテム取得
|
||
*
|
||
* @command REGISTER_ITEMS_RED
|
||
* @desc 赤箱アイテム登録
|
||
*
|
||
* @command REGISTER_ITEMS_SILVER
|
||
* @desc 銀箱アイテム登録(スキル)
|
||
*
|
||
* @command REGISTER_ITEMS_GOLD
|
||
* @desc 金箱アイテム登録(遺物)
|
||
*
|
||
* @command REGISTER_ITEMS_DEBUG
|
||
* @desc デバッグ用
|
||
* @arg itemIds @type item[]
|
||
*
|
||
* @command PREPARE_ITEM_CHOICES
|
||
* @desc 変数1-3にID、4-6に説明を設定
|
||
*
|
||
* @command GAIN_SELECTED_ITEM
|
||
* @desc 選択アイテム取得
|
||
*
|
||
* @command GAIN_RANDOM_ITEM_BY_WEIGHT
|
||
* @desc 重み付きランダム取得(赤箱用)
|
||
*
|
||
* @command GAIN_RANDOM_UNOWNED_ITEM
|
||
* @desc 未所持をランダム取得、なければお金(銀箱金箱用)
|
||
*/
|
||
|
||
(() => {
|
||
'use strict';
|
||
const script = document.currentScript;
|
||
|
||
let _items = [];
|
||
|
||
//=========================================================================
|
||
// ユーティリティ
|
||
//=========================================================================
|
||
|
||
// 現在フロア取得
|
||
function getCurrentFloor() {
|
||
return window.Kurogoma?.floorManager?.currentFloor ?? 0;
|
||
}
|
||
|
||
// フロア出現チェック
|
||
function canAppearOnFloor(item, floor) {
|
||
const startFloor = Number(item.meta['出現開始フロア'] ?? 0);
|
||
return startFloor === 0 || floor >= startFloor;
|
||
}
|
||
|
||
// スキルタイプ判定
|
||
function isActiveSkill(item) {
|
||
return item?.meta?.['スキルタイプ'] === 'アクティブ';
|
||
}
|
||
|
||
// 所持数取得
|
||
// パッシブ:そのアイテムのみカウント
|
||
// アクティブ:強化前後を合算(どちらか片方しか持てない)
|
||
function getOwnedCount(item) {
|
||
let count = $gameParty.numItems(item);
|
||
|
||
// アクティブスキルは強化前後を合算
|
||
if (isActiveSkill(item) && item.id % 2 === 0) {
|
||
const evolved = $dataItems[item.id + 1];
|
||
if (evolved) count += $gameParty.numItems(evolved);
|
||
}
|
||
return count;
|
||
}
|
||
|
||
// 所持制限チェック
|
||
function canObtainMore(item) {
|
||
const limit = Number(item.meta['所持制限'] ?? 1);
|
||
const owned = getOwnedCount(item);
|
||
return owned < limit;
|
||
}
|
||
|
||
// 通知付きアイテム取得
|
||
function gainItemWithNotify(item) {
|
||
Torigoya.NotifyMessage.Manager.notify(
|
||
new Torigoya.NotifyMessage.NotifyItem({
|
||
message: "Obtained " + item.name + "!",
|
||
icon: item.iconIndex
|
||
})
|
||
);
|
||
$gameParty.gainItem(item, 1);
|
||
}
|
||
|
||
// 通知付きお金取得
|
||
function gainGoldWithNotify(amount) {
|
||
Torigoya.NotifyMessage.Manager.notify(
|
||
new Torigoya.NotifyMessage.NotifyItem({
|
||
message: `Obtained ${amount}G!`
|
||
})
|
||
);
|
||
$gameParty.gainGold(amount);
|
||
}
|
||
|
||
// 配列シャッフル
|
||
function shuffle(array) {
|
||
return [...array].sort(() => Math.random() - 0.5);
|
||
}
|
||
|
||
//=========================================================================
|
||
// アイテム候補フィルタ
|
||
//=========================================================================
|
||
|
||
// 基本フィルタ(カテゴリ、出現率、フロア)
|
||
function filterItems(category, floor, extraCondition = () => true) {
|
||
return $dataItems.filter(item => {
|
||
if (!item?.name) return false;
|
||
if (item.meta['SGカテゴリ'] !== category) return false;
|
||
if (Number(item.meta['宝箱出現率'] ?? 0) <= 0) return false;
|
||
if (!canAppearOnFloor(item, floor)) return false;
|
||
return extraCondition(item);
|
||
});
|
||
}
|
||
|
||
// 所持制限で絞り込み&シャッフル(最大3個)
|
||
function selectAvailable(items) {
|
||
const available = items.filter(item => canObtainMore(item));
|
||
// debugLog(items, available);
|
||
return shuffle(available).slice(0, 3);
|
||
}
|
||
|
||
//=========================================================================
|
||
// デバッグログ
|
||
//=========================================================================
|
||
|
||
function debugLog(candidates, available) {
|
||
console.log(`候補:${candidates.length} → 取得可能:${available.length}`);
|
||
|
||
// 所持状況
|
||
const owned = {};
|
||
$gameParty.allItems().forEach(item => {
|
||
const count = $gameParty.numItems(item);
|
||
if (count > 0) owned[item.name] = count;
|
||
});
|
||
console.log('所持:', owned);
|
||
|
||
// 判定結果
|
||
console.log(candidates.map(item => {
|
||
const limit = Number(item.meta['所持制限'] ?? 1);
|
||
const count = getOwnedCount(item);
|
||
const type = isActiveSkill(item) ? 'アクティブ' : 'パッシブ';
|
||
return ` ${item.name}[${type}]: ${count}/${limit} ${count < limit ? '○' : '×'}`;
|
||
}).join('\n'));
|
||
}
|
||
|
||
//=========================================================================
|
||
// コマンド:アイテム登録
|
||
//=========================================================================
|
||
|
||
// 赤箱(消費アイテム)
|
||
PluginManagerEx.registerCommand(script, "REGISTER_ITEMS_RED", args => {
|
||
const floor = getCurrentFloor();
|
||
_items = filterItems('Item', floor);
|
||
});
|
||
|
||
// 銀箱(スキル:偶数ID=強化前のみ)
|
||
PluginManagerEx.registerCommand(script, "REGISTER_ITEMS_SILVER", args => {
|
||
const floor = getCurrentFloor();
|
||
const candidates = filterItems('Skill', floor, item => item.id % 2 === 0);
|
||
_items = selectAvailable(candidates);
|
||
});
|
||
|
||
// 金箱(遺物)
|
||
PluginManagerEx.registerCommand(script, "REGISTER_ITEMS_GOLD", args => {
|
||
const floor = getCurrentFloor();
|
||
const candidates = filterItems('Relic', floor);
|
||
_items = selectAvailable(candidates);
|
||
});
|
||
|
||
//=========================================================================
|
||
// コマンド:アイテム取得
|
||
//=========================================================================
|
||
|
||
// 重み付きランダム取得(赤箱用)
|
||
PluginManagerEx.registerCommand(script, "GAIN_RANDOM_ITEM_BY_WEIGHT", function(args) {
|
||
const weighted = [];
|
||
for (const item of _items) {
|
||
const weight = Number(item.meta['宝箱出現率'] ?? 0);
|
||
for (let i = 0; i < weight; i++) weighted.push(item);
|
||
}
|
||
if (weighted.length === 0) return;
|
||
gainItemWithNotify(weighted[Math.floor(Math.random() * weighted.length)]);
|
||
});
|
||
|
||
// 選択肢準備
|
||
PluginManagerEx.registerCommand(script, "PREPARE_ITEM_CHOICES", args => {
|
||
for (let i = 0; i < 3; i++) {
|
||
const item = _items[i];
|
||
$gameVariables.setValue(1 + i, item?.id ?? 0);
|
||
$gameVariables.setValue(4 + i, item ? '\\FS[18]' + item.description : "");
|
||
}
|
||
});
|
||
// &選択アイテム取得
|
||
PluginManagerEx.registerCommand(script, "GAIN_SELECTED_ITEM", function(args) {
|
||
const index = this._branch[this._indent];
|
||
if (index < 0 || !_items[index]) return;
|
||
gainItemWithNotify(_items[index]);
|
||
});
|
||
|
||
// 未所持ランダム取得(銀箱金箱用)
|
||
PluginManagerEx.registerCommand(script, "GAIN_RANDOM_UNOWNED_ITEM", function(args) {
|
||
if (_items.length === 0) {
|
||
gainGoldWithNotify(1000);
|
||
} else {
|
||
gainItemWithNotify(_items[Math.floor(Math.random() * _items.length)]);
|
||
}
|
||
});
|
||
|
||
})(); |