983 lines
35 KiB
JavaScript
983 lines
35 KiB
JavaScript
//=============================================================================
|
|
// RPG Maker MZ - SceneLewdStatus
|
|
//
|
|
// Copyright 2024 Panzer-IV. All rights reserved.
|
|
// This source code or any portion thereof must not be
|
|
// reproduced or used without licensed in any manner whatsoever.
|
|
//=============================================================================
|
|
/*:
|
|
* @target MZ
|
|
* @plugindesc みんぱぶエロステ画面プラグイン
|
|
* @author 四号戦車
|
|
* @base PluginCommonBase
|
|
* @base DebugSwitch
|
|
* @base TextResource
|
|
* @base PluginUtils
|
|
* @orderAfter PluginCommonBase
|
|
* @orderAfter DebugSwitch
|
|
* @orderAfter TextResource
|
|
* @orderAfter PluginUtils
|
|
*
|
|
* @param bgm
|
|
* @text シーンのBGM
|
|
* @desc シーン中再生するBGMを指定します。
|
|
* @type file
|
|
* @dir audio/bgm
|
|
* @default
|
|
*
|
|
* @param lewdLevel1
|
|
* @text 勇者レベル
|
|
* @desc エロステ値を管理する変数を指定して下さい。
|
|
* @type variable
|
|
* @default 0
|
|
*
|
|
* @param lewdLevel2
|
|
* @text 娼婦レベル
|
|
* @desc エロステ値を管理する変数を指定して下さい。
|
|
* @type variable
|
|
* @default 0
|
|
*
|
|
* @param playerActor
|
|
* @text プレイヤー
|
|
* @desc レベル表示するプレイヤーを指定します
|
|
* @type actor
|
|
* @default 0
|
|
*
|
|
* @param lewdStage
|
|
* @text エロステ段階の変数
|
|
* @desc エロステ段階を管理する変数を指定してください
|
|
* @type variable
|
|
* @default 0
|
|
*
|
|
* @param comment
|
|
* @text 備考欄
|
|
* @desc プラグイン側では使用しません。
|
|
* メモ欄としてお使いください。
|
|
* @type multiline_string
|
|
* @default
|
|
*
|
|
* @requiredAssets img/system/lewd_status/background
|
|
* @requiredAssets img/system/lewd_status/back_button
|
|
* @requiredAssets img/system/lewd_status/frame
|
|
* @requiredAssets img/system/lewd_status/body_mask
|
|
* @requiredAssets img/system/lewd_status/body/stage_1
|
|
* @requiredAssets img/system/lewd_status/body/stage_2
|
|
* @requiredAssets img/system/lewd_status/body/stage_3
|
|
* @requiredAssets img/system/lewd_status/body/stage_4
|
|
* @requiredAssets img/system/lewd_status/body_background
|
|
*
|
|
* @help SceneLewdStatus.js
|
|
*
|
|
* Version: 0.0.2
|
|
*
|
|
* エロステ画面プラグイン
|
|
*
|
|
* @command startScene
|
|
* @text エロステ画面表示
|
|
* @desc エロステ画面を表示します
|
|
*
|
|
*/
|
|
(() => {
|
|
"use strict";
|
|
|
|
//========================================================================
|
|
// プラグイン定義
|
|
//========================================================================
|
|
const pluginName = "SceneLewdStatus";
|
|
const script = document.currentScript;
|
|
const param = PluginUtils.reparseParameter(script);
|
|
|
|
//========================================================================
|
|
// 定数定義
|
|
//========================================================================
|
|
const UI_AREA_X = 7;
|
|
const UI_AREA_Y = 0;
|
|
|
|
const LEWD_LEVEL_WIDTH = 260;
|
|
const LEWD_LEVEL_HEIGHT = 58;
|
|
const LEWD_LEVEL_MERGIN = 12;
|
|
|
|
const TITLE_TEXT = "0900-003-n003-0"; // 画面タイトル
|
|
const SYSTEM_LEWD_VALUE1 = "0900-030-n030-0"; // ゲージタイトル(勇者レベル)
|
|
const SYSTEM_LEWD_VALUE2 = "0900-031-n031-0"; // ゲージタイトル(娼婦レベル)
|
|
const SYSTEM_TOTAL_LEBEL = "0900-033-n033-0"; // ラベル(総合レベル)
|
|
|
|
const ITEM_WIDTH = 518;
|
|
const ITEM_HEIGHT = 60;
|
|
const ITEM_MERGIN = 8;
|
|
|
|
const CONTENT_AREA_WIDTH = 682;
|
|
const CONTENT_AREA_HEIHGT = 670;
|
|
|
|
const DESCRIPTION_LINE_HEIGHT = 40;
|
|
const DESCRIPTION_MERGIN = 18;
|
|
const CONTENT_LINE_WIDTH = 3;
|
|
|
|
const CONTENT_TOP = 134;
|
|
|
|
//========================================================================
|
|
// Helpers (word wrapping for English)
|
|
//========================================================================
|
|
/**
|
|
* Wrap text into multiple lines so that each line fits within maxWidth (in pixels)
|
|
* using the provided bitmap's current font settings. Preserves existing newlines.
|
|
* Falls back to character-level splitting if a single word is too wide.
|
|
* @param {string} text
|
|
* @param {Bitmap} bitmap
|
|
* @param {number} maxWidth
|
|
* @returns {string[]}
|
|
*/
|
|
function wrapTextToWidth(text, bitmap, maxWidth) {
|
|
if (!text) return [""];
|
|
|
|
const lines = [];
|
|
const rawLines = String(text).replace(/\r\n?|\u2028/g, "\n").split("\n");
|
|
|
|
for (const raw of rawLines) {
|
|
const words = raw.split(/(\s+)/); // keep whitespace tokens to avoid collapsing spaces
|
|
let current = "";
|
|
|
|
for (let i = 0; i < words.length; i++) {
|
|
const token = words[i];
|
|
const tentative = current + token;
|
|
const w = bitmap.measureTextWidth(tentative);
|
|
if (w <= maxWidth) {
|
|
current = tentative;
|
|
continue;
|
|
}
|
|
|
|
// If current is empty and a single token is too big, split the token by chars
|
|
if (!current) {
|
|
const split = splitLongTokenByChars(token, bitmap, maxWidth);
|
|
// take all but last as full lines, last continues
|
|
for (let j = 0; j < split.length - 1; j++) {
|
|
lines.push(split[j]);
|
|
}
|
|
current = split[split.length - 1];
|
|
} else {
|
|
// push the line and start new with token
|
|
if (current.trim().length > 0) lines.push(current.trimEnd());
|
|
|
|
// token itself might still be too big
|
|
const split = splitLongTokenByChars(token, bitmap, maxWidth);
|
|
for (let j = 0; j < split.length - 1; j++) {
|
|
lines.push(split[j]);
|
|
}
|
|
current = split[split.length - 1];
|
|
}
|
|
}
|
|
|
|
if (current.trim().length > 0 || raw === "") {
|
|
lines.push(current.trimEnd());
|
|
}
|
|
}
|
|
|
|
// Ensure at least one line
|
|
return lines.length > 0 ? lines : [""];
|
|
}
|
|
|
|
function splitLongTokenByChars(token, bitmap, maxWidth) {
|
|
const chunks = [];
|
|
let buf = "";
|
|
for (const ch of token) {
|
|
const tentative = buf + ch;
|
|
if (bitmap.measureTextWidth(tentative) <= maxWidth) {
|
|
buf = tentative;
|
|
} else {
|
|
if (buf) chunks.push(buf);
|
|
buf = ch;
|
|
}
|
|
}
|
|
if (buf) chunks.push(buf);
|
|
return chunks.length ? chunks : [token];
|
|
}
|
|
|
|
//========================================================================
|
|
// 定数定義(ゲーム固有)
|
|
//========================================================================
|
|
const State = {
|
|
PUSSY: { // おまんこ
|
|
name: 'PUSSY',
|
|
label: '0900-011-n011-0',
|
|
texts: [
|
|
"0910-001-n001-0",
|
|
"0910-002-n002-0",
|
|
"0910-003-n003-0",
|
|
"0910-004-n004-0",
|
|
],
|
|
position: new Point(-415, 434),
|
|
},
|
|
BREASTS: { // おっぱい
|
|
name: 'BREASTS',
|
|
label: '0900-012-n012-0',
|
|
texts: [
|
|
"0920-001-n001-0",
|
|
"0920-002-n002-0",
|
|
"0920-003-n003-0",
|
|
"0920-004-n004-0",
|
|
],
|
|
position: new Point(-436, 332),
|
|
},
|
|
BUTT: { // お尻
|
|
name: 'BUTT',
|
|
label: '0900-013-n013-0',
|
|
texts: [
|
|
"0930-001-n001-0",
|
|
"0930-002-n002-0",
|
|
"0930-003-n003-0",
|
|
"0930-004-n004-0",
|
|
],
|
|
position: new Point(-524, 516),
|
|
},
|
|
MOUTH: { // おクチ
|
|
name: 'MOUTH',
|
|
label: '0900-014-n014-0',
|
|
texts: [
|
|
"0940-001-n001-0",
|
|
"0940-002-n002-0",
|
|
"0940-003-n003-0",
|
|
"0940-004-n004-0",
|
|
],
|
|
position: new Point(-470, 0),
|
|
},
|
|
WOMB: { // 子宮
|
|
name: 'WOMB',
|
|
label: '0900-017-n017-0',
|
|
texts: [
|
|
"0950-001-n001-0",
|
|
"0950-002-n002-0",
|
|
"0950-003-n003-0",
|
|
"0950-004-n004-0",
|
|
],
|
|
position: new Point(-407, 525),
|
|
},
|
|
MIND: { // 精神
|
|
name: 'MIND',
|
|
label: '0900-018-n018-0',
|
|
texts: [
|
|
"0960-001-n001-0",
|
|
"0960-002-n002-0",
|
|
"0960-003-n003-0",
|
|
"0960-004-n004-0",
|
|
],
|
|
position: new Point(-440, 320),
|
|
},
|
|
};
|
|
|
|
//========================================================================
|
|
// クラス定義 (SceneLewdStatus)
|
|
//========================================================================
|
|
class SceneLewdStatus extends Scene_Base {
|
|
constructor() {
|
|
super();
|
|
this.images = {};
|
|
this.isImageLoaded = false;
|
|
this.runOnExit = false;
|
|
this.interpreter = null;
|
|
|
|
this._state = null;
|
|
this.stateSprite = {};
|
|
this.currentStage = null;
|
|
}
|
|
|
|
create() {
|
|
super.create();
|
|
this.createWindowLayer();
|
|
|
|
let promises = [
|
|
ImageManager.loadSystemAsync("lewd_status/background"),
|
|
ImageManager.loadSystemAsync("lewd_status/back_button"),
|
|
ImageManager.loadSystemAsync("lewd_status/frame"),
|
|
ImageManager.loadSystemAsync("lewd_status/body_mask"),
|
|
ImageManager.loadSystemAsync("lewd_status/body/stage_1"),
|
|
ImageManager.loadSystemAsync("lewd_status/body/stage_2"),
|
|
ImageManager.loadSystemAsync("lewd_status/body/stage_3"),
|
|
ImageManager.loadSystemAsync("lewd_status/body/stage_4"),
|
|
ImageManager.loadSystemAsync("lewd_status/body_background"),
|
|
];
|
|
|
|
const bgBitmap = new Bitmap(Graphics.width, Graphics.height);
|
|
bgBitmap.fillAll('#000000');
|
|
this.blackBackground = new Sprite(bgBitmap);
|
|
this.blackBackground.setFrame(0, 0, Graphics.width, Graphics.height);
|
|
this.blackBackground.zIndex = 0;
|
|
this.addChild(this.blackBackground);
|
|
|
|
Promise.all(promises).then(images => {
|
|
this.createDisplayObjects(images);
|
|
this.isImageLoaded = true;
|
|
});
|
|
}
|
|
|
|
createDisplayObjects(images) {
|
|
this.background = new Sprite(images[0]);
|
|
this.background.zIndex = 1;
|
|
this.addChild(this.background);
|
|
|
|
this.baseSprites = this.createSprites(images);
|
|
|
|
this.content = this.createContentSprite(images, images[2].width, images[2].height);
|
|
|
|
if (!!this.content) {
|
|
this.content.move(UI_AREA_X, UI_AREA_Y);
|
|
this.content.zIndex = 100;
|
|
this.addChild(this.content);
|
|
}
|
|
|
|
this.window = this.createMessageWindow();
|
|
this.addWindow(this.window);
|
|
|
|
this.sortChildren();
|
|
}
|
|
|
|
createSprites(images) {
|
|
const sprites = [];
|
|
|
|
const uiWidth = images[2].width;
|
|
const uiHeight = images[2].height;
|
|
|
|
const frame = new Sprite(new Bitmap(uiWidth, uiHeight));
|
|
const frameBitmap = frame.bitmap;
|
|
frameBitmap.blt(images[2], 0, 0, uiWidth, uiHeight, 0, 0);
|
|
|
|
frameBitmap.textColor = '#FFFFFF';
|
|
frameBitmap.fontFace = 'genkai-mincho';
|
|
frameBitmap.outlineWidth = 0;
|
|
frameBitmap.fontSize = 64;
|
|
frameBitmap.drawText(TextResource.getText(TITLE_TEXT), 52, 46, 1200, 64, 'left');
|
|
|
|
frame.move(7, 0);
|
|
frame.zIndex = 60;
|
|
this.addChild(frame);
|
|
sprites.push(frame);
|
|
|
|
const backButtonArea = new Sprite_InputHandle();
|
|
backButtonArea.bitmap = images[1];
|
|
backButtonArea.setFrame(0, 0, 72, 72);
|
|
backButtonArea.addEnterListener(() => {
|
|
if (this.handleBackButtonClicked()) {
|
|
if (!this.runOnExit && !this.isBusy()) {
|
|
this._exit();
|
|
}
|
|
}
|
|
});
|
|
backButtonArea.move(1830, 990);
|
|
backButtonArea.zIndex = 3;
|
|
this.addChild(backButtonArea);
|
|
sprites.push(backButtonArea);
|
|
|
|
const bar1 = this.createLewdGauge(param.lewdLevel1, SYSTEM_LEWD_VALUE1);
|
|
bar1.move(902, 846);
|
|
bar1.zIndex = 100;
|
|
this.addChild(bar1);
|
|
sprites.push(bar1);
|
|
|
|
const bar2 = this.createLewdGauge(param.lewdLevel2, SYSTEM_LEWD_VALUE2);
|
|
bar2.move(902, 918);
|
|
bar2.zIndex = 100;
|
|
this.addChild(bar2);
|
|
sprites.push(bar2);
|
|
|
|
const level = $gameActors.actor(param.playerActor).level;
|
|
const levelTextBitmap = new Bitmap(918, 50);
|
|
levelTextBitmap.textColor = '#FFFFFF';
|
|
levelTextBitmap.fontFace = 'MPLUS1Code-Regular';
|
|
levelTextBitmap.outlineWidth = 0;
|
|
levelTextBitmap.fontSize = 40;
|
|
levelTextBitmap.drawText(TextResource.getText(SYSTEM_TOTAL_LEBEL), 0, 0, 230, levelTextBitmap.height, 'left');
|
|
levelTextBitmap.drawText(level, 818, 0, 100, levelTextBitmap.height, 'right');
|
|
const levelText = new Sprite(levelTextBitmap);
|
|
levelText.move(902, 986);
|
|
levelText.zIndex = 100;
|
|
this.addChild(levelText);
|
|
sprites.push(levelText);
|
|
|
|
return sprites;
|
|
}
|
|
|
|
createContentSprite(images, width, height) {
|
|
const content = new Sprite(new Bitmap(width, height));
|
|
|
|
const charaBackGround = new Sprite(images[8]);
|
|
charaBackGround.move(1265, 33);
|
|
charaBackGround.zIndex = 1;
|
|
content.addChild(charaBackGround);
|
|
|
|
const chMask = new Sprite(images[3]);
|
|
this.character = new Sprite_Scrollable(images[3].width, images[2].height, chMask);
|
|
this.leveledCharacters = [ 0, 1, 2, 3 ].map(index => {
|
|
const chImageSprite = new Sprite(images[index + 4]);
|
|
chImageSprite.zIndex = 1;
|
|
chImageSprite.hide();
|
|
this.character.addChild(chImageSprite);
|
|
return chImageSprite;
|
|
});
|
|
|
|
this.character.enableLimit(false);
|
|
this.character.enableInput(false);
|
|
this.character.zIndex = 3;
|
|
this.character.move(1265, 33);
|
|
content.addChild(this.character);
|
|
|
|
this.stateMenuArea = new Sprite_Scrollable(ITEM_WIDTH, CONTENT_AREA_HEIHGT);
|
|
this.stateMenuArea.enableScroll(false);
|
|
this.stateMenus = this.createMenuSprite(Object.values(State)).map(sprite => {
|
|
this.stateMenuArea.addChild(sprite);
|
|
return sprite;
|
|
});
|
|
|
|
this.stateMenuArea.move(39, CONTENT_TOP);
|
|
this.stateMenuArea.zIndex = 2;
|
|
content.addChild(this.stateMenuArea);
|
|
|
|
this.descriptionArea = this.createDescriptionFrame();
|
|
const descriptionEntries = Object.values(State).map(state => {
|
|
return [ state.name, {
|
|
state: state.name,
|
|
sprites: [ 1, 2, 3, 4 ].map(level => {
|
|
const sprite = this.createDescriptionText(state, level);
|
|
sprite.hide();
|
|
this.descriptionArea.addChild(sprite);
|
|
return sprite;
|
|
}),
|
|
}
|
|
];
|
|
});
|
|
this.descriptions = Object.fromEntries(descriptionEntries);
|
|
|
|
this.descriptionArea.move(574, CONTENT_TOP);
|
|
this.descriptionArea.zIndex = 2;
|
|
content.addChild(this.descriptionArea);
|
|
|
|
this.setState(State.PUSSY.name);
|
|
|
|
return content;
|
|
}
|
|
|
|
createMenuSprite(itemNames) {
|
|
return itemNames.map((item, index) => {
|
|
const sprite = new Sprite_StatusItem(item.name, item.label, ITEM_WIDTH, ITEM_HEIGHT);
|
|
sprite.move(0, (ITEM_HEIGHT + ITEM_MERGIN) * index);
|
|
return sprite;
|
|
});
|
|
}
|
|
|
|
createDescriptionFrame() {
|
|
const areaSprite = new Sprite_Scrollable(CONTENT_AREA_WIDTH, CONTENT_AREA_HEIHGT);
|
|
const frameSprite = new Sprite(new Bitmap(CONTENT_AREA_WIDTH, CONTENT_AREA_HEIHGT));
|
|
const frameBitmap = frameSprite.bitmap;
|
|
const lw = CONTENT_LINE_WIDTH;
|
|
|
|
frameBitmap.fillAll('#FFFFFF');
|
|
frameBitmap.clearRect(lw, lw, CONTENT_AREA_WIDTH - (lw * 2), CONTENT_AREA_HEIHGT - (lw * 2));
|
|
frameSprite.zIndex = 2;
|
|
|
|
areaSprite.addChild(frameSprite);
|
|
|
|
return areaSprite;
|
|
}
|
|
|
|
createDescriptionText(state, level) {
|
|
const index = level - 1;
|
|
const text = TextResource.getText(state.texts[index]);
|
|
// Switch to an English-friendly font and wrap by pixel width; shrink if too tall
|
|
const width = CONTENT_AREA_WIDTH - (DESCRIPTION_MERGIN * 2);
|
|
const maxHeight = CONTENT_AREA_HEIHGT - DESCRIPTION_MERGIN;
|
|
const tmp = new Bitmap(1, 1);
|
|
tmp.textColor = '#FFFFFF';
|
|
tmp.fontFace = 'NotoSerifCJKjp-Bold'; // English-friendly, narrower than CJK fonts
|
|
tmp.outlineWidth = 0;
|
|
let fontSize = 26; // start a bit smaller than JP
|
|
let lines = [];
|
|
let lineHeight = 0;
|
|
let height = 0;
|
|
|
|
for (let tries = 0; tries < 12; tries++) {
|
|
tmp.fontSize = fontSize;
|
|
lines = wrapTextToWidth(text, tmp, width);
|
|
lineHeight = Math.max(24, Math.round(tmp.fontSize * 1.3));
|
|
height = lines.length * lineHeight;
|
|
if (height <= maxHeight || fontSize <= 18) break;
|
|
fontSize -= 1; // shrink until it fits or min size reached
|
|
}
|
|
|
|
const bitmap = new Bitmap(width, height);
|
|
bitmap.textColor = tmp.textColor;
|
|
bitmap.fontFace = tmp.fontFace;
|
|
bitmap.outlineWidth = tmp.outlineWidth;
|
|
bitmap.fontSize = tmp.fontSize;
|
|
|
|
lines.forEach((line, index) => {
|
|
const y = (lineHeight * index);
|
|
bitmap.drawText(line, 0, y, width, lineHeight, 'left');
|
|
})
|
|
|
|
const sprite = new Sprite(bitmap);
|
|
sprite.move(DESCRIPTION_MERGIN, (DESCRIPTION_MERGIN / 2));
|
|
sprite.zIndex = 1;
|
|
return sprite;
|
|
}
|
|
|
|
createMessageWindow() {
|
|
const rect = new Rectangle(0, 0, 840, 248);
|
|
const window = new Window_LewdLevel(rect);
|
|
window.setLewdLevelListener(this.setLewdStage.bind(this));
|
|
|
|
const currentLewdStage = Math.max(PluginUtils.getVariables(param.lewdStage) || 1, 1);
|
|
this.setLewdStage(currentLewdStage);
|
|
return window;
|
|
}
|
|
|
|
createWindowLayer() {
|
|
this._windowLayer = new WindowLayer();
|
|
this._windowLayer.x = 7;
|
|
this._windowLayer.y = 826;
|
|
this._windowLayer.zIndex = 500;
|
|
this.addChild(this._windowLayer);
|
|
}
|
|
|
|
createLewdGauge(bindingVariable, label) {
|
|
const sprite = new Sprite(new Bitmap(1000, 54));
|
|
const bitmap = sprite.bitmap;
|
|
bitmap.textColor = '#FFFFFF';
|
|
bitmap.fontFace = 'MPLUS1Code-Regular';
|
|
bitmap.fontSize = 40;
|
|
bitmap.outlineWidth = 0;
|
|
|
|
const labelWidth = 230;
|
|
const countWidth = 68;
|
|
const textHeight = 50;
|
|
const labelY = (bitmap.height - textHeight) / 2;
|
|
|
|
const barWidth = 620;
|
|
const mergin = 10;
|
|
|
|
bitmap.drawText(TextResource.getText(label), 0, labelY, labelWidth, textHeight, 'left');
|
|
|
|
const lewdCount = PluginUtils.getVariables(bindingVariable) || 0;
|
|
bitmap.drawText(lewdCount, labelWidth + barWidth, labelY, countWidth, textHeight, 'right');
|
|
|
|
const bar = new Sprite_ProgressBar(barWidth, 54, 99);
|
|
bar.lineWidth = 6;
|
|
bar.bind(bindingVariable);
|
|
bar.setProgressGradation([
|
|
new GradientPoint(0, '#CACACA'),
|
|
new GradientPoint(100, '#CACACA'),
|
|
]);
|
|
|
|
bar.zIndex = 3;
|
|
bar.move(labelWidth + mergin, 0);
|
|
sprite.addChild(bar);
|
|
|
|
return sprite;
|
|
}
|
|
|
|
setBloking(enable) {
|
|
if (enable !== this.isTouchBlocking) {
|
|
if (enable) {
|
|
this.onStartBlocking();
|
|
} else {
|
|
this.onEndBlocking();
|
|
|
|
}
|
|
this.isTouchBlocking = enable;
|
|
}
|
|
}
|
|
|
|
setState(value) {
|
|
if (State.hasOwnProperty(value)) {
|
|
if (value !== this._state) {
|
|
const point = State[value].position;
|
|
this.character.smoothScrollTo(point.x, point.y, 6);
|
|
|
|
Object.values(this.descriptions).forEach(description => {
|
|
description.sprites.forEach((sprite, index) => {
|
|
sprite.visible = (description.state === value && this.currentStage === (index + 1));
|
|
});
|
|
});
|
|
|
|
this.stateMenus.forEach((sprite, index) => {
|
|
if (sprite.getName() === value) {
|
|
sprite.setFocus(true);
|
|
this.stateindex = index;
|
|
} else {
|
|
sprite.setFocus(false);
|
|
}
|
|
});
|
|
this._state = value;
|
|
}
|
|
} else {
|
|
Logger.w(`[SceneLewdStatus] invalid state: state = ${value}`);
|
|
}
|
|
}
|
|
|
|
setLewdStage(value) {
|
|
const stage = Number(value).clamp(1, 4);
|
|
|
|
if (this.currentStage !== stage) {
|
|
Object.values(this.descriptions).forEach(description => {
|
|
description.sprites.forEach((sprite, index) => {
|
|
sprite.visible = (description.state === this._state && stage === (index + 1));
|
|
});
|
|
});
|
|
|
|
this.leveledCharacters.forEach((sprite, index) => {
|
|
sprite.visible = (stage === (index + 1));
|
|
});
|
|
this.currentStage = stage;
|
|
}
|
|
}
|
|
|
|
onExit() {
|
|
// for overload
|
|
}
|
|
|
|
onStartBlocking() {
|
|
// for overload
|
|
}
|
|
|
|
onEndBlocking() {
|
|
// for overload
|
|
}
|
|
|
|
handleBackButtonClicked() {
|
|
// for overload
|
|
return true;
|
|
}
|
|
|
|
start() {
|
|
super.start();
|
|
|
|
if (!!this.bgm && this.bgm !== '') {
|
|
AudioManager.playBgm({
|
|
name: this.bgm,
|
|
volume: 100,
|
|
pitch: 100,
|
|
pan: 0,
|
|
pos: 0,
|
|
});
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
super.stop();
|
|
if (!!this.bgm && this.bgm !== '') {
|
|
AudioManager.stopBgm();
|
|
}
|
|
}
|
|
|
|
update() {
|
|
super.update();
|
|
|
|
if (!this.isActive()) {
|
|
return;
|
|
}
|
|
|
|
if (!this.runOnExit && !this.isBusy()) {
|
|
this.processInput();
|
|
}
|
|
}
|
|
|
|
processInput() {
|
|
if ((Input.isRepeated("cancel") || TouchInput.isCancelled()) && !this.runOnExit) {
|
|
this._exit();
|
|
} else if (Input.isRepeated(InputClass.INPUT_CLASS_UP)) {
|
|
this.moveStateFocus((this.stateindex < 0) ? 0 : -1);
|
|
} else if (Input.isRepeated(InputClass.INPUT_CLASS_DOWN)) {
|
|
this.moveStateFocus((this.stateindex < 0) ? 0 : 1);
|
|
} else if (TouchInput.isHovered()) {
|
|
this.processStatus();
|
|
}
|
|
}
|
|
|
|
processStatus() {
|
|
if (this.stateMenuArea.isTouchedInsideFrame()) {
|
|
const focusedIndex = this.stateMenus.findIndex(sprite => sprite.isHovered());
|
|
if (focusedIndex >= 0) {
|
|
this.updateStateFocusIndex(focusedIndex, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
moveStateFocus(moveIndex) {
|
|
const index = Number((this.stateindex >= 0) ? this.stateindex + moveIndex : 0);
|
|
if (index >= 0 && index < this.stateMenus.length) {
|
|
this.updateStateFocusIndex(index, false);
|
|
}
|
|
}
|
|
|
|
updateStateFocusIndex(index, fromTouch) {
|
|
if (index >= 0 && this.stateindex !== index) {
|
|
this.stateMenus.forEach((s, i) => s.setFocus(i === index));
|
|
this.stateindex = index;
|
|
this.setState(this.stateMenus[index].getName());
|
|
SoundManager.playCursor();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
_exit() {
|
|
this.runOnExit = true;
|
|
SoundManager.playCancel();
|
|
this.onExit();
|
|
// this.fadeOutAll();
|
|
this._updateInput();
|
|
this._exitScene();
|
|
}
|
|
|
|
_exitScene() {
|
|
SceneManager.pop();
|
|
}
|
|
|
|
_updateInput() {
|
|
Input.update();
|
|
TouchInput.update();
|
|
}
|
|
}
|
|
window.SceneLewdStatus = SceneLewdStatus;
|
|
|
|
//========================================================================
|
|
// クラス定義 (Window_LewdLevel)
|
|
//========================================================================
|
|
class Window_LewdLevel extends Window_Base {
|
|
constructor(rect) {
|
|
super(rect);
|
|
|
|
this.move(rect.x, rect.y, rect.width, rect.height);
|
|
|
|
this._frame
|
|
this._modeListener = null;
|
|
this._lewdLevelListener = null;
|
|
}
|
|
|
|
createContents() {
|
|
super.createContents();
|
|
|
|
const bitmap = this.contents;
|
|
bitmap.textColor = '#FFFFFF';
|
|
bitmap.fontFace = 'NotoSerifCJKjp-Black';
|
|
bitmap.fontSize = 40;
|
|
bitmap.outlineWidth = 0;
|
|
const textWidth = 804;
|
|
const x = (bitmap.width - textWidth) / 2;
|
|
bitmap.drawText(TextResource.getText('0900-005-n005-0'), x, 6, textWidth, 50, 'center');
|
|
|
|
const labels = [
|
|
'0900-006-n006-0',
|
|
'0900-007-n007-0',
|
|
'0900-008-n008-0',
|
|
'0900-009-n009-0',
|
|
];
|
|
|
|
const maxLewdStage = Math.max(PluginUtils.getVariables(param.lewdStage) || 1, 1) - 1;
|
|
const areaSprite = new Sprite();
|
|
this.stages = labels.map((label, index) => {
|
|
const sprite = new Sprite_LewdLevel(label, index + 1);
|
|
const x = (index % 3) * (LEWD_LEVEL_WIDTH + LEWD_LEVEL_MERGIN);
|
|
const y = Math.trunc(index / 3) * (LEWD_LEVEL_HEIGHT + LEWD_LEVEL_MERGIN);
|
|
|
|
sprite.setActive(index <= maxLewdStage);
|
|
sprite.move(x, y);
|
|
areaSprite.addChild(sprite);
|
|
return sprite;
|
|
});
|
|
|
|
const bounds = areaSprite.getBounds();
|
|
areaSprite.move((this.width - bounds.width) / 2, 84);
|
|
this.addChild(areaSprite);
|
|
|
|
this.updateFocusIndex(maxLewdStage, false);
|
|
}
|
|
|
|
setDrugAcitive(active) {
|
|
this.stages[this.stages.length - 1].setActive(active);
|
|
}
|
|
|
|
setModeListener(listener) {
|
|
if (!!listener && typeof listener === 'function') {
|
|
this._modeListener = listener;
|
|
}
|
|
}
|
|
|
|
setLewdLevelListener(listener) {
|
|
if (!!listener && typeof listener === 'function') {
|
|
this._lewdLevelListener = listener;
|
|
}
|
|
}
|
|
|
|
update() {
|
|
super.update();
|
|
this.processInput();
|
|
}
|
|
|
|
processInput() {
|
|
if (Input.isTriggered(InputClass.INPUT_CLASS_LEFT)) {
|
|
for (let i = 1; (this.index - i) >= 0; i++) {
|
|
const index = Number(this.index - i).clamp(0, this.stages.length);
|
|
if (this.stages[index].isActive()) {
|
|
this.updateFocusIndex(index, false);
|
|
break;
|
|
}
|
|
}
|
|
} else if (Input.isTriggered(InputClass.INPUT_CLASS_RIGHT)) {
|
|
for (let i = 1; (this.index + i) < this.stages.length; i++) {
|
|
const index = Number(this.index + i).clamp(0, this.stages.length);
|
|
if (this.stages[index].isActive()) {
|
|
this.updateFocusIndex(index, false);
|
|
break;
|
|
}
|
|
}
|
|
} else if (TouchInput.isHovered()) {
|
|
const focusedIndex = this.stages.findIndex(sprite => {
|
|
return sprite.isHovered() && sprite.isActive();
|
|
});
|
|
if (focusedIndex >= 0) {
|
|
this.updateFocusIndex(focusedIndex, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
updateFocusIndex(index, fromTouch) {
|
|
if (index >= 0 && this.index !== index) {
|
|
this.stages.forEach((s, i) => {
|
|
if (i === index) {
|
|
s.setFocus(true);
|
|
const level = s.getLevel();
|
|
if (level < 0) {
|
|
this._fireModeChange(Mode.DRAG);
|
|
} else {
|
|
if (this.index >= 0 && this.stages[this.index].getLevel() < 0) {
|
|
this._fireModeChange(Mode.STATUS);
|
|
}
|
|
this._fireLewdLevelChanged(level);
|
|
}
|
|
} else {
|
|
s.setFocus(false);
|
|
}
|
|
});
|
|
this.index = index;
|
|
SoundManager.playCursor();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
_fireModeChange(newMode) {
|
|
if (!!this._modeListener && typeof this._modeListener === 'function') {
|
|
this._modeListener(newMode);
|
|
}
|
|
}
|
|
|
|
_fireLewdLevelChanged(newLevel) {
|
|
if (!!this._lewdLevelListener && typeof this._lewdLevelListener === 'function') {
|
|
this._lewdLevelListener(newLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
//========================================================================
|
|
// クラス定義 (Sprite_StatusItem)
|
|
//========================================================================
|
|
class Sprite_StatusItem extends Sprite_InputHandle {
|
|
constructor(name, label, width, height) {
|
|
super();
|
|
this.setFrame(0, 0, width, height);
|
|
|
|
this._name = name;
|
|
this._focus = false;
|
|
|
|
this.bg = new Sprite(new Bitmap(width, height));
|
|
const bgBitmap = this.bg.bitmap;
|
|
bgBitmap.fillAll('#FFFFFF');
|
|
this.bg.zIndex = 0;
|
|
this.bg.opacity = PluginUtils.percent(255, 70);
|
|
this.addChild(this.bg);
|
|
|
|
const textSprite = this.createLabelSprite(label);
|
|
textSprite.move((this.width - textSprite.width) / 2, (this.height - textSprite.height) / 2);
|
|
textSprite.zIndex = 1;
|
|
this.addChild(textSprite);
|
|
|
|
this.setFocus(false);
|
|
}
|
|
|
|
createLabelSprite(label) {
|
|
const title = new Bitmap(494, 40);
|
|
title.textColor = '#FFFFFF';
|
|
title.fontFace = 'NotoSerifCJKjp-Bold';
|
|
title.outlineWidth = 0;
|
|
title.fontSize = 28;
|
|
title.drawText(TextResource.getText(label), 0, 0, 494, 40, 'left');
|
|
return new Sprite(title);
|
|
}
|
|
|
|
getName() {
|
|
return this._name;
|
|
}
|
|
|
|
normalColor() {
|
|
return 0x000000;
|
|
}
|
|
|
|
focusedColor() {
|
|
return 0xCACACA;
|
|
}
|
|
|
|
setFocus(focus) {
|
|
this.bg.tint = focus ? this.focusedColor() : this.normalColor();
|
|
this._focus = focus;
|
|
}
|
|
|
|
isFocused() {
|
|
return this._focus;
|
|
}
|
|
}
|
|
|
|
//========================================================================
|
|
// クラス定義 (Sprite_LewdLevel)
|
|
//========================================================================
|
|
class Sprite_LewdLevel extends Sprite_StatusItem {
|
|
constructor(label, level) {
|
|
super(String(level), label, LEWD_LEVEL_WIDTH, LEWD_LEVEL_HEIGHT);
|
|
|
|
this._level = level;
|
|
this._active = true;
|
|
}
|
|
|
|
getLevel() {
|
|
return Number(this.getName());
|
|
}
|
|
|
|
normalColor() {
|
|
return 0x444444;
|
|
}
|
|
|
|
setActive(value) {
|
|
this.opacity = value ? 255 : 40;
|
|
this._active = value;
|
|
}
|
|
|
|
isActive() {
|
|
return this._active;
|
|
}
|
|
|
|
createLabelSprite(label) {
|
|
const title = new Bitmap(LEWD_LEVEL_WIDTH, LEWD_LEVEL_HEIGHT);
|
|
title.textColor = '#FFFFFF';
|
|
title.fontFace = 'NotoSerifCJKjp-Bold';
|
|
title.outlineWidth = 0;
|
|
title.fontSize = 36;
|
|
title.drawText(TextResource.getText(label), 0, 0, LEWD_LEVEL_WIDTH, LEWD_LEVEL_HEIGHT, 'center');
|
|
return new Sprite(title);
|
|
}
|
|
}
|
|
|
|
//========================================================================
|
|
// プラグインコマンド
|
|
//========================================================================
|
|
PluginManagerEx.registerCommand(script, 'startScene', args => {
|
|
SceneManager._scene.fadeOutAll();
|
|
SceneManager.push(SceneLewdStatus);
|
|
});
|
|
})();
|