nyacronomicon/js/plugins/KN_Chest.js
2026-03-18 01:22:55 -05:00

219 lines
No EOL
7.9 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.

//=============================================================================
// 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)]);
}
});
})();