lewd-hypnosis-city-hypnosm/js/plugins/Keke_VariableActorCommand.js
2026-04-29 12:29:52 -05:00

791 lines
No EOL
27 KiB
JavaScript

//=============================================================================
// Keke_VariableActorCommand - 可変アクターコマンド
// バージョン: 1.1.0
//=============================================================================
// Copyright (c) 2020 ケケー
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================
/*:
* @target MZ
* @plugindesc アクターコマンドを自在に組み替える
* @author ケケー
*
* @help
* 【ver.1.1.0】
* アクターコマンドを自在に組み替えることができる
*
*
*
* ◉ 特徴 ◉
* ■キャラごとにコマンド自由構成
* ■コマンド数に応じたウインドウ自動伸縮
* ■コマンドの動的変更
*
*
*
* ◉ 使い方 ◉
* 設定はデータベースのメモ欄で行う
*
* ■コマンドを追加(削除)
* アクター、職業、装備、スキル、アイテム、ステートのメモ欄に
*
* <コマンド: (-)(コマンド)(/)(タイプ/ID), (表示順), (表示名), (アイコンID)>
*
* ★(-)(コマンド)
* 追加するコマンド。6種類から選ぶ
* ◎攻撃
* 通常攻撃。スキルID 1 のスキル
* ◎防御
* 防御。スキルID 2 のスキル
* ◎スキル
* スキルコマンド。
* ◎アイテム
* アイテムコマンド
* ◎逃げる
* 戦闘から逃げる。パーティコマンド版と同じ
* ◎オート
* 自動戦闘。パーティ全員が自動で戦う
* ※頭に - を付けた場合
* コマンド削除になる
*
* ★(/)(スキルタイプ/ID)
* この部分はスキル/アイテムのときのみ書く。スキルタイプかIDのどちらか
* ◎スキルタイプ
* スキルのときのみ
* スキルタイプ名を書くと、そのスキルタイプがコマンドとして追加される
* ◎ID
* スキルIDを書くと、そのスキル個別がコマンドとして追加される
* アイテムIDならそのアイテム個別
*
* ★(表示順)
* コマンドの表示される順番。数値が小さいほど上に表示される
*
* ★(表示名)
* コマンドの実際に表示される名前。省略可能
* 省略した場合、コマンド本来の名前がそのまま表示される
*
* ★(アイコンID)
* 表示するアイコンのID。省略可能
* 省略すると基本的にはアイコンを表示しないが、
* スキル個別のときのみ、そのスキル本来のアイコンを表示する
*
* ※コマンド追加がひとつでもある時点で、デフォのコマンドは無効化される
*
* ⚫︎具体例
* ◎このようなコマンド構成にする場合
* ブラッドスティア(スキルID162)
* 魔剣技(スキルタイプ『攻撃特技』, アイコンID 76)
* 破壊魔法(スキルタイプ『攻撃魔法』, アイコンID 79)
* 聖魔法(スキルタイプ『回復魔法』, アイコンID 72)
* ハイガード(防御コマンド)
* アイテム(アイテムコマンド, アイコンID 165)
* 逃げる(逃げるコマンド, アイコンID 82)
* オート(自動コマンド, アイコンID 83)
*
* <コマンド:スキル/162,10>
* <コマンド:スキル/攻撃特技,20,魔剣技,76>
* <コマンド:スキル/攻撃魔法,30,破壊魔法,79>
* <コマンド:スキル/回復魔法,40,聖魔法,72>
* <コマンド:防御,50,ハイガード>
* <コマンド:アイテム,60, ,165>
* <コマンド:逃げる,70, ,82>
* <コマンド:オート,80, ,83>
*
* ◎スキルタイプ『攻撃魔法』『回復魔法』をコマンドから消す場合
* <コマンド:-スキル/攻撃魔法>
* <コマンド:-スキル/回復魔法>
*
* ◎スキル『ファイナルスティア』(スキルID164)をコマンドの一番上に追加する場合
* <コマンド:スキル/164,1>
*
*
*
* ◉ 利用規約 ◉
* MITライセンスのもと、自由に使ってくれて大丈夫です
*
*
*
*
*
* @param ウインドウ
*
* @param ウインドウ自動伸縮
* @parent ウインドウ
* @desc ウインドウをコマンド数に応じて自動伸縮させるか
* @type boolean
* @default true
*
* @param ウインドウ伸縮下端
* @parent ウインドウ
* @desc この座標より下には伸びず上に伸びていく
* @default 616
*
* @param ウインドウ不透明度
* @parent ウインドウ
* @desc ウインドウの不透明度(0〜255)
* @default 255
*
* @param アイコン
*
* @param アイコン表示
* @parent アイコン
* @desc アイコンを表示するか
* @type boolean
* @default true
*
* @param アイコンサイズ
* @parent アイコン
* @desc アイコンの大きさ(ピクセル)
* @default 32
*
* @param アイコンX位置
* @parent アイコン
* @desc アイコンのX位置(ピクセル)
* @default -4
*
* @param アイコンY位置
* @parent アイコン
* @desc アイコンのY位置(ピクセル)
* @default 0
*
* @param アイコン配置
* @parent アイコン
* @desc アイコンをウインドウ左に配置するか右に配置するか
* @type select
* @option 左
* @option 右
* @default 左
*
*
* @param タッチボタン
*
* @param キャンセルボタン自動移動
* @parent タッチボタン
* @desc 自動的にキャンセルボタンをコマンド上方に移動するか
* @type boolean
* @default true
*
* @param その他
*
* @param パーティコマンド無効
* @parent その他
* @desc パーティコマンドを表示しなくする
* @type boolean
* @default false
*
* @param 用語・自動戦闘
* @parent その他
* @desc 自動戦闘の呼び方
* @default オート
*/
(() => {
// プラグイン名
const pluginName = "Keke_VariableActorCommand";
//-- パラメータ受け取り --//
const parameters = PluginManager.parameters(pluginName);
// ウインドウ
const keke_windowAutoResize = eval(parameters["ウインドウ自動伸縮"]);
const keke_windowResizeMax = Number(parameters["ウインドウ伸縮下端"]);
const keke_windowOpacity = Number(parameters["ウインドウ不透明度"]);
// アイコン
const keke_iconShow = eval(parameters["アイコン表示"]);
const keke_iconSize = Number(parameters["アイコンサイズ"]);
const keke_iconPosX = Number(parameters["アイコンX位置"]);
const keke_iconPosY = Number(parameters["アイコンY位置"]);
const keke_iconRel = parameters["アイコン配置"];
// タッチボタン
const keke_cancelAutoRepos = eval(parameters["キャンセルボタン自動移動"]);
// その他
const keke_noPartyCommand = eval(parameters["パーティコマンド無効"]);
const keke_autoBattleWord = parameters["用語・自動戦闘"];
//-- プラグインコマンド --//
PluginManager.registerCommand(pluginName, "set", args => {
const tester = Number(args.tester);
});
//-- 共通開始 --//
const _Window_ActorCommand_initialize = Window_ActorCommand.prototype.initialize;
Window_ActorCommand.prototype.initialize = function(rect) {
_Window_ActorCommand_initialize.call(this, rect);
// 変数イニット
this._iconSpritesKe = [];
};
//-- 共通更新 --//
// シーンバトル
const _Scene_Battle_update = Scene_Battle.prototype.update;
Scene_Battle.prototype.update = function() {
_Scene_Battle_update.call(this);
// 自動戦闘の更新
this.updateAutoBattleKe();
};
//-- 共通処理 --//
// コマンドリストの作成
const _Window_ActorCommand_makeCommandList = Window_ActorCommand.prototype.makeCommandList;
Window_ActorCommand.prototype.makeCommandList = function() {
// 独自コマンドリストの作成
if (!this.makeCommandListFreeKe()) {
_Window_ActorCommand_makeCommandList.call(this);
}
// 不透明度
this.opacity = keke_windowOpacity;
// リサイズ
this.resizeKe();
// キャンセルボタンの自動移動
SceneManager._scene.reposCancelButtonKe(this);
};
//-- アクターコマンド自由構成 --//
// 自由コマンドリストの作成
Window_ActorCommand.prototype.makeCommandListFreeKe = function() {
if (!this._actor) { return 0; }
// イニット
let addData = [];
let delData = [];
let match = null;
// コマンドリストのクリア
this.clearCommandList();
// アイコンの消去
this.deleteIconKe();
// メモ欄からコマンドノート取得
const cmdNotes = this._actor.totalAllMetaArrayKeVac(["コマンド", "cmd"]);
// コマンドデータにセット
cmdNotes.forEach(note => {
// イニット
const data = note.split(",");
const type = data[0];
const order = data[1] || 0;
const name = data[2] || "";
const iconIndex = data[3] || 0;
let del = false;
// シンボル取得
let symbol = "";
if (type.includes("攻撃") || type.includes("attack")) { symbol = "attack"; }
if (type.includes("防御") || type.includes("guard")) { symbol = "guard"; }
if (type.includes("スキル") ||type.includes("skill")) { symbol = "skill"; }
if (type.includes("アイテム") || type.includes("item")) { symbol = "item"; }
if (type.includes("逃げる") || type.includes("escape")) { symbol = "escape"; }
if (type.includes("オート") || type.includes("auto")) { symbol = "auto"; }
// シンボルがなければリターン
if (!symbol) { return }
// スキルタイプ/スキル個別取得
let id = 1;
if (symbol == "skill") {
const tps = type.split("/");
if (tps[1]) {
// 数字ならスキル個別
if (tps[1].match(/\d+/)) {
symbol = "skillOne";
id = Number(tps[1]);
// 単語ならスキルタイプ
} else {
const skillType = tps[1].replace(/\s/g, "");
id = $dataSystem.skillTypes.findIndex(name => name && name.replace(/\s/g, "") == skillType);
if (id < 0) { id = 1; }
}
}
}
// アイテム個別取得
if (symbol == "item") {
const tps = type.split("/");
if (tps[1]) {
symbol = "itemOne";
id = Number(tps[1]);
}
}
// 消去かどうか
del = type.startsWith("-") ? true : false;
// 消去セット
if (del) {
delData.push({ symbol:symbol, id:id });
// 追加セット
} else {
addData.push({ symbol:symbol, id:id, name:name, order:order, iconIndex:iconIndex });
}
}, this);
// 追加データを順番に応じてソート
addData.sort((a, b) => a.order - b.order);
// 消去データの分を消去
addData = addData.filter(add => {
const dels = delData.filter(del => del.symbol == add.symbol && del.id == add.id);
return !dels.length;
}, this);
// 重複を削除
const dups = [];
addData = addData.filter((add, i) => {
const duped = dups.filter(dup => dup.symbol == add.symbol && dup.id == add.id).length
dups.push(add);
return !duped;
});
// 追加データからコマンド内容生成
addData.forEach(data => {
$gameSystem._acCmdExtKe = data.iconIndex;
switch (data.symbol) {
case "attack":
this.addCommand(data.name || TextManager.attack, "attack", this._actor.canAttack());
break;
case "guard":
this.addCommand(data.name || TextManager.guard, "guard", this._actor.canGuard());
break;
case "skill":
this.addCommand(data.name || $dataSystem.skillTypes[data.id], "skill", true, data.id);
break;
case "skillOne":
this.addCommand(data.name || $dataSkills[data.id].name, "skillOne", this._actor.canUse($dataSkills[data.id]), data.id);
break;
case "item":
this.addCommand(data.name || TextManager.item, "item");
break;
case "itemOne":
this.addCommand(data.name || $dataItems[data.id].name, "itemOne", this._actor.canUse($dataItems[data.id]), data.id);
break;
case "escape":
this.addCommand(data.name || TextManager.escape, "escape");
break;
case "auto":
this.addCommand(data.name || keke_autoBattleWord, "auto");
break;
}
$gameSystem._acCmdExtKe = null;
}, this);
return addData.length;
};
// 独自コマンドExtの追加
const _Window_ActorCommand_addCommand = Window_ActorCommand.prototype.addCommand;
Window_ActorCommand.prototype.addCommand = function(name, symbol, enabled = true, ext = null) {
_Window_ActorCommand_addCommand.call(this, name, symbol, enabled, ext);
if ($gameSystem._acCmdExtKe) {
const last = this._list[this._list.length - 1];
last.extKe = $gameSystem._acCmdExtKe;
}
};
// 独自コマンドの追加
const _Scene_Battle_createActorCommandWindow = Scene_Battle.prototype.createActorCommandWindow;
Scene_Battle.prototype.createActorCommandWindow = function() {
_Scene_Battle_createActorCommandWindow.call(this);
const acWindow = this._actorCommandWindow;
// 個別スキル
acWindow.setHandler("skillOne", this.commandSkillOneKe.bind(this));
// 個別アイテム
acWindow.setHandler("itemOne", this.commandItemOneKe.bind(this));
// 逃げる
acWindow.setHandler("escape", this.commandEscape.bind(this));
// 自動戦闘
acWindow.setHandler("auto", this.commandAutoBattleKe.bind(this));
};
// コマンド・個別スキル
Scene_Battle.prototype.commandSkillOneKe = function() {
const action = BattleManager.inputtingAction();
if (!action || !action._item) { return; };
const skillId = this._actorCommandWindow.currentExt();
action.setSkill(skillId);
this.onSelectAction();
};
// コマンド・個別アイテム
Scene_Battle.prototype.commandItemOneKe = function() {
const action = BattleManager.inputtingAction();
if (!action || !action._item) { return; };
const itemId = this._actorCommandWindow.currentExt();
console.log(itemId);
action.setItem(itemId);
this.onSelectAction();
};
// アイコン描画呼び出し
const _Window_ActorCommand_drawItem = Window_ActorCommand.prototype.drawItem;
Window_ActorCommand.prototype.drawItem = function(index) {
this._index = index;
this.drawIconKe();
_Window_ActorCommand_drawItem.call(this, index);
};
// アイコン描画
Window_ActorCommand.prototype.drawIconKe = function() {
if (!keke_iconShow) { return; }
// イニット
const symbol = this.currentSymbol();
const id = this.currentExt();
let iconIndex = this.currentData() ? this.currentData().extKe : null;
const rect = this.itemLineRect(this._index);
const scene = SceneManager._scene;
const wPad = $gameSystem.windowPadding();
const attackId = this._actor.attackSkillId();
const guardId = this._actor.guardSkillId();
const iconW = ImageManager.iconWidth;
const iconH = ImageManager.iconHeight;
const isRight = keke_iconRel == "右";
// スキルアイコンがあったら取得
if (symbol == "attack" && !iconIndex) { iconIndex = $dataSkills[attackId] ? $dataSkills[attackId].iconIndex : 0; }
if (symbol == "guard" && !iconIndex) { iconIndex = iconIndex = $dataSkills[guardId] ? $dataSkills[guardId].iconIndex : 0;; }
if (symbol == "skillOne" && !iconIndex) { iconIndex = $dataSkills[id] ? $dataSkills[id].iconIndex : 0; }
if (symbol == "itemOne" && !iconIndex) { iconIndex = $dataItems[id] ? $dataItems[id].iconIndex : 0; }
// アイコン描画
if (iconIndex) {
// スプライト形成
const iconSprite = $gameSystem.makeIconSpriteKeVac(iconIndex);
scene.addChild(iconSprite);
this._iconSpritesKe.push(iconSprite);
// 拡大
const iconTw = keke_iconSize;
const scale = iconTw / iconW;
iconSprite.scale.x = scale;
iconSprite.scale.y = scale
// 位置
iconSprite.x = this.x + wPad + rect.x + (isRight ? rect.width + iconTw / 2 - keke_iconPosX : - iconTw / 2 + keke_iconPosX);
iconSprite.y = this.y + wPad + rect.y + iconTw / 2 + (rect.height - iconTw * 0.75) / 2 + keke_iconPosY;
}
};
// アイコンの消去
Window_ActorCommand.prototype.deleteIconKe = function() {
if (!this._iconSpritesKe.length) { return; }
const scene = SceneManager._scene;
this._iconSpritesKe.forEach(sprite => scene.removeChild(sprite));
this._iconSpritesKe = [];
};
// ウインドウ閉じるときアイコンも消す
const _Window_ActorCommand_close = Window_ActorCommand.prototype.close;
Window_ActorCommand.prototype.close = function() {
_Window_ActorCommand_close.call(this);
this.deleteIconKe();
};
// ウインドウを出すときアイコンも出す
const _Window_ActorCommand_show = Window_ActorCommand.prototype.show;
Window_ActorCommand.prototype.show = function() {
_Window_ActorCommand_show.call(this);
this._iconSpritesKe.forEach(sprite => sprite.visible = true);
};
// ウインドウを消すときアイコンも消す
const _Window_ActorCommand_hide = Window_ActorCommand.prototype.hide;
Window_ActorCommand.prototype.hide = function() {
_Window_ActorCommand_hide.call(this);
this._iconSpritesKe.forEach(sprite => sprite.visible = false);
};
//-- アクターコマンド自動伸縮 --//
// リサイズ
Window_ActorCommand.prototype.resizeKe = function() {
// 自動伸縮でなければリターン
if (!keke_windowAutoResize) { return; }
// 基本のY位置を保存
if (this._oriYKe == null) { this._oriYKe = this.y; }
// コマンド数取得
let cmdNum = this._list.length;
// ハイト変更
this.height = this.fittingHeight(cmdNum) * 1;
// ウインドウ下端
const downMax = this._oriYKe + this.fittingHeight(cmdNum);
// 画面外に出ないようにする
this.y = this._oriYKe;
if (downMax > keke_windowResizeMax) { this.y -= downMax - keke_windowResizeMax; }
};
// ハイト拡大
const _Scene_Battle_actorCommandWindowRect = Scene_Battle.prototype.actorCommandWindowRect;
Scene_Battle.prototype.actorCommandWindowRect = function() {
let result = _Scene_Battle_actorCommandWindowRect.call(this);
// 自動伸縮時のみ
if (keke_windowAutoResize) { result.height = Graphics.height; }
return result;
};
// キャンセルボタンのリポズ
Scene_Battle.prototype.reposCancelButtonKe = function(window) {
if (!keke_cancelAutoRepos) { return; }
if (!this._cancelButton) { return; }
const isLeft = !SceneManager._scene.isRightInputMode();
this._cancelButton.x = isLeft ? 0 : this._cancelButton.x;
this._cancelButton.y = window.y - this._cancelButton.height - 4;
};
//-- 自動戦闘 --//
// 自動戦闘フラグ
const _Game_BattlerBase_isAutoBattle = Game_BattlerBase.prototype.isAutoBattle;
Game_BattlerBase.prototype.isAutoBattle = function() {
let result = _Game_BattlerBase_isAutoBattle.call(this);
if (this._autoBattleKe) { result = true; }
return result;
};
// コマンド・自動戦闘
Scene_Battle.prototype.commandAutoBattleKe = function() {
// 個別フラグオン
$gameParty.battleMembers().forEach(actor => {
actor._autoBattleKe = true;
actor.makeAutoBattleActions();
}, this);
// 全体フラグオン
this._inAutoBattleKe = true;
// ウインドウ閉じる
this.closeCommandWindows();
this.selectNextCommand();
};
// コマンド・自動戦闘(個別)
Scene_Battle.prototype.commandAutoBattleOneKe = function() {
// 個別フラグオン
const actor = BattleManager.actor();
// アクターがいないならリターン
if (!actor) { return; }
actor._autoBattleKe = true;
// 全体フラグオン
this._inAutoBattleKe = true;
// アクション作成
actor.makeAutoBattleActions();
// ウインドウ閉じる
this.closeCommandWindows();
this.selectNextCommand();
};
// 自動戦闘の解除
Scene_Battle.prototype.endAutoBattleKe = function() {
// 個別フラグオフ
$gameParty.battleMembers().forEach(actor => {
actor._autoBattleKe = false;
}, this);
// 全体フラグオフ
this._inAutoBattleKe = false;
};
// 自動戦闘の解除(ボタン)
Scene_Battle.prototype.endAutoBattleBtnKe = function() {
// 自動戦闘の解除
this.endAutoBattleKe();
// サウンド
SoundManager.playCancel();
};
// 自動戦闘の更新
Scene_Battle.prototype.updateAutoBattleKe = function() {
// 自動戦闘中、キャンセルボタンか画面タッチで
if (this._inAutoBattleKe && (Input.isTriggered("ok") || Input.isTriggered("cancel") || TouchInput.isTriggered())) {
// 自動戦闘終了
this.endAutoBattleBtnKe();
}
};
// 戦闘終了時に自動戦闘解除
const _Scene_Battle_terminate = Scene_Battle.prototype.terminate;
Scene_Battle.prototype.terminate = function() {
_Scene_Battle_terminate.call(this);
this.endAutoBattleKe();
};
//-- パーティコマンド無効 --//
const _Scene_Battle_changeInputWindow = Scene_Battle.prototype.changeInputWindow;
Scene_Battle.prototype.changeInputWindow = function() {
// パーティコマンド無効なら
if (keke_noPartyCommand) {
// カレントアクターが空になったら
if (BattleManager.isInputting() && !BattleManager.actor()) {
// 次のインプット可アクターをセット
for (const actor of $gameParty.battleMembers()) {
if (actor.canInput()) {
BattleManager._currentActor = actor;
break;
}
}
// インプット可アクターがいないならコマンド終了
if (!BattleManager._currentActor) {
this.endCommandSelection();
return;
}
}
}
_Scene_Battle_changeInputWindow.call(this);
};
//-- メタ配列 /ベーシック --//
// 全てのメタ配列を合算
Game_Battler.prototype.totalAllMetaArrayKeVac = function(words) {
// イニット
let data = null
let array = [];
// バトラー値
data = this.actorId ? this.actor() : this.enemy();
if (data) { this.getMetaArrayKeVac(data.note, words).forEach(e => array.push(e)); }
if (this._actorId) {
// 職業値
data = this.currentClass();
if (data) { this.getMetaArrayKeVac(data.note, words).forEach(e => array.push(e)); }
// 装備値
this._equips.forEach(equip => {
data = equip.object();
if (data) { this.getMetaArrayKeVac(data.note, words).forEach(e => array.push(e)); }
}, this);
}
// ステート値
this._states.forEach(stateId => {
data = $dataStates[stateId];
if (data) { this.getMetaArrayKeVac(data.note, words).forEach(e => array.push(e)); }
}, this);
// アクション値
const actions = [BattleManager._action];
const chainRun = BattleManager._chainRunActionKe;
if (chainRun && chainRun != BattleManager._action) { actions.push(BattleManager._chainRunActionKe); }
for (const action of actions) {
if (!action) { continue; }
data = action.item();
if (data) { this.getMetaArrayKeVac(data.note, words).forEach(e => array.push(e)); }
}
// スペース削除
array = array.map(e => e.replace(/\s/g, ""));
// 空の要素は削除
array = array.filter(e => e);
return array;
};
// メタ配列を取得
Game_Battler.prototype.getMetaArrayKeVac= function(note, words) {
return $gameSystem.metaAllKeVac(note, words);
};
//-- 全取得メタ --//
Game_System.prototype.metaAllKeVac = function(note, words) {
var result = [];
words.forEach(word => {
var regText = '\<' + word + ':([^\>]*)\>';
var regExp_g = new RegExp(regText, 'g');
var regExp = new RegExp(regText);
var matches = note.match(regExp_g);
var match = null;
if (matches) {
matches.forEach(function(line) {
result.push(line.match(regExp)[1]);
}, this);
}
}, this);
return result;
};
//-- アイコンスプライト /ベーシック --//
// アイコンスプライト作成
Game_System.prototype.makeIconSpriteKeVac = function(iconIndex) {
const sprite = new Sprite();
sprite.anchor.x = 0.5;
sprite.anchor.y = 0.5;
const bitmap = ImageManager.loadSystem("IconSet");
sprite.bitmap = bitmap;
const pw = ImageManager.iconWidth;
const ph = ImageManager.iconHeight;
const sx = (iconIndex % 16) * pw;
const sy = Math.floor(iconIndex / 16) * ph;
sprite.setFrame(sx, sy, pw, ph);
return sprite;
};
})();