138 lines
5.9 KiB
JavaScript
138 lines
5.9 KiB
JavaScript
/*:
|
||
* @target MZ
|
||
* @plugindesc [改良版] ショップ画面拡張 + HP/MP比較 + 装備%補正(特徴)を新値に反映
|
||
* @author you
|
||
*
|
||
* @help
|
||
* 右側の新値(→の右)は、装備の固定加算(params)に加え、
|
||
* 防具/武器の「特徴」(Traits: PARAM) による%補正も掛け合わせた
|
||
* 最終実数値を表示します。
|
||
* 例:防具に「最大HP×105%」がある場合、装備後HPは1.05倍で表示。
|
||
*
|
||
* 既存の ShopScene_Extension v1.0.5 の下に配置してください。
|
||
*/
|
||
|
||
(() => {
|
||
"use strict";
|
||
|
||
/** ───────── ユーティリティ(装備による加算/倍率の分解) ───────── **/
|
||
|
||
// 装備配列から、params 加算合計を取得
|
||
function sumEquipParams(equips, paramId) {
|
||
return equips.reduce((sum, it) => {
|
||
return sum + (it && it.params ? (it.params[paramId] || 0) : 0);
|
||
}, 0);
|
||
}
|
||
|
||
// 装備配列から、Traits: PARAM の倍率(乗算)を取得
|
||
function prodEquipParamRate(equips, paramId) {
|
||
// Game_BattlerBase の定数に合わせた code
|
||
const TRAIT_PARAM = Game_BattlerBase.TRAIT_PARAM; // 通常は 21
|
||
return equips.reduce((prod, it) => {
|
||
if (!it || !it.traits) return prod;
|
||
const r = it.traits.reduce((p, tr) => {
|
||
return p * (tr.code === TRAIT_PARAM && tr.dataId === paramId ? tr.value : 1);
|
||
}, 1);
|
||
return prod * r;
|
||
}, 1);
|
||
}
|
||
|
||
// 指定アクターの「非装備由来」の加算・倍率を算出(=現在から装備分を差し引く)
|
||
function decomposeNonEquipPart(actor, paramId) {
|
||
const equips = actor.equips();
|
||
const plusAll = actor.paramPlus(paramId); // 装備を含む全加算
|
||
const plusEquips = sumEquipParams(equips, paramId); // 装備由来の加算
|
||
const rateAll = actor.paramRate(paramId); // 装備を含む全倍率(Traits総積)
|
||
const rateEquips = prodEquipParamRate(equips, paramId); // 装備由来の倍率(Traits PARAM のみ)
|
||
const nonEquipPlus = plusAll - plusEquips; // 装備以外の加算
|
||
const nonEquipRate = rateEquips !== 0 ? (rateAll / rateEquips) : rateAll; // 装備以外の倍率
|
||
return { nonEquipPlus, nonEquipRate };
|
||
}
|
||
|
||
// 仮想的に「old 装備 → new 装備」に差し替えたときの装備配列を作る
|
||
function virtualEquips(actor, newItem, oldItem) {
|
||
const equips = actor.equips().slice();
|
||
if (!newItem && !oldItem) return equips;
|
||
|
||
// 差し替え対象スロットを特定
|
||
let slotIndex = -1;
|
||
|
||
if (oldItem) {
|
||
// 現在装備している oldItem のスロットを探す
|
||
slotIndex = equips.findIndex(e => e && e.objectId === oldItem.objectId && e.etypeId === oldItem.etypeId);
|
||
// objectId 無いDBでは id で同定
|
||
if (slotIndex < 0) slotIndex = equips.findIndex(e => e && e.id === oldItem.id && e.etypeId === oldItem.etypeId);
|
||
}
|
||
|
||
if (slotIndex < 0 && newItem) {
|
||
// newItem の etypeId に合うスロットを探す(最初に見つかった箇所)
|
||
const etypeId = newItem.etypeId;
|
||
const slots = actor.equipSlots();
|
||
slotIndex = slots.findIndex(s => s === etypeId);
|
||
// 既に同スロットに何か入っている場合も素直に置き換える
|
||
if (slotIndex < 0) slotIndex = 0; // 念のため
|
||
}
|
||
|
||
if (slotIndex >= 0) {
|
||
equips[slotIndex] = newItem || null; // new を入れる(外す場合は null)
|
||
}
|
||
return equips;
|
||
}
|
||
|
||
/** ───────── ここから表示ロジックの上書き/拡張 ───────── **/
|
||
|
||
// 8パラメータ(HP/MP含む)を描画
|
||
const _drawAllParams = Window_ShopStatus.prototype.drawAllParams;
|
||
Window_ShopStatus.prototype.drawAllParams = function(x, y) {
|
||
for (let i = 0; i <= 7; i++) {
|
||
this.drawItem(x, y, i);
|
||
y += this.lineHeight();
|
||
}
|
||
};
|
||
|
||
// 「右側の新値」を、装備の固定加算+Traits倍率を反映した最終値で計算
|
||
Window_ShopStatus.prototype.newEquipValue = function(actor, paramId, newItem, oldItem) {
|
||
// 現在の装備のうち「装備由来以外」の加算/倍率をまず取り出す
|
||
const { nonEquipPlus, nonEquipRate } = decomposeNonEquipPart(actor, paramId);
|
||
|
||
// 差し替え後の仮想装備リストを作る
|
||
const vEquips = virtualEquips(actor, newItem, oldItem);
|
||
|
||
// 仮想装備由来の加算&倍率
|
||
const plusEquips = sumEquipParams(vEquips, paramId);
|
||
const rateEquips = prodEquipParamRate(vEquips, paramId);
|
||
|
||
// ベース値(職業・レベル等)
|
||
const base = actor.paramBase(paramId);
|
||
// バフ(ショップ中は通常0だが、残っていても左/右で整合が取れるよう適用)
|
||
const buffRate = actor.paramBuffRate(paramId);
|
||
|
||
// 公式計算式に近い形で算出(非装備と装備の合成)
|
||
// 注:MZの内部実装と小数点処理の順序が完全一致しないケースもありますが、
|
||
// 実用上ほぼ一致するようにしています。
|
||
let value = (base) * (nonEquipRate * rateEquips) + (nonEquipPlus + plusEquips);
|
||
value = Math.floor(value * buffRate);
|
||
|
||
// 最小/最大クリップ
|
||
value = value.clamp(actor.paramMin(paramId), actor.paramMax(paramId));
|
||
return value;
|
||
};
|
||
|
||
// 右側の描画も既存の仕組みでOK(newEquipValue を差し替えたので%補正が反映される)
|
||
const _drawNewParam = Window_ShopStatus.prototype.drawNewParam;
|
||
Window_ShopStatus.prototype.drawNewParam = function(x, y, paramId) {
|
||
const paramWidth = this.paramWidth();
|
||
if (this._actor.canEquip(this._item)) {
|
||
const newValue = this.newEquipValue(this._actor, paramId, this._item, this._currentEquippedItem);
|
||
const diff = newValue - this._actor.param(paramId);
|
||
this.changeTextColor(ColorManager.paramchangeTextColor(diff));
|
||
this.drawText(newValue, x, y, paramWidth, "right");
|
||
} else {
|
||
this.resetTextColor();
|
||
this.changePaintOpacity(false);
|
||
this.drawText("--", x, y, paramWidth, "right");
|
||
this.changePaintOpacity(true);
|
||
}
|
||
};
|
||
|
||
})();
|