Skip to content

Instantly share code, notes, and snippets.

@f-space
Last active Mar 19, 2019
Embed
What would you like to do?
不思議のダンジョン風のUIをマップ画面に表示するRPGツクールMVプラグイン
/*:
* @plugindesc マップ画面上にステータスを表示する
* @author F_
*
* @param horizontal_margin
* @desc 横方向の余白(px)
* @default 50
*
* @param vertical_margin
* @desc 縦方向の余白(px)
* @default 20
*
* @param floor_unit
* @desc 階層の単位
* @default F
*
* @param separator
* @desc 現在値と最大値の仕切り
* @default /
*
* @param max_floor
* @desc 最大階層
* @default 99
*
* @param max_level
* @desc 最大レベル
* @default 99
*
* @param max_hp
* @desc 最大HP
* @default 999
*
* @param max_gold
* @desc 最大ゴールド
* @default 999999
*
* @param gauges
* @desc 描画するゲージ一覧(コンマ区切りで記述 [exp, hp, mp])
* @default exp, hp, mp
*
* @help
* XXX階と表示するにはマップのメモ欄に<floor:XXX>と記述します。
*
* Copyright (c) 2019 F_
* Released under the MIT license
* http://opensource.org/licenses/mit-license.php
*/
!function () {
const PLUGIN_NAME = document.currentScript.src.split("/").pop().slice(0, -3);
const PARAMS = PluginManager.parameters(PLUGIN_NAME);
function positiveInteger(name) {
const value = Number(PARAMS[name]);
if (!Number.isSafeInteger(value) || value < 0) {
throw new Error(`parameter '${name}' must be a positive integer.`);
}
return value;
}
const params = {
horizontalMargin: Number(PARAMS['horizontal_margin']),
verticalMargin: Number(PARAMS['vertical_margin']),
floorUnit: String(PARAMS['floor_unit']),
separator: String(PARAMS['separator']),
maxFloor: positiveInteger('max_floor'),
maxLevel: positiveInteger('max_level'),
maxHp: positiveInteger('max_hp'),
maxGold: positiveInteger('max_gold'),
gauges: String(PARAMS['gauges']).split(",").map(x => x.trim().toLowerCase()),
};
class InfoWindow extends Window_Base {
constructor(...args) {
super(...args);
}
initialize() {
super.initialize(0, 0, this.windowWidth(), this.windowHeight());
this.opacity = 0;
this._values = {};
}
windowWidth() {
return Graphics.boxWidth;
}
windowHeight() {
return this.fittingHeight(1)
+ (this.gaugeSpacing() + this.gaugeHeight()) * 2
+ params.verticalMargin * 2;
}
standardFontSize() {
return 42;
}
standardPadding() {
return 0;
}
textPadding() {
return 8;
}
update() {
super.update();
const map = $dataMap;
const floorTag = Number(map && map.meta['floor']);
const actor = $gameParty.leader();
const floor = !Number.isNaN(floorTag) ? floorTag.clamp(0, params.maxFloor) : undefined;
const level = actor.level.clamp(0, params.maxLevel);
const hp = actor.hp.clamp(0, params.maxHp);
const mhp = actor.mhp.clamp(0, params.maxHp);
const mp = actor.mp;
const mmp = actor.mmp;
const exp = actor.isMaxLevel() ? 0 : actor.currentExp() - actor.currentLevelExp();
const mexp = actor.nextLevelExp() - actor.currentLevelExp();
const gold = $gameParty.gold();
const values = { floor, level, hp, mhp, mp, mmp, exp, mexp, gold };
const dirty = Object.entries(values).some(([k, v]) => v !== this._values[k]);
if (dirty) {
this._values = values;
this.refresh();
}
}
refresh() {
this.contents.clear();
const layout = this.measureInfoText();
this.drawInfoText(layout);
}
gaugeSpacing() {
return 4;
}
gaugeHeight() {
return 8;
}
measureInfoText() {
const offsetX = params.horizontalMargin;
const offsetY = params.verticalMargin;
const floorWidth = this.measureFloorText();
const levelWidth = this.measureLevelText();
const hpWidth = this.measureHPText();
const goldWidth = this.measureGoldText();
const width = this.contents.width;
const totalWidth = floorWidth + levelWidth + hpWidth + goldWidth;
const totalSpace = width - totalWidth - params.horizontalMargin * 2;
const spacing = Math.round(totalSpace / 3);
return { offsetX, offsetY, floorWidth, levelWidth, hpWidth, goldWidth, spacing };
}
measureFloorText() {
const digits = this.getDigits(params.maxFloor);
let width = 0;
width += this.measureNumberText(digits);
width += this.textPadding();
width += this.textWidth(params.floorUnit);
return width;
}
measureLevelText() {
const digits = this.getDigits(params.maxLevel)
let width = 0;
width += this.textWidth(TextManager.levelA);
width += this.textPadding();
width += this.measureNumberText(digits);
return width;
}
measureHPText() {
const digits = this.getDigits(params.maxHp);
let width = 0;
width += this.textWidth(TextManager.hpA);
width += this.textPadding();
width += this.measureNumberText(digits) * 2;
width += this.textWidth(params.separator);
return width;
}
measureGoldText() {
const digits = this.getDigits(params.maxGold);
let width = 0;
width += this.measureNumberText(digits);
width += this.textPadding();
width += this.textWidth(TextManager.currencyUnit);
return width;
}
measureNumberText(length) {
return this.textWidth('0') * length;
}
drawInfoText(layout) {
const { offsetX, offsetY } = layout;
const lineHeight = this.lineHeight() + this.gaugeSpacing();
const gaugeHeight = this.gaugeHeight() + this.gaugeSpacing();
const floorX = offsetX;
const floorY = offsetY;
this.drawFloorText(floorX, floorY, layout.floorWidth);
const levelX = floorX + layout.floorWidth + layout.spacing;
const levelY = offsetY;
this.drawLevelText(levelX, levelY, layout.levelWidth);
if (params.gauges.includes('exp')) {
const expGaugeX = levelX;
const expGaugeY = levelY + lineHeight;
this.drawExpGauge(expGaugeX, expGaugeY, layout.levelWidth);
}
const hpX = levelX + layout.levelWidth + layout.spacing;
const hpY = offsetY;
this.drawHPText(hpX, hpY, layout.hpWidth);
let gaugeY = hpY + lineHeight;
if (params.gauges.includes('hp')) {
const hpGaugeX = hpX;
const hpGaugeY = gaugeY;
this.drawHPGauge(hpGaugeX, hpGaugeY, layout.hpWidth);
gaugeY += gaugeHeight;
}
if (params.gauges.includes('mp')) {
const mpGaugeX = hpX;
const mpGaugeY = gaugeY;
this.drawMPGauge(mpGaugeX, mpGaugeY, layout.hpWidth);
gaugeY += gaugeHeight;
}
const goldX = hpX + layout.hpWidth + layout.spacing;
const goldY = offsetY;
this.drawGoldText(goldX, goldY, layout.goldWidth);
}
drawFloorText(x, y, width) {
const { floor } = this._values;
const digits = this.getDigits(params.maxFloor);
if (floor !== undefined) {
const text0 = String(floor).padStart(digits);
const text1 = params.floorUnit;
const width0 = this.textWidth(text0);
const width1 = this.textWidth(text1);
const padding = this.textPadding();
this.drawText(text0, x, y, width0, 'left');
this.drawText(text1, x + width0 + padding, y, width1, 'left');
}
}
drawLevelText(x, y, width) {
const { level } = this._values;
const digits = this.getDigits(params.maxLevel);
const text0 = TextManager.levelA;
const text1 = String(level).padStart(digits);
const width0 = this.textWidth(text0);
const width1 = this.textWidth(text1);
const padding = this.textPadding();
this.drawText(text0, x, y, width0, 'left');
this.drawText(text1, x + width0 + padding, y, width1, 'left');
}
drawExpGauge(x, y, width) {
const { exp, mexp } = this._values;
const rate = mexp !== 0 ? (exp / mexp).clamp(0, 1) : 1;
const color1 = this.tpGaugeColor1();
const color2 = this.tpGaugeColor2();
this.drawGauge(x, y, width, rate, color1, color2);
}
drawHPText(x, y, width) {
const { hp, mhp } = this._values;
const digits = this.getDigits(params.maxHp);
const text0 = TextManager.hpA;
const text1 = String(hp).padStart(digits) + params.separator + String(mhp).padStart(digits);
const width0 = this.textWidth(text0);
const width1 = this.textWidth(text1);
const padding = this.textPadding();
this.drawText(text0, x, y, width0, 'left');
this.drawText(text1, x + width0 + padding, y, width1, 'left');
}
drawHPGauge(x, y, width) {
const { hp, mhp } = this._values;
const rate = mhp !== 0 ? (hp / mhp).clamp(0, 1) : 0;
const color1 = this.hpGaugeColor1();
const color2 = this.hpGaugeColor2();
this.drawGauge(x, y, width, rate, color1, color2);
};
drawMPGauge(x, y, width) {
const { mp, mmp } = this._values;
const rate = mmp !== 0 ? (mp / mmp).clamp(0, 1) : 0;
const color1 = this.mpGaugeColor1();
const color2 = this.mpGaugeColor2();
this.drawGauge(x, y, width, rate, color1, color2);
}
drawGoldText(x, y, width) {
const { gold } = this._values;
const digits = this.getDigits(params.maxGold);
const text0 = String(gold).padStart(digits);
const text1 = TextManager.currencyUnit;
const width0 = this.textWidth(text0);
const width1 = this.textWidth(text1);
const padding = this.textPadding();
this.drawText(text0, x, y, width0, 'left');
this.drawText(text1, x + width0 + padding, y, width1, 'left');
}
drawGauge(x, y, width, rate, color1, color2) {
const filledAreaWidth = Math.floor(width * rate);
const height = this.gaugeHeight();
const background = this.gaugeBackColor();
this.contents.fillRect(x, y, width, height, background);
this.contents.gradientFillRect(x, y, filledAreaWidth, height, color1, color2);
}
getDigits(x) {
return x !== 0 ? Math.floor(Math.log10(x)) + 1 : 1;
}
}
const Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
Scene_Map.prototype.createAllWindows = function () {
Scene_Map_createAllWindows.apply(this, arguments);
this.createInfoWindow();
}
Scene_Map.prototype.createInfoWindow = function () {
this._infoWindow = new InfoWindow();
this.addWindow(this._infoWindow);
}
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment