magical-girls-runa-and-nanami/js/plugins/ShopScene_Extension_HPMP.js
2026-02-28 12:33:13 -06:00

138 lines
5.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.

/*:
* @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;
};
// 右側の描画も既存の仕組みでOKnewEquipValue を差し替えたので%補正が反映される)
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);
}
};
})();