lewd-hypnosis-city-hypnosm/js/plugins/NRP_ClassChangeScene.js
2026-04-28 07:32:15 -05:00

2714 lines
80 KiB
JavaScript
Raw 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.

//=============================================================================
// NRP_ClassChangeScene.js
//=============================================================================
/*:
* @target MZ
* @plugindesc v1.042 A class change system will be implemented.
* @author Takeshi Sunagawa (http://newrpg.seesaa.net/)
* @url http://newrpg.seesaa.net/article/483459448.html
*
* @help A class change system will be implemented.
*
* ◆Main Features
* - Displays parameter changes
* and learnable skills after class change.
* - Can set up an advanced class that can change classes
* when the conditions are met.
* - Class change commands can be added to the menu screen.
* - Different images can be specified for different professions and actors.
* (Face, Character, Battler)
*
* ------------------------------------------
* ■Usage
* ------------------------------------------
* Register your candidate professions
* in the "ClassList" of the plugin parameters.
* You can also set the class change condition at that time.
* Classes that do not meet the conditions will not be displayed.
*
* It is also possible to display different images
* for each class and actor by registering face graphics
* and pictures in "ClassImageList".
*
* If you execute the following plugin command,
* the class change screen will be displayed.
* If you turn on "ShowMenuCommand",
* you can also call it from the menu screen.
*
* ------------------------------------------
* ■Plugin Command
* ------------------------------------------
* ◆SceneStart
* Call the class change screen.
* You can specify the actor to be the target of the class change.
* If you do not specify, the actors' selection screen
* will be displayed first.
*
* You can also specify an additional ClassList.
* This is useful, for example, for professions
* that can only be class changed in certain locations.
*
* ------------------------------------------
* ■Note of Classes
* ------------------------------------------
* If you write the following, the description
* will be displayed on the class change screen.
* Line breaks and control characters are also possible.
*
* <ClassMessage>
* ~Text~
* </ClassMessage>
*
* [Terms]
* There are no restrictions.
* Modification, redistribution freedom, commercial availability,
* and rights indication are also optional.
* The author is not responsible,
* but will deal with defects to the extent possible.
*
* @command SceneStart
* @desc Call the class change screen. If no actor is specified, the selection screen for actors is also displayed.
*
* @arg Actor
* @type actor
* @desc This is the actor to be targeted. If not specified, the screen for selecting actors will be displayed.
*
* @arg VariableActor
* @type variable
* @desc Specify the target actor as a variable.
* This one has priority.
*
* @arg AddClassList
* @type struct<Class>[]
* @desc This is the additional ClassList.
* Combine with the ClassList of the plugin parameter.
*
*
*
* @param ClassList
* @type struct<Class>[]
* @desc This is a list of targets for class change.
* Register, including conditions.
*
* @param KeepExp
* @type boolean
* @default false
* @desc Make sure that experience is retained during class changes.
*
* @param NoDuplicate
* @type boolean
* @default false
* @desc It is prohibited to have multiple actors change classes to the same class.
*
* @param ClassChangeMessage
* @type string
* @desc This is the message when changing classes.
* %1=Actor, %2=Class。blank to hide.
*
* @param SoundSuccess
* @type file
* @dir audio/se
* @desc The sound effect when a class change is successfully.
* If not specified, the default decision sound will be played.
*
* @param <Layout>
* @desc Items related to the layout of the class change screen.
*
* @param SortClassId
* @parent <Layout>
* @type boolean
* @default false
* @desc Sorts the list in ClassId order.
*
* @param ClassListWidth
* @parent <Layout>
* @type number
* @default 280
* @desc The width of the Class List.
*
* @param DisplayListLevel
* @parent <Layout>
* @type boolean
* @default true
* @desc Displays the level in the Class List.
*
* @param MessageFontSize
* @parent <Layout>
* @type number
* @desc This is the font size of the class description.
* If not specified, use the system setting.
*
* @param DisplayParameters
* @parent <Layout>
* @type string
* @default 0,1,2,3,4,5,6,7
* @desc The parameter to display. Default: 0,1,2,3,4,5,6,7
* 0: MHP to 7: Luck.
*
* @param ParamFontSize
* @parent <Layout>
* @type number
* @desc This is the font size of the class parameters.
* If not specified, use the system setting.
*
* @param ParamLineHeight
* @parent <Layout>
* @type number
* @default 36
* @desc The height of a single line of the class parameters.
* Default:36
*
* @param <Layout Image>
* @desc This item is used to set the image for the class change screen.
*
* @param ClassImageList
* @parent <Layout Image>
* @type struct<ClassImage>[]
* @desc This is a list for setting images for each class and actor.
*
* @param UseClassImage
* @parent <Layout Image>
* @type boolean
* @default true
* @desc The images (other than pictures) set in ClassImageList will be reflected in the battle, menu, and other.
*
* @param ReverseImagePos
* @parent <Layout Image>
* @type boolean
* @default false
* @desc Reverses the placement of parameters and images left and right.
*
* @param PictureOnScroll
* @parent <Layout Image>
* @type boolean
* @default true
* @desc Link the picture to the up/down scroll.
*
* @param PictureAdjustX
* @parent <Layout Image>
* @type number @min -9999 @max 9999
* @default 0
* @desc Adjusts the x-coordinate for displaying the picture.
*
* @param PictureAdjustY
* @parent <Layout Image>
* @type number @min -9999 @max 9999
* @default 0
* @desc Adjusts the y-coordinate for displaying the picture.
*
* @param PictureOpacity
* @parent <Layout Image>
* @type number
* @default 128
* @desc The opacity of the picture.
*
* @param <Learn Skills>
* @desc These are the related items of learned skills.
*
* @param ShowSkillsType
* @parent <Learn Skills>
* @type select
* @option No display @value
* @option Show under @value under
* @option Display other page @value page
* @default page
* @desc Set the placement to display the learned skills in the class information.
*
* @param ShowUnlearnedSkills
* @parent <Learn Skills>
* @type select
* @option No display @value
* @option Display @value show
* @option Mask Display @value mask
* @default mask
* @desc Displays unlearned skills in class information.
*
* @param SkillFontSize
* @parent <Learn Skills>
* @type number
* @desc The font size of the skill name.
* If not specified, use the system setting.
*
* @param <Menu Command>
* @desc This is a related item for displaying class changes in menu commands.
*
* @param ShowMenuCommand
* @parent <Menu Command>
* @type boolean
* @default false
* @desc Add class change to the menu command.
*
* @param ShowMenuCommandPosition
* @parent <Menu Command>
* @type number
* @default 3
* @desc This is the position to insert the class change into the menu command. 0 is the first position.
*
* @param ClassChangeName
* @parent <Menu Command>
* @type text
* @default Class Change
* @desc Sets the display command name for the class change.
*
* @param MenuCommandSwitch
* @parent <Menu Command>
* @type switch
* @desc Displays the command only when the switch is on.
* If it is blank, it will always be displayed.
*
* @param ClassChangeSymbol
* @parent <Menu Command>
* @type text
* @default classchange
* @desc Sets the symbol for the class change.
* This value can be used when working with other plugins.
*/
/*~struct~Class:
* @param Class
* @type class
* @desc It is subject to class change.
*
* @param Condition
*
* @param Actors
* @parent Condition
* @type actor[]
* @desc This is a candidate for actors that allow class changes.
*
* @param Switch
* @parent Condition
* @type switch
* @desc This switch is a class change requirement.
*
* @param Item
* @parent Condition
* @type item
* @desc This item is a class change requirement.
*
* @param ClassInfo
* @parent Condition
* @type struct<ClassInfo>[]
* @desc Class information for class change conditions.
*
* @param Script
* @parent Condition
* @type string
* @desc The script for the class change condition.
* e.g. a.level >= 10
*/
/*~struct~ClassInfo:
* @param Class
* @type class
* @desc This class is a condition for class change.
*
* @param Level
* @type number
* @desc The class level that is a requirement for class change.
*/
/*~struct~ClassImage:
* @param <Target>
*
* @param Class
* @parent <Target>
* @type class
* @desc This is the target class.
*
* @param Actor
* @parent <Target>
* @type actor
* @desc This is the target actor.
*
* @param <Image>
*
* @param Face
* @parent <Image>
* @type file
* @dir img/faces
* @desc This is the file of the face graphic to be displayed.
* Use this file in combination with the index below.
*
* @param FaceIndex
* @parent <Image>
* @type number
* @desc Index of the face graphic.
* If the face graphic is omitted, the current file is used.
*
* @param Picture
* @parent <Image>
* @type file
* @dir img/pictures
* @desc Specify the picture to be displayed.
* Overrides the face graphic.
*
* @param Character
* @parent <Image>
* @type file
* @dir img/characters
* @desc The file of the character image to be used.
* Use this file in combination with the index below.
*
* @param CharacterIndex
* @parent <Image>
* @type number
* @desc Index of the character graphic.
* If the character graphic is omitted, the current file is used.
*
* @param Battler
* @parent <Image>
* @type file
* @dir img/sv_actors
* @desc The file of the SV actor image to be used.
*/
/*:ja
* @target MZ
* @plugindesc v1.042 転職システムを実装する。
* @author 砂川赳http://newrpg.seesaa.net/
* @url http://newrpg.seesaa.net/article/483459448.html
*
* @help 転職システムを実装します。
*
* ◆主な機能
* ・転職後の能力変化や習得スキルを表示
* ・条件を満たした場合に転職できる上級職などを設定可
* ・メニュー画面に転職用のコマンドを追加可
* ・職業やアクター毎に異なる画像を指定可
*  (顔グラ、キャラグラ、バトラー)
*
* ------------------------------------------
* ■使用方法
* ------------------------------------------
* プラグインパラメータの『職業一覧』に、候補となる職業を登録してください。
* その際、転職条件の設定も可能です。
* 条件を満たさない職業は表示されません。
*
* また、『職業画像一覧』に顔グラフィックやピクチャーを登録することで、
* 職業やアクター毎に異なる画像を表示することも可能です。
*
* 下記のプラグインコマンドを実行すれば、転職画面が表示されます。
* 『メニューコマンドに表示』をオンにすれば、
* メニュー画面から呼び出すことも可能です。
*
* ------------------------------------------
* ■プラグインコマンド
* ------------------------------------------
* ◆シーン開始
* 転職画面を呼び出します。
* 転職の対象とするアクターを指定可能です。
* 指定しなかった場合は、アクターの選択画面が事前に表示されます。
*
* また、追加の職業一覧を指定可能です。
* 例えば、特定の場所でのみ転職可能な職業などに便利です。
*
* ------------------------------------------
* ■職業のメモ欄
* ------------------------------------------
* 以下のように記述すれば、転職画面に説明が表示されます。
* 改行や制御文字も可能です。
*
* <ClassMessage>
* ~表示したい文章~
* </ClassMessage>
*
* ■利用規約
* 特に制約はありません。
* 改変、再配布自由、商用可、権利表示も任意です。
* 作者は責任を負いませんが、不具合については可能な範囲で対応します。
*
* @command SceneStart
* @text シーン開始
* @desc 転職画面を呼び出します。
* アクターを指定しない場合は、アクター選択画面も表示。
*
* @arg Actor
* @text アクター
* @type actor
* @desc 対象とするアクターです。
* 指定がない場合は、アクターの選択画面を表示します。
*
* @arg VariableActor
* @text アクター(変数指定)
* @type variable
* @desc 対象とするアクターを変数で指定します。
* こちらのほうが優先されます。
*
* @arg AddClassList
* @text 職業一覧(追加)
* @type struct<Class>[]
* @desc 転職の対象となる職業一覧の追加分です。
* プラグインパラメータの職業一覧に結合します。
*
*
*
* @param ClassList
* @text 職業一覧
* @type struct<Class>[]
* @desc 転職の対象となる職業一覧です。
* 転職条件なども含めて登録してください。
*
* @param KeepExp
* @text 経験値の保存
* @type boolean
* @default false
* @desc 転職時に経験値を維持するようにします。
*
* @param NoDuplicate
* @text 職業の重複禁止
* @type boolean
* @default false
* @desc 同一の職業へ複数のアクターが転職することを禁止します。
*
* @param ClassChangeMessage
* @text 転職時のメッセージ
* @type string
* @desc 転職時のメッセージです。
* %1=アクター, %2=職業。空白で非表示します。
*
* @param SoundSuccess
* @text 成功時の効果音
* @type file
* @dir audio/se
* @desc 転職に成功した際の効果音です。
* 指定がない場合はデフォルトの決定音を鳴らします。
*
* @param <Layout>
* @text <レイアウト関連>
* @desc 転職画面のレイアウト関連項目です。
*
* @param SortClassId
* @parent <Layout>
* @text 職業IDで並び替え
* @type boolean
* @default false
* @desc 職業ID順で一覧を並び替えます。
*
* @param ClassListWidth
* @parent <Layout>
* @text 職業一覧の横幅
* @type number
* @default 280
* @desc 職業一覧の横幅です。
*
* @param DisplayListLevel
* @parent <Layout>
* @text 一覧にレベルを表示
* @type boolean
* @default true
* @desc 職業一覧にレベルを表示します。
*
* @param MessageFontSize
* @parent <Layout>
* @text 説明文のフォントサイズ
* @type number
* @desc 職業の説明文のフォントサイズです。
* 未指定ならシステム設定を使います。
*
* @param DisplayParameters
* @parent <Layout>
* @text 表示するパラメータ
* @type string
* @default 0,1,2,3,4,5,6,7
* @desc 表示するパラメータです。初期値0,1,2,3,4,5,6,7
* 0:最大7:運となります。
*
* @param ParamFontSize
* @parent <Layout>
* @text パラメータのフォントサイズ
* @type number
* @desc 職業のパラメータのフォントサイズです。
* 未指定ならシステム設定を使います。
*
* @param ParamLineHeight
* @parent <Layout>
* @text パラメータの一行縦幅
* @type number
* @default 36
* @desc 職業のパラメータの一行の縦幅です。
* 初期値は36。
*
* @param <Layout Image>
* @text <レイアウト画像関連>
* @desc 転職画面に画像を設定するための項目です。
*
* @param ClassImageList
* @parent <Layout Image>
* @text 職業画像一覧
* @type struct<ClassImage>[]
* @desc 職業やアクター毎の画像を設定するリストです。
*
* @param UseClassImage
* @parent <Layout Image>
* @text 画像を他画面に反映
* @type boolean
* @default true
* @desc 職業画像一覧に設定した画像(ピクチャー以外)を、戦闘やメニューなどにも反映します。
*
* @param ReverseImagePos
* @parent <Layout Image>
* @text 画像配置の左右反転
* @type boolean
* @default false
* @desc パラメータと画像の配置を左右反転します。
*
* @param PictureOnScroll
* @parent <Layout Image>
* @text ピクチャーのスクロール連動
* @type boolean
* @default true
* @desc ピクチャーを上下のスクロールに連動します。
*
* @param PictureAdjustX
* @parent <Layout Image>
* @text ピクチャーX補正
* @type number @min -9999 @max 9999
* @default 0
* @desc ピクチャーを表示するX座標を調整します。
*
* @param PictureAdjustY
* @parent <Layout Image>
* @text ピクチャーY補正
* @type number @min -9999 @max 9999
* @default 0
* @desc ピクチャーを表示するY座標を調整します。
*
* @param PictureOpacity
* @parent <Layout Image>
* @text ピクチャー不透明度
* @type number
* @default 128
* @desc ピクチャーの不透明度です。
*
* @param <Learn Skills>
* @text <習得スキル関連>
* @desc 習得スキルの関連項目です。
*
* @param ShowSkillsType
* @parent <Learn Skills>
* @text 習得スキルの表示位置
* @type select
* @option 表示しない @value
* @option 下に表示 @value under
* @option 別ページに表示 @value page
* @default page
* @desc 職業情報に習得スキルを表示する配置を設定します。
*
* @param ShowUnlearnedSkills
* @parent <Learn Skills>
* @text 未習得のスキル表示
* @type select
* @option 表示しない @value
* @option 表示 @value show
* @option マスク表示 @value mask
* @default mask
* @desc 職業情報に未習得のスキルを表示します。
*
* @param SkillFontSize
* @parent <Learn Skills>
* @text スキルのフォントサイズ
* @type number
* @desc スキル名のフォントサイズです。
* 未指定ならシステム設定を使います。
*
* @param <Menu Command>
* @text <メニューコマンド関連>
* @desc メニューコマンドに転職を表示する際の関連項目です。
*
* @param ShowMenuCommand
* @parent <Menu Command>
* @text メニューコマンドに表示
* @type boolean
* @default false
* @desc メニューコマンドに転職を追加します。
*
* @param ShowMenuCommandPosition
* @parent <Menu Command>
* @text メニューコマンド挿入位置
* @type number
* @default 3
* @desc メニューコマンドに転職を挿入する位置です。
* 0が先頭になります。
*
* @param ClassChangeName
* @parent <Menu Command>
* @text 転職表示名
* @type text
* @default 転職
* @desc 転職の表示コマンド名を設定します。
*
* @param MenuCommandSwitch
* @parent <Menu Command>
* @text 表示許可するスイッチ
* @type switch
* @desc スイッチがオンの時のみコマンドを表示します。
* 空白なら常に表示します。
*
* @param ClassChangeSymbol
* @parent <Menu Command>
* @text [上級]転職記号
* @type text
* @default classchange
* @desc 転職の記号を設定します。
* この値は他のプラグインと連携する際に使用できます。
*/
/*~struct~Class:ja
* @param Class
* @text 職業
* @type class
* @desc 転職対象とする職業です。
*
* @param Condition
* @text <転職条件>
*
* @param Actors
* @parent Condition
* @text アクター(配列)
* @type actor[]
* @desc 転職を許可するアクターの候補です。
*
* @param Switch
* @parent Condition
* @text スイッチ
* @type switch
* @desc 転職条件となるスイッチです。
*
* @param Item
* @parent Condition
* @text アイテム
* @type item
* @desc 転職条件となるアイテムです。
*
* @param ClassInfo
* @parent Condition
* @text 職業情報(配列)
* @type struct<ClassInfo>[]
* @desc 転職条件となる職業情報です。
*
* @param Script
* @parent Condition
* @text スクリプト
* @type string
* @desc 転職条件となるスクリプトです。
* 例a.level >= 10
*/
/*~struct~ClassInfo:ja
* @param Class
* @text 職業
* @type class
* @desc 転職の条件とする職業です。
*
* @param Level
* @text レベル
* @type number
* @desc 転職の条件とする職業のレベルです。
*/
/*~struct~ClassImage:ja
* @param <Target>
* @text <設定対象>
*
* @param Class
* @parent <Target>
* @text 職業
* @type class
* @desc 対象の職業です。
*
* @param Actor
* @parent <Target>
* @text アクター
* @type actor
* @desc 対象のアクターです。
*
* @param <Image>
* @text <画像>
*
* @param Face
* @parent <Image>
* @text 顔グラフィック
* @type file
* @dir img/faces
* @desc 表示する顔グラフィックのファイルです。
* 下のインデックスと組み合わせてください。
*
* @param FaceIndex
* @parent <Image>
* @text 顔インデックス
* @type number
* @desc 顔グラフィックのインデックスです。
* 顔グラフィックを省略すると現在のファイルを使用します。
*
* @param Picture
* @parent <Image>
* @text ピクチャー
* @type file
* @dir img/pictures
* @desc 表示するピクチャーを指定します。
* 顔グラフィックよりも優先されます。
*
* @param Character
* @parent <Image>
* @text キャラクター画像
* @type file
* @dir img/characters
* @desc 使用するキャラクター画像のファイルです。
* 下のインデックスと組み合わせてください。
*
* @param CharacterIndex
* @parent <Image>
* @text キャラクターインデックス
* @type number
* @desc キャラクター画像のインデックスです。
* キャラクター画像を省略すると現在のファイルを使用します。
*
* @param Battler
* @parent <Image>
* @text SVアクター画像
* @type file
* @dir img/sv_actors
* @desc 使用するSVアクター画像のファイルです。
*/
(function() {
"use strict";
/**
* ●構造体をJSで扱えるように変換
*/
function parseStruct1(arg) {
const ret = [];
if (arg) {
for (const str of JSON.parse(arg)) {
ret.push(str);
}
}
return ret;
}
/**
* ●構造体二重配列をJSで扱えるように変換
*/
function parseStruct2(arg) {
const ret = [];
if (arg) {
for (const str of JSON.parse(arg)) {
ret.push(JSON.parse(str));
}
}
return ret;
}
function toBoolean(str, def) {
if (str === true || str === "true") {
return true;
} else if (str === false || str === "false") {
return false;
}
return def;
}
function toNumber(str, def) {
if (str == undefined || str == "") {
return def;
}
return isNaN(str) ? def : +(str || def);
}
function setDefault(str, def) {
if (str == undefined || str == "") {
return def;
}
return str;
}
const PLUGIN_NAME = "NRP_ClassChangeScene";
const parameters = PluginManager.parameters(PLUGIN_NAME);
const pClassList = parseStruct2(parameters["ClassList"]);
const pKeepExp = toBoolean(parameters["KeepExp"], false);
const pNoDuplicate = toBoolean(parameters["NoDuplicate"], false);
const pClassChangeMessage = setDefault(parameters["ClassChangeMessage"]);
const pSoundSuccess = parameters["SoundSuccess"];
const pSortClassId = toBoolean(parameters["SortClassId"], false);
const pClassListWidth = toNumber(parameters["ClassListWidth"], 280);
const pDisplayListLevel = toBoolean(parameters["DisplayListLevel"], true);
const pMessageFontSize = toNumber(parameters["MessageFontSize"]);
const pDisplayParameters = setDefault(parameters["DisplayParameters"], "");
const pParamFontSize = toNumber(parameters["ParamFontSize"]);
const pParamLineHeight = toNumber(parameters["ParamLineHeight"], 36);
const pClassImageList = parseStruct2(parameters["ClassImageList"]);
const pUseClassImage = toBoolean(parameters["UseClassImage"], true);
const pReverseImagePos = toBoolean(parameters["ReverseImagePos"], false);
const pPictureOnScroll = toBoolean(parameters["PictureOnScroll"], true);
const pPictureAdjustX = toNumber(parameters["PictureAdjustX"], 0);
const pPictureAdjustY = toNumber(parameters["PictureAdjustY"], 0);
const pPictureOpacity = toNumber(parameters["PictureOpacity"], 255);
const pShowSkillsType = parameters["ShowSkillsType"];
const pShowUnlearnedSkills = parameters["ShowUnlearnedSkills"];
const pSkillFontSize = toNumber(parameters["SkillFontSize"]);
const pShowMenuCommand = toBoolean(parameters["ShowMenuCommand"], false);
const pShowMenuCommandPosition = toNumber(parameters["ShowMenuCommandPosition"], 3);
const pClassChangeName = parameters["ClassChangeName"];
const pMenuCommandSwitch = toNumber(parameters["MenuCommandSwitch"]);
const pClassChangeSymbol = parameters["ClassChangeSymbol"];
//----------------------------------------
// MZ用プラグインコマンド
//----------------------------------------
// MVには存在しないため、空で定義しておかないとエラーになる。
if (!PluginManager.registerCommand) {
PluginManager.registerCommand = function() {}
}
/** 転職対象となる職業一覧 */
let mClassList = null;
/** アクターの変更禁止 */
let mActorNoChange = false;
/**
* ●シーン開始
*/
PluginManager.registerCommand(PLUGIN_NAME, "SceneStart", function(args) {
// アクターを取得
const actor = getActor(args);
// 対象に設定
if (actor) {
$gameParty.setMenuActor(actor);
mActorNoChange = true;
// 指定がない場合はクリア
} else {
$gameParty._menuActorId = 0;
mActorNoChange = false;
}
// 職業一覧の生成
mClassList = pClassList;
if (args.AddClassList) {
// プラグインコマンドの場合は、
// なぜか謎の文字コード001Bが含まれているので\に変換
let addClassList = args.AddClassList.replace(/\u001B/g, "\\");
// JSON形式をJS用に変換
addClassList = parseStruct2(addClassList);
// リストを結合
mClassList = mClassList.concat(addClassList);
}
// ID順で並び替え
if (pSortClassId) {
mClassList.sort((a, b) => a.Class - b.Class);
}
// 職業一覧を編集
mClassList = editClassList(mClassList);
// 選択肢ウィンドウが存在する場合は非表示
// ※ゴミが残らないようにするため
if (SceneManager._scene._choiceListWindow) {
SceneManager._scene._choiceListWindow.hide();
}
// シーン開始
SceneManager.push(Scene_ClassChange);
});
//----------------------------------------
// 共通関数
//----------------------------------------
/**
* ●アクターを取得
*/
function getActor(args) {
let actorId = setDefault(args.Actor);
// 変数の指定がある場合は優先
const variablActor = setDefault(args.VariableActor);
if (variablActor) {
actorId = $gameVariables.value(variablActor);
}
// アクターを取得
const actor = $gameActors.actor(actorId);
return actor;
}
/**
* ●職業一覧を編集する。
*/
function editClassList(classList) {
for (const classInfo of classList) {
classInfo.class = classInfo.Class;
classInfo.actors = parseStruct1(classInfo.Actors);
classInfo.switch = toNumber(classInfo.Switch);
classInfo.item = toNumber(classInfo.Item);
classInfo.classInfo = classInfo.ClassInfo;
classInfo.script = classInfo.Script;
}
return classList;
}
//----------------------------------------
// 職業レベルの取得
//----------------------------------------
/**
* ●経験値から職業のレベルを計算
*/
function getClassLevel(actor, classId) {
const exp = actor._exp[classId];
let level = 1;
// 処理高速化のため先に中間レベルをチェックしてもよいかも?
// exp >= this.expForLevel(50); みたいな感じで
// 再帰的に現在のレベルを求める。
while (!isMaxLevel(actor, level) && exp >= nextLevelExp(actor, classId, level)) {
level++;
}
return level;
};
/**
* ●職業がアクターの最大レベルになっているか?
*/
function isMaxLevel(actor, level) {
return level >= actor.maxLevel();
};
/**
* ●次のレベルの経験値を取得
*/
function nextLevelExp(actor, classId, level) {
return expForLevel(actor, classId, level + 1);
};
// 一時的に強制変更するための職業ID
let mForceClassId = null;
/**
* ●指定レベルに到達するのに必要な経験値を取得
*/
function expForLevel(actor, classId, level) {
// 参照する職業IDを強制書換
mForceClassId = classId;
// 内部でGame_Actor.prototype.currentClass()を参照
const exp = actor.expForLevel(level);
// 職業IDをクリア
mForceClassId = null;
return exp;
};
/**
* ●現在の職業を取得
*/
const _Game_Actor_currentClass = Game_Actor.prototype.currentClass;
Game_Actor.prototype.currentClass = function() {
if (mForceClassId) {
// -1で空白を返す
if (mForceClassId == -1) {
const ret = [];
ret.name = "";
return ret;
}
return $dataClasses[mForceClassId];
}
return _Game_Actor_currentClass.apply(this, arguments);
};
// リフレッシュ防止フラグ
let mNoRefresh = false;
/**
* ●リフレッシュ
*/
const _Game_Actor_refresh = Game_Actor.prototype.refresh;
Game_Actor.prototype.refresh = function() {
// フラグが立っている時は禁止
// ※以降で装備解除処理が行われるので防止するため
if (mNoRefresh) {
return;
}
_Game_Actor_refresh.apply(this, arguments);
};
//-----------------------------------------------------------------------------
// Scene_ClassChange
//
// 転職シーン用クラス
function Scene_ClassChange() {
this.initialize(...arguments);
}
Scene_ClassChange.prototype = Object.create(Scene_MenuBase.prototype);
Scene_ClassChange.prototype.constructor = Scene_ClassChange;
Scene_ClassChange.prototype.initialize = function() {
Scene_MenuBase.prototype.initialize.call(this);
Scene_Message.prototype.initialize.call(this);
// アクターの選択を行うかどうか?
this._isSelectActor = false;
// 職業画像の読込
loadClassImage();
};
/**
* ●アクターの設定
*/
Scene_ClassChange.prototype.updateActor = function() {
let actor = $gameActors.actor($gameParty._menuActorId);
// チェック処理は行わない。
// if (!this.members().includes(actor)) {
// actor = this.members()[0];
// }
this._actor = actor;
};
/**
* ●更新処理
*/
Scene_ClassChange.prototype.update = function() {
Scene_MenuBase.prototype.update.call(this);
if (this._isMessageClosing) {
// メッセージが完全に閉じてからシーン終了
if (this._messageWindow.isClosed()) {
this.classChangeEnd();
}
return;
}
// メッセージのクローズ開始を検出
if (this.isMessageWindowClosing()) {
this._isMessageClosing = true;
}
};
/**
* ●ウィンドウの生成
*/
Scene_ClassChange.prototype.create = function() {
Scene_MenuBase.prototype.create.call(this);
// アクター選択用ウィンドウ
this.createStatusWindow();
// 選択用ウィンドウ
let wx = 0;
let wy = this.mainAreaTop();
let ww = pClassListWidth;
let wh = Graphics.boxHeight - wy;
this._selectWindow = new Windows_SelectClasses(new Rectangle(wx, wy, ww, wh));
this._selectWindow.setHandler("ok", this.onClassChangeConfirm.bind(this));
this._selectWindow.setHandler('cancel', this.onClassChangeSelectCancel.bind(this));
// アクターが指定されている場合は切替禁止
if (!mActorNoChange) {
this._selectWindow.setHandler("pagedown", this.nextActor.bind(this));
this._selectWindow.setHandler("pageup", this.previousActor.bind(this));
}
this.addWindow(this._selectWindow);
// 情報用ウィンドウ
wx = this._selectWindow.width;
ww = Graphics.boxWidth - wx;
this._infoWindow = new Windows_ClassInfo(new Rectangle(wx, wy, ww, wh));
this._infoWindow.setHandler("ok", this.onClassChangeOk.bind(this));
this._infoWindow.setHandler('cancel', this.onClassChangeCancel.bind(this));
this.addWindow(this._infoWindow);
// 職業選択用ウィンドウから情報用ウィンドウへの参照を設定
this._selectWindow.setInfoWindow(this._infoWindow);
// メッセージ表示用の設定
this.createMessageWindows();
};
/**
* ●処理開始
*/
Scene_ClassChange.prototype.start = function() {
Scene_MenuBase.prototype.start.call(this);
Scene_Message.prototype.start.call(this);
// アクターが指定されていない場合は、
// まずアクター選択ウィンドウを表示する。
if (this.isNoActor()) {
// アクター選択を行うモード
this._isSelectActor = true;
// 選択開始
this.selectActorStart();
return;
}
// アクター情報の設定
this.refreshActor();
// 職業選択ウィンドウにフォーカス
this._selectWindow.activate();
this._infoWindow.deactivate();
};
/**
* ●ヘルプウィンドウの縦幅
* ※存在しないので0
*/
Scene_ClassChange.prototype.helpAreaHeight = function() {
return 0;
};
/**
* ●各ウィンドウにアクター情報を設定
*/
Scene_ClassChange.prototype.refreshActor = function() {
const actor = this._actor;
this._selectWindow.setActor(actor);
this._infoWindow.setActor(actor);
};
/**
* ●アクターが未設定かどうか?
*/
Scene_ClassChange.prototype.isNoActor = function() {
return !$gameParty._menuActorId;
};
//----------------------------------------
// アクター選択用ウィンドウ
//----------------------------------------
/**
* ●アクター選択用ウィンドウの作成
*/
Scene_ClassChange.prototype.createStatusWindow = function() {
const rect = this.statusWindowRect();
this._statusWindow = new Window_MenuStatus(rect);
this._statusWindow.setHandler("ok", this.onClassChangeSelectStart.bind(this));
this._statusWindow.setHandler('cancel', this.popScene.bind(this));
this.addWindow(this._statusWindow);
};
/**
* ●ステータスウィンドウ用の領域を確保
*/
Scene_ClassChange.prototype.statusWindowRect = function() {
const ww = Graphics.boxWidth;
const wh = this.mainAreaHeight();
const wx = this.isRightInputMode() ? 0 : Graphics.boxWidth - ww;
const wy = this.mainAreaTop();
return new Rectangle(wx, wy, ww, wh);
};
/**
* ●アクター選択開始
*/
Scene_ClassChange.prototype.selectActorStart = function() {
// 転職用ウィンドウは非表示
this._selectWindow.hide();
this._infoWindow.hide();
// スキルページを解除
this._infoWindow._isSkillPage = false;
// さらにアクター選択用ウィンドウを表示&フォーカス
this._statusWindow.show();
this._statusWindow.activate();
// インデックスがない場合(-1)は先頭を選択
// インデックスがある場合(キャンセルで転職ウィンドウから戻った)は維持
if (this._statusWindow.index() < 0) {
this._statusWindow.select(0);
}
// 描画更新(顔グラ)
this._statusWindow.refresh();
};
//----------------------------------------
// 転職選択用ウィンドウ
//----------------------------------------
/**
* ●転職の選択開始
*/
Scene_ClassChange.prototype.onClassChangeSelectStart = function() {
// アクター選択ウィンドウの選択結果を反映
this._actor = this._statusWindow.actor(this._statusWindow.index());
// アクター選択ウィンドウを非表示
this._statusWindow.hide();
// 職業選択ウィンドウの表示&フォーカス
this._selectWindow.show();
this._selectWindow.activate();
// 職業情報ウィンドウの表示。ただし選択しない
this._infoWindow.show();
this._infoWindow.deselect();
this._infoWindow.deactivate()
// アクター情報の設定
this.refreshActor();
};
/**
* ●転職の選択キャンセル
*/
Scene_ClassChange.prototype.onClassChangeSelectCancel = function() {
// アクターの選択を行う場合
if (this._isSelectActor) {
// アクター選択へ戻る
this.selectActorStart();
// アクターの選択がない場合は前シーンへ
} else {
this.popScene();
}
};
/**
* ●転職確認
*/
Scene_ClassChange.prototype.onClassChangeConfirm = function() {
this._infoWindow.select(0);
this._infoWindow.activate();
};
/**
* ●転職確定
*/
Scene_ClassChange.prototype.onClassChangeOk = function() {
// 選択中の職業を取得
const classItem = this._selectWindow.item();
// 転職実行
this._actor.changeClass(classItem.id, pKeepExp);
if (pClassChangeMessage) {
// 成功メッセージの表示
const text = pClassChangeMessage.format(
this._actor.name(),
classItem.name
);
$gameMessage.add(text);
// メッセージがない場合は即終了
} else {
this.classChangeEnd();
}
};
/**
* ●転職キャンセル
*/
Scene_ClassChange.prototype.onClassChangeCancel = function() {
this._infoWindow.deselect();
// 職業選択ウィンドウに戻る
this._selectWindow.activate();
};
/**
* ●転職確定後の終了処理
*/
Scene_ClassChange.prototype.classChangeEnd = function() {
// 画像反映を行う場合はリフレッシュ
if (pUseClassImage) {
$gamePlayer.refresh();
}
// アクターの選択を行う場合
if (this._isSelectActor) {
// アクター選択へ戻る
this.selectActorStart();
// アクターの選択がない場合は前シーンへ
} else {
this.popScene();
}
};
//----------------------------------------
// ボタンによるアクター切替用
//----------------------------------------
/**
* ●アクターの変更
*/
Scene_ClassChange.prototype.onActorChange = function() {
Scene_MenuBase.prototype.onActorChange.call(this);
this.refreshActor();
// スキルページを解除
this._infoWindow._isSkillPage = false;
// 職業選択ウィンドウに合わせる。
this._selectWindow.activate();
};
/**
* ●ページボタンが必要かどうか?
*/
Scene_ClassChange.prototype.needsPageButtons = function() {
return true;
};
/**
* ●ページボタンの表示制御
*/
Scene_ClassChange.prototype.arePageButtonsEnabled = function() {
// アクターが指定されている場合は切替禁止
// アクター選択中は切替禁止
if (mActorNoChange || this._statusWindow.active) {
return false;
}
return true;
};
//----------------------------------------
// 以下メッセージ表示用
//----------------------------------------
/**
* ●停止
*/
Scene_ClassChange.prototype.stop = function() {
Scene_Message.prototype.stop.call(this);
};
/**
* ●終了時
*/
Scene_ClassChange.prototype.terminate = function() {
Scene_Message.prototype.terminate.call(this);
};
/**
* ●メッセージが閉じている最中か?
*/
Scene_ClassChange.prototype.isMessageWindowClosing = function() {
return this._messageWindow.isClosing();
};
/**
* ●ウィンドウ生成
*/
Scene_ClassChange.prototype.createMessageWindows = function() {
this.createMessageWindow();
this.createScrollTextWindow();
this.createNameBoxWindow();
this.createChoiceListWindow();
this.createNumberInputWindow();
this.createEventItemWindow();
this.associateWindows();
// メッセージウィンドウの下が消えないよう調整
this.addChild(this._windowLayer.removeChild(this._messageWindow));
this.addChild(this._windowLayer.removeChild(this._scrollTextWindow));
};
Scene_ClassChange.prototype.createMessageWindow = function() {
Scene_Message.prototype.createMessageWindow.call(this);
};
Scene_ClassChange.prototype.createScrollTextWindow = function() {
Scene_Message.prototype.createScrollTextWindow.call(this);
};
Scene_ClassChange.prototype.createNameBoxWindow = function() {
Scene_Message.prototype.createNameBoxWindow.call(this);
};
Scene_ClassChange.prototype.createChoiceListWindow = function() {
Scene_Message.prototype.createChoiceListWindow.call(this);
};
Scene_ClassChange.prototype.createNumberInputWindow = function() {
Scene_Message.prototype.createNumberInputWindow.call(this);
};
Scene_ClassChange.prototype.createEventItemWindow = function() {
Scene_Message.prototype.createEventItemWindow.call(this);
};
Scene_ClassChange.prototype.messageWindowRect = function() {
return Scene_Message.prototype.messageWindowRect.call(this);
};
Scene_ClassChange.prototype.scrollTextWindowRect = function() {
return Scene_Message.prototype.scrollTextWindowRect.call(this);
};
Scene_ClassChange.prototype.eventItemWindowRect = function() {
return Scene_Message.prototype.eventItemWindowRect.call(this);
};
Scene_ClassChange.prototype.associateWindows = function() {
const messageWindow = this._messageWindow;
// 余計な表示がされるので、ダミーのウィンドウを設定
const rect = new Rectangle(0, 0, 0, 0);
const goldWindow = new Window_Gold(rect);
messageWindow.setGoldWindow(goldWindow);
messageWindow.setNameBoxWindow(this._nameBoxWindow);
messageWindow.setChoiceListWindow(this._choiceListWindow);
messageWindow.setNumberInputWindow(this._numberInputWindow);
messageWindow.setEventItemWindow(this._eventItemWindow);
this._nameBoxWindow.setMessageWindow(messageWindow);
this._choiceListWindow.setMessageWindow(messageWindow);
this._numberInputWindow.setMessageWindow(messageWindow);
this._eventItemWindow.setMessageWindow(messageWindow);
};
/**
* ●成功メッセージの追加
*/
Scene_ClassChange.prototype.showMessage = function(message) {
// メッセージが有効な場合
if (message) {
const window = this._messageWindow;
$gameMessage.add(message);
// メッセージウィンドウにフォーカス
if (window) {
window.activate();
}
}
};
//-----------------------------------------------------------------------------
// Windows_SelectClasses
//
// 職業選択用ウィンドウ
function Windows_SelectClasses() {
this.initialize(...arguments);
}
Windows_SelectClasses.prototype = Object.create(Window_Selectable.prototype);
Windows_SelectClasses.prototype.constructor = Windows_SelectClasses;
Windows_SelectClasses.prototype.initialize = function(rect) {
Window_Selectable.prototype.initialize.call(this, rect);
};
Windows_SelectClasses.prototype.refresh = function() {
this.makeItemList();
this.select(0);
Window_Selectable.prototype.refresh.call(this);
};
/**
* ●項目生成
*/
Windows_SelectClasses.prototype.makeItemList = function() {
const classes = [];
// eval参照用
const a = this._actor;
// 転職条件を満たすか判定
for (const classInfo of mClassList) {
// 対象のアクターでない場合
if (classInfo.actors && classInfo.actors.length && !this.isActorConditionOK(classInfo.actors)) {
continue;
// 対象のスイッチがオンでない場合
} else if (classInfo.switch && !$gameSwitches.value(classInfo.switch)) {
continue;
// 対象のアイテムが持っていない場合
} else if (classInfo.item && !$gameParty.hasItem($dataItems[classInfo.item])) {
continue;
// 対象の職業情報を満たさない場合
} else if (classInfo.classInfo && !this.isClassConditionOK(classInfo.classInfo)) {
continue;
// 対象のスクリプトがオンでない場合
} else if (classInfo.script && !eval(classInfo.script)) {
continue;
}
// 条件を満たすなら追加
classes.push($dataClasses[classInfo.class]);
}
this._data = classes;
};
/**
* ●アクター条件を満たすかどうか?
*/
Windows_SelectClasses.prototype.isActorConditionOK = function(actorIds) {
// 引数は文字列配列、this._actor.actorId()は数字なので==で比較
return actorIds.some(id => id == this._actor.actorId());
};
/**
* ●職業条件を満たすかどうか?
*/
Windows_SelectClasses.prototype.isClassConditionOK = function(jsonConditions) {
// JSON形式のままなのでJS方式に変換
const conditions = parseStruct2(jsonConditions);
// 一時アクターを生成し、その職業情報を取得する。
const tempActor = JsonEx.makeDeepCopy(this._actor);
for (const condition of conditions) {
// 一時アクターを転職させる。
// ただし、転職時の装備解除を防ぐためリフレッシュを禁止
mNoRefresh = true;
tempActor.changeClass(condition.Class, pKeepExp);
mNoRefresh = false;
// レベル条件を満たさないならfalse
if (tempActor.level < condition.Level) {
return false;
}
}
return true;
};
/**
* ●項目表示
*/
Windows_SelectClasses.prototype.drawItem = function(index) {
if (!this._actor) {
return;
}
const classItem = this.itemAt(index);
if (classItem) {
const rect = this.itemLineRect(index);
// 転職可不可の表示制御
this.changePaintOpacity(isClassEnabled(classItem, this._actor));
// 職業名の表示
this.drawItemName(classItem, rect.x, rect.y);
// 職業レベルの表示
if (pDisplayListLevel) {
const level = getClassLevel(this._actor, classItem.id);
this.drawClassLevel(level, rect.x, rect.y, rect.width);
}
// 表示を戻す
this.changePaintOpacity(1);
}
};
/**
* ●選択中の項目が選択可能かどうか?
*/
Windows_SelectClasses.prototype.isCurrentItemEnabled = function() {
// 対象項目が存在するかどうか?
return !!this.item();
};
/**
* ●選択中の項目を取得
*/
Windows_SelectClasses.prototype.item = function() {
return this.itemAt(this.index());
};
/**
* ●項目の取得
*/
Windows_SelectClasses.prototype.itemAt = function(index) {
return this._data && index >= 0 ? this._data[index] : null;
};
/**
* ●最大項目数
*/
Windows_SelectClasses.prototype.maxItems = function() {
return this._data ? this._data.length : 1;
};
/**
* ●項目名の表示
*/
Windows_SelectClasses.prototype.drawItemName = function(item, x, y) {
if (item) {
let textMargin = 4;
let levelWidth = 0;
// 職業レベルの表示
if (pDisplayListLevel) {
levelWidth = 64;
}
const itemWidth = Math.max(0, this.innerWidth - textMargin - levelWidth);
this.resetTextColor();
this.drawTextEx(item.name, x + textMargin, y, itemWidth);
}
};
/**
* ●職業のレベルを表示
*/
Windows_SelectClasses.prototype.drawClassLevel = function(level, x, y, width) {
this.drawText(level, x, y, width, "right");
};
/**
* ●カーソル移動時
*/
Windows_SelectClasses.prototype.select = function(index) {
Window_Selectable.prototype.select.apply(this, arguments);
const classItem = this.itemAt(index);
// 比較用に転職後アクター情報を設定
if (this._actor) {
if (classItem) {
const tempActor = JsonEx.makeDeepCopy(this._actor);
// 一時アクターを転職させる。
// ただし、転職時の装備解除を防ぐためリフレッシュを禁止
mNoRefresh = true;
tempActor.changeClass(classItem.id, pKeepExp);
mNoRefresh = false;
this._infoWindow.setTempActor(tempActor);
} else {
this._infoWindow.setTempActor(null);
}
}
};
/**
* ●情報ウィンドウの設定
*/
Windows_SelectClasses.prototype.setInfoWindow = function(window) {
this._infoWindow = window;
};
/**
* ●アクターの設定
*/
Windows_SelectClasses.prototype.setActor = function(actor) {
this._actor = actor;
this.refresh();
// 現在の職業にインデックスを設定する。
for (let i = 0; i < this._data.length; i++) {
const classItem = this.itemAt(i);
// 一致するクラスが存在した場合
if (this._actor.isClass(classItem)) {
// インデックスを設定
this.select(i);
break;
}
}
};
//-----------------------------------------------------------------------------
// Windows_ClassInfo
//
// 職業情報用ウィンドウ
function Windows_ClassInfo() {
this.initialize(...arguments);
}
Windows_ClassInfo.prototype = Object.create(Window_EquipStatus.prototype);
Windows_ClassInfo.prototype.constructor = Windows_ClassInfo;
Windows_ClassInfo.prototype.initialize = function(rect) {
Window_Status.prototype.initialize.call(this, rect);
// スクロール間隔
this._scrollInterval = this.lineHeight();
};
/**
* ●アクターの設定
*/
Windows_ClassInfo.prototype.setActor = function(actor) {
if (this._actor !== actor) {
this._actor = actor;
this.refresh();
}
};
/**
* ●ページの変更
*/
Windows_ClassInfo.prototype.changePage = function() {
this._isSkillPage = !this._isSkillPage;
// スクロール位置を先頭に戻す。
this.scrollTo(this._scrollX, 0);
this.refresh();
};
/**
* ●再描画
*/
Windows_ClassInfo.prototype.paint = function() {
if (this.contents) {
this.contents.clear();
this.contentsBack.clear();
this.drawAllItems();
this.refreshCursor();
}
};
/**
* ●描画更新
*/
Windows_ClassInfo.prototype.refresh = function() {
this.contents.clear();
this.drawAllItems();
// スクロール込の縦幅を計算
this.setOverallHeight();
};
/**
* ●職業情報
*/
Windows_ClassInfo.prototype.getClass = function() {
return this._tempActor.currentClass();
}
/**
* ●各項目の描画
*/
Windows_ClassInfo.prototype.drawAllItems = function() {
if (this._actor && this._tempActor) {
if (this._isSkillPage) {
this.drawLearnSkills(this.itemPadding(), -this._scrollY + this.itemPadding());
return;
}
const nameRect = this.itemLineRect(0);
// 変更先の職業を表示
this.drawActorClass(this.itemPadding(), -this._scrollY + this.itemPadding());
// 職業レベルを表示
this.drawActorClassLevel(this.itemPadding(), -this._scrollY + this.itemPadding() + nameRect.height);
// 職業経験値を表示
this.drawExpInfo(0, -this._scrollY + this.itemPadding() + this.lineHeight());
this.drawActorName(this._actor, nameRect.x, -this._scrollY + this.itemPadding(), nameRect.width);
if (pReverseImagePos) {
this.drawClassImage(this._tempActor, this.paramX() + 170, this.paramY(0));
this.drawAllParams();
} else {
this.drawClassImage(this._tempActor, nameRect.x, this.paramY(0));
this.drawAllParams();
}
// 説明文を表示
this.drawClassMessage(this.itemPadding(), this.classMessageY());
// 習得スキルを表示
this.drawLearnSkills(this.itemPadding(), this.classSkillY());
}
};
/**
* ●職業画像を表示
*/
Windows_ClassInfo.prototype.drawClassImage = function(
actor, x, y, width, height
) {
let faceName = actor.faceName();
let faceIndex = actor.faceIndex();
// 独自の職業画像が存在すれば取得する。
const classImage = findClassImage(actor);
if (classImage) {
// ピクチャー
if (classImage.Picture) {
if (pPictureAdjustX) {
x += pPictureAdjustX;
}
if (pPictureAdjustY) {
y += pPictureAdjustY;
}
// スクロール連動しない場合は逆に加算して打ち消す。
if (!pPictureOnScroll) {
y += this._scrollY;
}
this.drawPicture(classImage.Picture, x, y, width, height);
return;
// 顔グラ
} else if (classImage.Face) {
faceName = classImage.Face;
}
// 顔グラ(インデックス)
if (classImage.FaceIndex != undefined) {
faceIndex = classImage.FaceIndex;
}
}
// 通常はアクターの顔グラ
this.drawFace(faceName, faceIndex, x, y, width, height);
};
/**
* ●ピクチャーの描画
*/
Windows_ClassInfo.prototype.drawPicture = function(
imageName, x, y, width, height
) {
const bitmap = ImageManager.loadPicture(imageName);
width = width || bitmap.width;
height = height || bitmap.height;
const sw = width;
const sh = height;
// 中央寄せ
const dx = x;
const dy = y;
const sx = 0;
const sy = 0;
this.contents.paintOpacity = pPictureOpacity;
this.contents.blt(bitmap, sx, sy, sw, sh, dx, dy);
this.contents.paintOpacity = 255;
};
/**
* ●職業名を表示
*/
Windows_ClassInfo.prototype.drawActorClass = function(x, y, width) {
width = width || 168;
this.resetTextColor();
this.drawText(this.getClass().name, x, y, this.innerWidth - this.itemPadding(), "right");
};
/**
* ●職業レベルを表示
*/
Windows_ClassInfo.prototype.drawActorClassLevel = function(x, y) {
this.changeTextColor(ColorManager.systemColor());
this.drawText(TextManager.levelA, x, y, 48);
this.resetTextColor();
this.drawText(this._tempActor.level, x + 84, y, 36, "right");
};
/**
* ●職業経験値を表示
*/
Windows_ClassInfo.prototype.drawExpInfo = function(x, y) {
const faceWidth = ImageManager.faceWidth;
this.changeTextColor(ColorManager.systemColor());
this.drawText(TextManager.exp, faceWidth + this.itemPadding(), y, 270);
this.resetTextColor();
// 現在の経験値
this.drawText(this.expTotalValue(), x - 125, y, this.innerWidth - this.itemPadding(), "right");
// "/"
this.drawText("/", x - 110, y, this.innerWidth - this.itemPadding(), "right");
// 次のレベルアップまでの経験値
this.drawText(this.expNextValue(), x, y, this.innerWidth - this.itemPadding(), "right");
};
/**
* ●現在の経験値
*/
Windows_ClassInfo.prototype.expTotalValue = function() {
if (this._tempActor.isMaxLevel()) {
return "-------";
} else {
return this._tempActor.currentExp();
}
};
/**
* ●次のレベルに必要な合計経験値
*/
Windows_ClassInfo.prototype.expNextValue = function() {
if (this._tempActor.isMaxLevel()) {
return "-------";
} else {
// デフォルトとは異なり、現在EXPとの合計を表示
return this._tempActor.currentExp() + this._tempActor.nextRequiredExp();
}
};
/**
* ●職業レベルのX座標を取得
*/
Windows_ClassInfo.prototype.levelX = function() {
const itemPadding = this.itemPadding();
const levelWidth = 120;
return this.innerWidth - itemPadding - levelWidth;
};
/**
* ●各パラメータを表示
*/
Windows_ClassInfo.prototype.drawAllParams = function() {
if (pParamFontSize) {
this.contents.fontSize = pParamFontSize;
}
let x = this.itemPadding();
if (!pReverseImagePos) {
x += ImageManager.faceWidth + 16;
}
// パラメータの候補を取得
let i = -1;
if (pDisplayParameters) {
const displayParameters = pDisplayParameters.split(",");
for (const dispParam of displayParameters) {
i++;
const y = this.paramY(i);
this.drawItem(x, y, toNumber(dispParam));
}
}
// パラメータの終了Y座標を取得
this._parameterEndY = this.paramY(i);
this.resetTextColor();
this.resetFontSettings();
};
/**
* ●パラメータの横幅
*/
Windows_ClassInfo.prototype.paramWidth = function() {
return 64;
};
/**
* ●パラメータのX座標
*/
Windows_ClassInfo.prototype.paramX = function() {
const itemPadding = this.itemPadding();
const rightArrowWidth = this.rightArrowWidth();
const paramWidth = this.paramWidth();
if (pReverseImagePos) {
return 150;
}
return this.innerWidth - itemPadding - paramWidth * 2 - rightArrowWidth;
};
/**
* ●パラメータのY座標取得
*/
Windows_ClassInfo.prototype.paramY = function(index) {
return -this._scrollY + Math.floor(this.lineHeight() * 2.5) + pParamLineHeight * index;
};
/**
* ●職業の習得スキルを表示
*/
Windows_ClassInfo.prototype.drawLearnSkills = function(x, y) {
// スキルを表示しない場合
if (!pShowSkillsType) {
// 終了座標だけを設定
this._skillEndY = y;
return;
// または別ページに表示する場合
// かつ、スキルページではない場合
} else if (!this._isSkillPage && pShowSkillsType == "page") {
// 終了座標だけを設定
this._skillEndY = y;
return;
}
this.resetTextColor();
if (pSkillFontSize) {
this.contents.fontSize = pSkillFontSize;
}
let i = 0;
for (const learning of this.getClass().learnings) {
const skill = $dataSkills[learning.skillId];
let skillName = skill.name;
if (!this._tempActor.isLearnedSkill(learning.skillId)) {
// 未習得のスキルを表示しない場合
if (!pShowUnlearnedSkills) {
continue;
}
// 未習得なら半透明表示
this.changePaintOpacity(false);
// マスクする場合
if (pShowUnlearnedSkills == "mask") {
skillName = "";
}
}
if (i % 2 == 0) {
x = this.itemPadding();
} else {
x = this.itemPadding() + this.innerWidth / 2;
}
const iconY = y + (this.lineHeight() - ImageManager.iconHeight) / 2;
const textMargin = ImageManager.iconWidth + 4;
const itemWidth = Math.max(0, this.innerWidth / 2 - this.itemPadding() - textMargin);
// アイコンを描画
this.drawIcon(skill.iconIndex, x, iconY);
// スキル名を描画
this.drawText(skillName, x + textMargin, y, itemWidth);
// 表示を戻す
this.changePaintOpacity(1);
// 次の行へ
if (i % 2 == 1) {
y += this.lineHeight();
}
i++;
}
// 項目数が奇数の場合は改行追加
if (i > 0 && i % 2 == 1) {
y += this.lineHeight();
}
this.resetFontSettings();
this._skillEndY = y + this.lineHeight();
};
/**
* ●職業の説明を表示
*/
Windows_ClassInfo.prototype.drawClassMessage = function(x, y) {
if (pMessageFontSize) {
this.contents.fontSize = pMessageFontSize;
}
const classMessage = this.getClassMessage();
this.drawTextEx(classMessage, x, y);
const textHeight = this.getTextHeight(classMessage);
// フォント設定をリセット(\c[]などを初期化)
this.resetFontSettings();
// 終了地点を保持しておく
this._classMessageEndY = y + textHeight + this.lineHeight() / 2;
};
/**
* ●文字列描画処理
* ※Window_Base.prototype.drawTextExとほぼ同じだがフォントリセットしない。
*/
Windows_ClassInfo.prototype.drawTextEx = function(text, x, y, width) {
const textState = this.createTextState(text, x, y, width);
this.processAllText(textState);
return textState.outputWidth;
};
/**
* ●職業説明文のY座標取得
*/
Windows_ClassInfo.prototype.classMessageY = function() {
// パラメータの下に接続8はマージン
return this._parameterEndY + this.lineHeight() + 8;
};
/**
* ●職業習得スキルのY座標取得
*/
Windows_ClassInfo.prototype.classSkillY = function() {
const classMessage = this.getClassMessage();
// 説明文が存在しない場合は省略
if (!classMessage) {
return Math.floor(this.classMessageY()) + 8;
}
// 職業説明の下に接続8はマージン
return Math.floor(this._classMessageEndY) + 8;
};
/**
* ●文章の縦幅取得
*/
Windows_ClassInfo.prototype.getTextHeight = function(text) {
return this.textSizeEx(text).height;
};
/**
* ●文章サイズの取得
*/
Windows_ClassInfo.prototype.textSizeEx = function(text) {
// 正確を期すためフォントサイズをリセットしない。
// this.resetFontSettings();
const textState = this.createTextState(text, 0, 0, 0);
textState.drawing = false;
this.processAllText(textState);
return { width: textState.outputWidth, height: textState.outputHeight };
};
/**
* ●職業の説明文を表示
*/
Windows_ClassInfo.prototype.getClassMessage = function () {
const noteSplit = this.getClass().note.split("\n");
// タグ名
const tagName = "ClassMessage";
// メッセージ
let msg = "";
// タグ開始検出用
let readStart = false;
// 一行ずつ読込
for (const noteLine of noteSplit) {
// 開始タグ
if (noteLine.match("<" + tagName + ">")) {
// 内容モード開始
readStart = true;
// 終了タグ
} else if (noteLine.match("</\\s*" + tagName + ">")) {
// 処理終了
break;
// 内容モード時
} else if (readStart) {
// 行内容を追加
if (msg) {
msg += "\n";
}
// msg.push(noteLine);
msg += noteLine;
}
}
return msg;
};
/**
* ●カーソルの表示
*/
Windows_ClassInfo.prototype.refreshCursor = function() {
if (this._cursorAll) {
this.setCursorRect(0, 0, this.width, Graphics.height);
} else if (this.index() >= 0) {
this.setCursorRect(0, 0, this.width, Graphics.height);
} else {
this.setCursorRect(0, 0, 0, 0);
}
};
/**
* ●カーソル移動が有効かどうか?
*/
Windows_ClassInfo.prototype.isCursorMovable = function() {
return this.isOpenAndActive();
};
/**
* ●選択中の項目が選択可能かどうか?
*/
Windows_ClassInfo.prototype.isCurrentItemEnabled = function() {
return isClassEnabled(this.getClass(), this._actor);
};
/**
* ●転職決定時
*/
Windows_ClassInfo.prototype.processOk = function() {
if (this.isCurrentItemEnabled()) {
// 転職成功効果音
if (pSoundSuccess) {
AudioManager.playSe({"name":pSoundSuccess, "volume":90, "pitch":100, "pan":0})
// 指定がない場合はデフォルトの決定音
} else {
this.playOkSound();
}
this.updateInputData();
this.deactivate();
this.callOkHandler();
} else {
this.playBuzzerSound();
}
};
/**
* ●転職キャンセル時
*/
Windows_ClassInfo.prototype.processCancel = function() {
Window_Selectable.prototype.processCancel.apply(this, arguments);
// スクロール位置を先頭に戻す。
this.scrollTo(this._scrollX, 0);
};
/**
* ●カーソル下
*/
Windows_ClassInfo.prototype.cursorDown = function(wrap) {
this.smoothScrollDown(1);
};
/**
* ●カーソル上
*/
Windows_ClassInfo.prototype.cursorUp = function(wrap) {
this.smoothScrollUp(1);
};
/**
* ●タッチが有効かどうか?
*/
Windows_ClassInfo.prototype.isTouchOkEnabled = function() {
return this.isOkEnabled();
};
/**
* ●当たり判定
*/
Windows_ClassInfo.prototype.hitTest = function(x, y) {
// 要素内なら有効と判定
if (this.innerRect.contains(x, y)) {
return 1;
}
return -1;
};
/**
* ●スクロールを含めた縦幅を計算
*/
Windows_ClassInfo.prototype.setOverallHeight = function() {
if (this._actor && this._tempActor) {
this._overallHeight = this._skillEndY;
return;
}
this._overallHeight = 0;
};
/**
* ●スクロールを含めた縦幅
*/
Windows_ClassInfo.prototype.overallHeight = function() {
return this._overallHeight;
};
/**
* ●最大の縦スクロール幅
*/
Windows_ClassInfo.prototype.maxScrollY = function() {
let maxScrollY = Math.max(0, this.overallHeight() - this.innerHeight);
// スクロール単位で丸める。
// ※丸めておかないと上に戻った時にズレる。
maxScrollY = Math.floor(maxScrollY / this.scrollBlockHeight()) * this.scrollBlockHeight();
return maxScrollY;
};
/**
* ●スクロール単位
*/
Windows_ClassInfo.prototype.scrollBlockHeight = function() {
return this._scrollInterval;
};
/**
* ●原点の更新
*/
Windows_ClassInfo.prototype.updateOrigin = function() {
const blockWidth = this.scrollBlockWidth() || 1;
// const blockHeight = this.scrollBlockHeight() || 1;
const blockHeight = 1; // ブロックは使わない。
const baseX = this._scrollX - (this._scrollX % blockWidth);
const baseY = this._scrollY - (this._scrollY % blockHeight);
if (baseX !== this._scrollBaseX || baseY !== this._scrollBaseY) {
this.updateScrollBase(baseX, baseY);
this.paint();
}
this.origin.x = this._scrollX % blockWidth;
this.origin.y = this._scrollY % blockHeight;
};
/**
* ●カーソル移動時
*/
Windows_ClassInfo.prototype.processCursorMove = function() {
if (this.isCursorMovable()) {
// スクロールをスムーズにするため独自関数を使用
if (isRepeated.bind(Input)("down")) {
this.cursorDown(Input.isTriggered("down"));
}
if (isRepeated.bind(Input)("up")) {
this.cursorUp(Input.isTriggered("up"));
}
}
Window_Selectable.prototype.processCursorMove.apply(this, arguments);
};
// Windows_ClassInfo.prototype._updateCursor = function() {
// this._cursorSprite.alpha = this._makeCursorAlpha();
// this._cursorSprite.visible = this.isOpen() && this.cursorVisible;
// this._cursorSprite.x = this._cursorRect.x;
// this._cursorSprite.y = this._cursorRect.y;
// };
// Windows_ClassInfo.prototype._makeCursorAlpha = function() {
// const blinkCount = this._animationCount % 40;
// const baseAlpha = this.contentsOpacity / 255;
// if (this.active) {
// if (blinkCount < 20) {
// return baseAlpha - blinkCount / 32;
// } else {
// return baseAlpha - (40 - blinkCount) / 32;
// }
// }
// return baseAlpha;
// };
/**
* ●スクロールをスムーズにするための独自関数
* ※Input.isRepeatedを改修
*/
function isRepeated(keyName) {
if (this._isEscapeCompatible(keyName) && this.isRepeated("escape")) {
return true;
} else {
return (
this._latestButton === keyName &&
(this._pressedTime === 0 ||
(this._pressedTime >= 0 &&
this._pressedTime % this.keyRepeatInterval === 0))
);
}
};
//-----------------------------------------------------------------------------
// ページ切替用
//-----------------------------------------------------------------------------
// 別ページに表示する場合
if (pShowSkillsType == "page") {
/**
* ●右キー
*/
Windows_SelectClasses.prototype.cursorRight = function(wrap) {
this.playCursorSound();
// スキルページへ切替
this._infoWindow.changePage();
};
/**
* ●左キー
*/
Windows_SelectClasses.prototype.cursorLeft = function(wrap) {
this.playCursorSound();
// スキルページへ切替
this._infoWindow.changePage();
};
/**
* ●右キー
*/
Windows_ClassInfo.prototype.cursorRight = function(wrap) {
this.playCursorSound();
// スキルページへ切替
this.changePage();
};
/**
* ●左キー
*/
Windows_ClassInfo.prototype.cursorLeft = function(wrap) {
this.playCursorSound();
// スキルページへ切替
this.changePage();
};
/**
* ●ページを使用しない。
* ※NRP_PageWindow.jsとの競合対策
*/
Windows_SelectClasses.prototype.isUsePage = function() {
return false;
}
/**
* ●ページ切替矢印更新
*/
Windows_ClassInfo.prototype.updateArrows = function() {
Window_Selectable.prototype.updateArrows.apply(this, arguments);
// 左右のページ切替矢印を表示
// this.leftArrowVisible = true;
this.rightArrowVisible = true;
};
/**
* ●ページ切替矢印作成
*/
Windows_ClassInfo.prototype._createAllParts = function() {
Window.prototype._createAllParts.apply(this, arguments);
// 左右の矢印を追加
// this._leftArrowSprite = new Sprite();
this._rightArrowSprite = new Sprite();
// this.addChild(this._leftArrowSprite);
this.addChild(this._rightArrowSprite);
};
/**
* ●ページ切替矢印配置
*/
Windows_ClassInfo.prototype._refreshArrows = function() {
Window.prototype._refreshArrows.apply(this, arguments);
var w = this._width;
var h = this._height;
var p = 24;
var q = p/2;
var sx = 96+p;
var sy = 0+p;
var cursorLeftW = 12;
var cursorRightW = 12;
// // カーソル画像設定
// this._leftArrowSprite.bitmap = this._windowskin;
// this._leftArrowSprite.setFrame(sx, sy+q, q, p);
// this._leftArrowSprite.anchor.x = 0.5;
// this._leftArrowSprite.anchor.y = 0.5;
this._rightArrowSprite.bitmap = this._windowskin;
this._rightArrowSprite.setFrame(sx+q+p, sy+q, q, p);
this._rightArrowSprite.anchor.x = 0.5;
this._rightArrowSprite.anchor.y = 0.5;
// カーソル位置設定
var leftX;
var leftY;
var rightX;
var rightY;
// // 横位置の設定
// if (pPageCursorHorizontal == "right") {
// rightX = w - cursorRightW / 2 - 4;
// leftX = rightX - cursorRightW;
// } else if (pPageCursorHorizontal == "leftRight") {
// leftX = cursorLeftW / 2 + 4;
// rightX = w - cursorRightW / 2 - 4;
// }
leftX = cursorLeftW / 2 + 4;
rightX = w - cursorRightW / 2 - 4;
// 縦位置の設定
leftY = h / 2;
rightY = h / 2;
// this._leftArrowSprite.move(leftX, leftY);
this._rightArrowSprite.move(rightX, rightY);
};
}
//-----------------------------------------------------------------------------
// メニューコマンド
//-----------------------------------------------------------------------------
if (pShowMenuCommand) {
/**
* ●メニューコマンド追加(メインコマンド)
*/
const _Window_MenuCommand_addMainCommands = Window_MenuCommand.prototype.addMainCommands;
Window_MenuCommand.prototype.addMainCommands = function() {
// 元処理実行
_Window_MenuCommand_addMainCommands.call(this);
// 非表示スイッチが存在かつオフの場合は無効
if (pMenuCommandSwitch && !$gameSwitches.value(pMenuCommandSwitch)) {
return;
}
// 指定位置に転職コマンドを挿入
// ※標準では装備の下
this._list.splice(pShowMenuCommandPosition, 0,
{ name: pClassChangeName, symbol: pClassChangeSymbol, enabled: true, ext: null});
};
/**
* ●メニューコマンド呼び出し先の設定
*/
const _Scene_Menu_createCommandWindow = Scene_Menu.prototype.createCommandWindow;
Scene_Menu.prototype.createCommandWindow = function() {
// 元処理実行
_Scene_Menu_createCommandWindow.call(this);
// コマンド追加(アクター選択)
this._commandWindow.setHandler(pClassChangeSymbol, this.commandPersonal.bind(this));
};
/**
* ●アクター選択
*/
const _Scene_Menu_onPersonalOk = Scene_Menu.prototype.onPersonalOk;
Scene_Menu.prototype.onPersonalOk = function() {
_Scene_Menu_onPersonalOk.apply(this, arguments);
// 転職画面に遷移
if (this._commandWindow.currentSymbol() == pClassChangeSymbol) {
// 職業一覧の生成
mClassList = editClassList(pClassList);
// アクターの変更許可
mActorNoChange = false;
// 転職画面起動
SceneManager.push(Scene_ClassChange);
}
};
}
//-----------------------------------------------------------------------------
// 画像の反映
//-----------------------------------------------------------------------------
if (pUseClassImage) {
/**
* ●顔グラ
*/
const _Game_Actor_faceName = Game_Actor.prototype.faceName;
Game_Actor.prototype.faceName = function() {
const classImage = findClassImage(this);
if (classImage && classImage.Face) {
return classImage.Face;
}
return _Game_Actor_faceName.apply(this, arguments);
};
/**
* ●顔グラ(インデックス)
*/
const _Game_Actor_faceIndex = Game_Actor.prototype.faceIndex;
Game_Actor.prototype.faceIndex = function() {
const classImage = findClassImage(this);
if (classImage && classImage.FaceIndex) {
return classImage.FaceIndex;
}
return _Game_Actor_faceIndex.apply(this, arguments);
};
/**
* ●キャラクター
*/
const _Game_Actor_characterName = Game_Actor.prototype.characterName;
Game_Actor.prototype.characterName = function() {
const classImage = findClassImage(this);
if (classImage && classImage.Character) {
return classImage.Character;
}
return _Game_Actor_characterName.apply(this, arguments);
};
/**
* ●キャラクター(インデックス)
*/
const _Game_Actor_characterIndex = Game_Actor.prototype.characterIndex;
Game_Actor.prototype.characterIndex = function() {
const classImage = findClassImage(this);
if (classImage && classImage.CharacterIndex) {
return classImage.CharacterIndex;
}
return _Game_Actor_characterIndex.apply(this, arguments);
};
/**
* ●SVアクター
*/
const _Game_Actor_battlerName = Game_Actor.prototype.battlerName;
Game_Actor.prototype.battlerName = function() {
const classImage = findClassImage(this);
if (classImage && classImage.Battler) {
return classImage.Battler;
}
return _Game_Actor_battlerName.apply(this, arguments);
};
}
//-----------------------------------------------------------------------------
// 共通関数
//-----------------------------------------------------------------------------
/**
* ●独自の職業画像が存在すればロードする。
*/
function loadClassImage() {
// 画像設定がない場合は処理終了
if (!pClassImageList) {
return;
}
// 画像の設定がある場合
for (const classImage of pClassImageList) {
if (classImage.Picture) {
ImageManager.loadPicture(classImage.Picture);
} else if (classImage.Face) {
ImageManager.loadFace(classImage.Face);
}
}
// 転職解除用に元の顔グラも読み込んでおく。
for (const actor of $gameParty.members()) {
// ※あえて_faceNameを直接参照
ImageManager.loadFace(actor._faceName);
}
// パーティにいないアクターが指定されていた場合
const tmpActor = $gameActors.actor($gameParty._menuActorId);
if (tmpActor && !$gameParty.members().includes(tmpActor)) {
// 顔グラを読み込んでおく。
ImageManager.loadFace(tmpActor._faceName);
}
};
/**
* ●独自の職業画像が存在すれば取得する。
*/
function findClassImage(actor) {
// 画像の設定がある場合
for (const classImage of pClassImageList) {
// 職業が一致する場合
if (classImage.Class == actor.currentClass().id) {
// アクターの指定がある場合
if (toNumber(classImage.Actor)) {
if (classImage.Actor == actor.actorId()) {
return classImage;
}
// アクターの指定がない場合
} else {
return classImage;
}
// 職業の指定がない場合
} else if (!classImage.Class) {
// アクターの指定がある場合
if (toNumber(classImage.Actor)) {
if (classImage.Actor == actor.actorId()) {
return classImage;
}
// アクターの指定がない場合
} else {
return classImage;
}
}
}
// 存在しなければnullを返す。
return null;
};
/**
* ●職業が選択可能かどうか?
*/
function isClassEnabled(item, actor) {
// 既に就いている職業の場合は無効
if (item.id == actor._classId) {
return false;
// 職業の重複禁止
} else if (pNoDuplicate) {
// 誰かが既にその職業へ就いている場合
if ($gameActors._data.some(dataActor => dataActor && dataActor._classId == item.id)) {
return false;
}
}
return true;
};
})();