nyacronomicon/js/plugins/KN_Map.js
2026-03-13 01:56:07 -05:00

683 lines
No EOL
24 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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_Map.js
//=============================================================================
/*:ja
* @target MZ
* @author kurogoma knights
* @base PluginCommonBase
* @plugindesc MAP機能いろいろ
*
* @noteParam sbgName
* @noteDir img/parallaxes/
* @noteType file
* @noteData maps
*
* @noteParam sbgNightName
* @noteDir img/parallaxes/
* @noteType file
* @noteData maps
*
* @param EnableStand
* @desc 立ち絵常時表示
* @default true
* @type boolean
*
* @param EnableMotion
* @desc モーション
* @default false
* @type boolean
*
* @command SHOW_STILL
* @desc
* @arg stillPictureName
* @text スチル選択
* @type file
* @dir img/pictures
* @arg stillBGPictureName
* @text 背景選択
* @type file
* @dir img/pictures
* @arg tweenType
* @default None
* @type select
* @option None
* @option TweenA
* @option TweenB
* @option TweenC
*
* @command HIDE_STILL
*
* @command SHOW_UI
*
* @command HIDE_UI
*
* @command HIDE_WITHOUT_STAND
*
*/
(() => {
'use strict';
const script = document.currentScript;
const param = PluginManagerEx.createParameter(script);
// 共通ピクチャ設定
const PICTURE_ORIGIN = 0; // 0:左上 1:中央?
const PICTURE_SCALE_X = 100;
const PICTURE_SCALE_Y = 100;
const PICTURE_OPACITY = 255;
const PICTURE_BLEND_MODE = 0;
// ファイル名
const DEFAULT_STAND_BG_NAME = "KN/stand_bg"; // 立ち絵背景
const DEFAULT_STAND_FRAME_NAME = "KN/none";
// const DEFAULT_STAND_FRAME_NAME = "KN/stand_frame"; // 立ち絵背景フレーム
const STAND_BODY_NAME = "stand/body"; // 素体
const STAND_EAR_NAME = "stand/body_ear"; // 素体
const STAND_TAIL_NAME = "stand/body_tail"; // 素体
const STAND_NONE = "stand/none"; // から画像
const STAND_WEAPON = "stand/costume/book"
const GUIDE_NAME = "ui/guide"; // ギャラリーガイド画像
// ピクチャID整理予定
// 中央定数 `KN_CONST` があればそれを優先して使用。フォールバックは既存の値。
// Use centralized constants from Kurogoma.PIDConst (no fallbacks).
const STILL_BG_PICTURE_ID = window.Kurogoma.PIDConst.StillBgPictureId; // スチル背景
const STILL_PICTURE_ID = window.Kurogoma.PIDConst.StillPictureId; // スチル
const GUIDE_PICTURE_ID = window.Kurogoma.PIDConst.GuidePictureId; // ガイド
// 座標
const STAND_AREA_WIDTH = 384; // 立ち絵の表示幅
const SHIRO_STAND_X = 716; // シロ立ち絵x
const SHIRO_STAND_Y = 70; // シロ立ち絵y
const STILL_X = 0; // スチルは1200x720想定
const STILL_Y = 0; // スチルは1200x720想定
//
// プラグインコマンド
//
// スチル表示・非表示
PluginManagerEx.registerCommand(script, "SHOW_STILL", args => {
$gameMap.hideUI();
$gameMap.showStillBGPicture(args.stillBGPictureName);
if (!args.tweenType || args.tweenType == "None")
$gameMap.showStillPicture(args.stillPictureName);
else
$gameMap.tweenStillPicture(args.stillPictureName, args.tweenType);
});
PluginManagerEx.registerCommand(script, "HIDE_STILL", args => {
$gameMap.showUI();
$gameMap.hideStillBGPicture();
$gameMap.hideStillPicture();
// プラグイン連携
// const pluginArgs = { visible: false };
// PluginManager.callCommand($gameMap.getInterpreter(), "MOG_ActorHud", "ActorHudVisible", pluginArgs);
});
// UI表示・非表示
PluginManagerEx.registerCommand(script, "SHOW_UI", args => {
$gameMap.showUI();
});
PluginManagerEx.registerCommand(script, "HIDE_UI", args => {
$gameMap.hideUI();
});
//
// 関数定義
//
// 立ち絵フェイススプライト名取得
const _getFacePath = function(costumeKey, actor) {
const pattern = $gameVariables.value(Kurogoma.VariableConst.Face) || "normal,none";
const [faceKey = "normal", _] = pattern.split(",");
return `stand/face/${faceKey}`;
}
// エモーション取得
const _getEmotionPath = function(actor) {
const pattern = $gameVariables.value(Kurogoma.VariableConst.Face) || "normal&none";
const [_, emotionKey = "none"] = pattern.split(",");
return `stand/emotion/${emotionKey}`;
}
// 立ち絵コスチュームスプライト名取得
const _getCostumePath = function(costumeKey, actor) {
let spriteName = "stand/costume/normal_1";
if (costumeKey === "bunny") {
spriteName = "stand/costume/bunny";
} else {
if ($gamePlayer.isArmorTaiha()) {
spriteName = "stand/costume/normal_3";
} else if ($gamePlayer.isArmorChuuha()) {
spriteName = "stand/costume/normal_2";
} else {
spriteName = "stand/costume/normal_1";
}
}
return spriteName;
}
//
// Game_Map
//
var _Game_Map_setup = Game_Map.prototype.setup;
Game_Map.prototype.setup = function(mapId) {
_Game_Map_setup.call(this, mapId);
this._sbgName = '';
this._sbgNightName = '';
if ($dataMap.meta) {
this._sbgName = $dataMap.meta.sbgName;
this._sbgNightName = $dataMap.meta.sbgNightName;
}
};
// スチル背景表示
Game_Map.prototype.showStillBGPicture = function(pictureName) {
if (!pictureName)
return;
$gameScreen.showPicture(STILL_BG_PICTURE_ID, pictureName,
PICTURE_ORIGIN, STILL_X, STILL_Y, PICTURE_SCALE_X, PICTURE_SCALE_Y,
PICTURE_OPACITY, PICTURE_BLEND_MODE);
};
// スチル背景非表示
Game_Map.prototype.hideStillBGPicture = function() {
$gameScreen.erasePicture(STILL_BG_PICTURE_ID);
}
// スチル表示
Game_Map.prototype.showStillPicture = function(pictureName) {
if (!pictureName)
return;
$gameScreen.showPicture(STILL_PICTURE_ID, pictureName,
PICTURE_ORIGIN, STILL_X, STILL_Y, PICTURE_SCALE_X, PICTURE_SCALE_Y,
PICTURE_OPACITY, PICTURE_BLEND_MODE);
};
// スチル表示トゥイーン
Game_Map.prototype.tweenStillPicture = function(pictureName, tweenType) {
if (!pictureName)
return;
switch (tweenType) {
case "TweenA":
$gameMap.tweenStillPictureA(pictureName, tweenType);
break;
case "TweenB":
break;
case "TweenC":
break;
default:
console.warn("トゥイーンが存在しません");
break;
}
};
// 下からふわっと
Game_Map.prototype.tweenStillPictureA = function(pictureName, tweenType) {
const startOpacity = 0, endOpacity = 255;
const distanceX = 0, distanceY = -5;
const duration = 15;
const easingType = 2; // (0:一定速度、1:ゆっくり始まる、2:ゆっくり終わる、3:ゆっくり始まってゆっくり終わる)
$gameScreen.showPicture(STILL_PICTURE_ID, pictureName,
PICTURE_ORIGIN, STILL_X - distanceX, STILL_Y - distanceY, PICTURE_SCALE_X, PICTURE_SCALE_Y,
startOpacity, PICTURE_BLEND_MODE);
$gameScreen.movePicture(STILL_PICTURE_ID,
PICTURE_ORIGIN, STILL_X + distanceX, STILL_Y + distanceY, PICTURE_SCALE_X, PICTURE_SCALE_Y,
endOpacity, PICTURE_BLEND_MODE, duration, easingType);
};
// スチル非表示
Game_Map.prototype.hideStillPicture = function() {
$gameScreen.erasePicture(STILL_PICTURE_ID);
}
// UI表示 (立ち絵もUIもきえる
Game_Map.prototype.showUI = function() {
SceneManager._scene._hudContainer?.show();
const pluginArgs = { visible: true };
PluginManager.callCommand($gameMap.getInterpreter(), "MOG_ActorHud", "ActorHudVisible", pluginArgs);
};
// UI非表示
Game_Map.prototype.hideUI = function() {
SceneManager._scene._hudContainer?.hide();
const pluginArgs = { visible: false };
PluginManager.callCommand($gameMap.getInterpreter(), "MOG_ActorHud", "ActorHudVisible", pluginArgs);
}
// ガイド表示
Game_Map.prototype.showGuide = function() {
if ($gameSwitches.value(Kurogoma.SwitchConst.GuideDisable)) return; // ガイド設定無効なら無視
$gameScreen.showPicture(GUIDE_PICTURE_ID, GUIDE_NAME,
PICTURE_ORIGIN, STILL_X, STILL_Y, PICTURE_SCALE_X, PICTURE_SCALE_Y,
PICTURE_OPACITY, PICTURE_BLEND_MODE);
};
// ガイド非表示
Game_Map.prototype.hideGuide = function() {
if ($gameSwitches.value(Kurogoma.SwitchConst.GuideDisable)) return; // ガイド設定無効なら無視
$gameScreen.erasePicture(GUIDE_PICTURE_ID);
}
// MAP更新
// Game_Map.refreshは変数の値が変わったりすると通知がきて呼ばれる
const _Game_Map_Refresh = Game_Map.prototype.refresh;
Game_Map.prototype.refresh = function() {
_Game_Map_Refresh.apply(this, arguments); // リロードでエラーでたらこれを消せば動く
SceneManager._scene._hudContainer?.refresh(); // 最新で再描画
}
//
// Game_Actor
//
const Game_Actor_executeFloorDamage = Game_Actor.prototype.executeFloorDamage;
Game_Actor.prototype.executeFloorDamage = function() {
Game_Actor_executeFloorDamage.call(this);
if (this.hp == 0) {
$gameSwitches.setValue(Kurogoma.SwitchConst.FloorDamageDead, true);
}
};
//
// ウィンドウ位置調整
//
// 選択肢調整
Window_ChoiceList.prototype.windowX = function() {
const positionType = $gameMessage.choicePositionType();
// 立ち絵表示中
if (SceneManager._scene._hudContainer?.isActive()) {
// 真ん中
if (positionType === 1) {
return (Graphics.boxWidth - this.windowWidth() - STAND_AREA_WIDTH) / 2;
// 右寄せ
} else if (positionType === 2) {
return Graphics.boxWidth - this.windowWidth() - STAND_AREA_WIDTH;
// 左よせ
} else {
return 0;
}
// 立ち絵表示してない
} else {
// 真ん中
if (positionType === 1) {
return (Graphics.boxWidth - this.windowWidth()) / 2;
// 右寄せ
} else if (positionType === 2) {
return Graphics.boxWidth - this.windowWidth() - STAND_AREA_WIDTH / 2;
// 左よせ
} else {
return STAND_AREA_WIDTH / 2;
}
}
};
Window_ChoiceList.prototype.windowWidth = function() {
const width = this.maxChoiceWidth() + this.colSpacing() + this.padding * 2;
return Math.min(width, Graphics.boxWidth - STAND_AREA_WIDTH); // あってる…?
};
// メッセージウィンドウ調整 updatePlacementで位置調整されるのでxyはそのまま
Scene_Message.prototype.messageWindowRect = function() {
const ww = Graphics.boxWidth - STAND_AREA_WIDTH; // 立ち絵を除いたサイズ
const wh = this.calcWindowHeight(4, false) + 8; // 4行にする
const wx = (Graphics.boxWidth - ww) / 2;
const wy = 0;
return new Rectangle(wx, wy, ww, wh);
};
// ゴールド調整
Scene_Message.prototype.goldWindowRect = function() {
const ww = this.mainCommandWidth();
const wh = this.calcWindowHeight(1, true);
const wx = Graphics.boxWidth - STAND_AREA_WIDTH - ww;
const wy = 0;
return new Rectangle(wx, wy, ww, wh);
};
// イベントアイテム調整
Scene_Message.prototype.eventItemWindowRect = function() {
const ww = Graphics.boxWidth - STAND_AREA_WIDTH;
const wh = this.calcWindowHeight(4, true); // ?
const wx = 0;
const wy = 0;
return new Rectangle(wx, wy, ww, wh);
};
// メッセージウィンドウとかゴールドの位置調整 おもにxyいじる
Window_Message.prototype.updatePlacement = function() {
const goldWindow = this._goldWindow;
const isActiveHudContainer = SceneManager._scene._hudContainer?.isActive();
this._positionType = $gameMessage.positionType();
this.x = (!$gameParty.inBattle() && isActiveHudContainer) ? 0 : STAND_AREA_WIDTH / 2;
this.y = (this._positionType * (Graphics.boxHeight - this.height)) / 2;
if (goldWindow) {
goldWindow.y = this.y > 0 ? 0 : Graphics.boxHeight - goldWindow.height;
}
};
//
// SceneMap
//
// スプライトセット作成(もとは "createWindowLayer" でやってた)
// [注意] 下記形式で上書きすると PluginManagerEx.findClassName でとれないので使わないようにする
// Scene_Map = class extends Scene_Map {...}
const _Scene_Map_createSpriteset = Scene_Map.prototype.createSpriteset;
Scene_Map.prototype.createSpriteset = function() {
_Scene_Map_createSpriteset.apply(this, arguments);
// 有効じゃなきゃ何もしない
if (!param.EnableStand)
return;
// HUD
this._hudContainer = new Sprite_HudContainer();
this.addContainer(this._hudContainer, 2); // ピクチャの上(フェード下)
// 立ち絵登録
this._hudContainer._standContainer = new Sprite_HudStandMotionContainer($gameMap._sbgName, $gameMap._sbgNightName);
this._hudContainer.addChildAt(this._hudContainer._standContainer, 0); // 一番奥
// 初期ズーム補正(これがないとメニュー開いたときちらつく?)
this._hudContainer.applyInitialZoomFix();
};
// コンテナの追加
// 描画順は スプライトセットが下 ウィンドウレイヤが上
// 実際の描画順はコンソールから `SceneManager._scene._spriteset.children` で確認
Scene_Map.prototype.addContainer = function(container, type) {
// 最前面に追加 フェードで隠れない
if (type === 0) {
container.z = 10;
this.addChild(container);
}
// WindowLayerの奥に追加
if (type === 1) {
const index = this.children.indexOf(this._windowLayer);
this.addChildAt(container, index);
}
// ピクチャコンテナの奥に追加 スチル、フェードで隠れる
if (type === 2) {
const index = this._spriteset.children.indexOf(this._spriteset._pictureContainer);
this._spriteset.addChildAt(container, index); // index+1だとコンテナの手前
}
}
// 監視
const Scene_Map_update = Scene_Map.prototype.update;
Scene_Map.prototype.update = function() {
Scene_Map_update.apply(this);
if (!param.EnableMotion)
return;
this.updateStandMotion(); // モーション
};
// 立ち絵更新
let motionFrame = 0; //
let motionWait = 5; // モーションに何フレかかるか
let requestFrame = 0;
let requestWait = 30; // 何フレ毎にリクエストしてみるか
let requestRate = 4; // リクエスト時に実行する確率(1/N)
Scene_Map.prototype.updateStandMotion = function() {
// アニメーション
motionFrame++;
if (motionFrame % motionWait === 0) {
motionFrame = 0;
this._hudContainer?.updateMotion();
}
// リクエスト (実行中は停止)
requestFrame++;
if (requestFrame % requestWait === 0) {
requestFrame = 0;
if ($gameMap.isEventRunning()) return;
const r = Kurogoma.Random.range(0, requestRate - 1);
if (r === 0) {
this._hudContainer?.requestMotion();
}
}
}
//
// HUDのコンテナ
//
class Sprite_HudContainer extends Sprite {
initialize() {
super.initialize();
this._lastZoom = 1.0;
this._motionCount = 3;
this._motionFrame = 0;
this._motinDelta = 1;
this._motionActive = false;
}
refresh() {
this.children.forEach(child => {
if (child && typeof child.refresh === "function") {
child.refresh();
}
});
}
// 監視
update() {
super.update();
this.updateZoomFix();
}
// --- 初期ズーム適用 ---
applyInitialZoomFix() {
const zoom = $gameScreen.zoomScale();
this.scale.set(1 / zoom, 1 / zoom);
this._lastZoom = zoom;
}
// --- ズーム打ち消し ---
updateZoomFix() {
const zoom = $gameScreen.zoomScale();
if (this._lastZoom !== zoom) {
this.scale.set(1 / zoom, 1 / zoom);
this._lastZoom = zoom;
}
}
requestMotion() {
this._motionActive = true;
}
updateMotion() {
if (!this._motionActive) return;
this._motionFrame += this._motinDelta;
if (this._motionFrame == this._motionCount - 1) {
this._motinDelta = -1;
}
if (this._motionFrame == 0) {
this._motinDelta = 1;
this._motionActive = false;
}
this._standContainer.updateMotion(this._motionFrame + 1);
}
hide() {
this.alpha = 0;
}
show() {
this.alpha = 1;
}
isActive() {
return this.alpha === 1;
}
}
//
// 立ち絵とかのコンテナ モーション可能 本編用
//
class Sprite_HudStandMotionContainer extends Sprite {
initialize(sbgName, sbgNightName) {
super.initialize();
this._sbgName = sbgName;
this._sbgNightName = sbgNightName;
this._bg = new Sprite();
this._tail = new Sprite();
this._body = new Sprite();
this._ear = new Sprite();
this._face = new Sprite();
this._costume = new Sprite();
this._weapon = new Sprite();
this._emotion = new Sprite();
this._frame = new Sprite();
this.addChild(this._bg);
this.addChild(this._tail);
this.addChild(this._body);
this.addChild(this._ear);
this.addChild(this._face);
this.addChild(this._costume);
this.addChild(this._weapon);
this.addChild(this._emotion);
this.addChild(this._frame);
this._tail.x = this._body.x = this._ear.x = this._face.x = this._emotion.x = this._costume.x = this._weapon.x = SHIRO_STAND_X;
this._tail.y = this._body.y = this._ear.y = this._face.y = this._emotion.y = this._costume.y = this._weapon.y = SHIRO_STAND_Y;
this.refresh();
};
refresh() {
this.updateStand();
this.updateBG();
}
updateMotion(index) {
// console.log("motion: " + index);
this.loadBody(); // 不要だけど、何かあったときに表示崩れないように
this.loadTail(index);
this.loadEar(index);
this.loadFace(index);
this.loadEmotion();
this.loadCostume(); // 不要...
this.loadWeapon(); // 不要...
}
updateStand() {
this._costumeKey = $gamePlayer.getCostumeKey();
this.loadBody();
this.loadTail(1);
this.loadEar(1);
this.loadFace(1);
this.loadEmotion();
this.loadCostume();
this.loadWeapon();
}
updateBG() {
let pictName = this._sbgName;
if (!pictName)
pictName = DEFAULT_STAND_BG_NAME;
this._bg.bitmap = ImageManager.loadParallax(pictName);
this._frame.bitmap = ImageManager.loadParallax(DEFAULT_STAND_FRAME_NAME);
}
loadBody() {
switch (this._costumeKey) {
default:
this._body.bitmap = ImageManager.loadPicture(STAND_BODY_NAME);
break;
}
}
loadTail(index) {
switch (this._costumeKey) {
case "bunny": // コスチューム増えたとき用のダミー
this._tail.bitmap = ImageManager.loadPicture(STAND_TAIL_NAME + "_" + index);
break;
default:
this._tail.bitmap = ImageManager.loadPicture(STAND_NONE);
break;
}
}
loadEar(index) {
switch (this._costumeKey) {
case "bunny": // コスチューム増えたとき用のダミー
this._ear.bitmap = ImageManager.loadPicture(STAND_EAR_NAME + "_" + index);
break;
default:
this._ear.bitmap = ImageManager.loadPicture(STAND_NONE);
break;
}
}
loadFace(index) {
switch (this._costumeKey) {
default:
const name = _getFacePath(this._costumeKey, $gameParty.leader());
// this._face.bitmap = ImageManager.loadPicture(name + "_" + index); // 目パチモーション
this._face.bitmap = ImageManager.loadPicture(name);
break;
}
}
loadCostume() {
switch (this._costumeKey) {
default:
const name = _getCostumePath(this._costumeKey, $gameParty.leader());
this._costume.bitmap = ImageManager.loadPicture(name);
break;
}
}
loadWeapon() {
const name = $gameSwitches.value(Kurogoma.SwitchConst.StandWeapon) ? STAND_WEAPON : STAND_NONE;
this._weapon.bitmap = ImageManager.loadPicture(name);
}
loadEmotion() {
const name = _getEmotionPath($gameParty.leader());
this._emotion.bitmap = ImageManager.loadPicture(name);
}
}
// 外からも参照する用
class Map {
static getCurrentFace() {
let faceName = "";
if ($gamePlayer.isHatujo()) {
faceName = "a";
} else if ($gamePlayer.isTorotoro()) {
faceName = "a";
} else if ($gamePlayer.isMuramura()) {
faceName = "a";
} else if ($gameParty.leader().isDying()) {
faceName = "sindoi";
} else if ($gamePlayer.isArmorTaiha()) {
faceName = "a";
} else if ($gamePlayer.isArmorChuuha()) {
faceName = "a";
} else {
faceName = "normal";
}
return faceName;
}
static getStandAreaWidth() {
return STAND_AREA_WIDTH;
}
}
window.Kurogoma = window.Kurogoma || {};
window.Kurogoma.Map = Map;
})();