code:
//=============================================================================
// NRP_LearnSkillList.js
//=============================================================================
/*:
 * @target MZ
 * @plugindesc v1.04 A list-style skill learning system.
 * @author Takeshi Sunagawa (https://newrpg.seesaa.net/)
 * @url https://newrpg.seesaa.net/article/499059518.html
 *
 * @help Implement a list-style skill learning system.
 *
 * It is a simple system where you spend the skill points you earn
 * and select the skill you want to learn from a list.
 *
 * Skill points can be obtained either by defeating enemies
 * or when leveling up.
 *
 * -------------------------------------------------------------------
 * [Create a Skill List]
 * -------------------------------------------------------------------
 * First, register the skill sets in the "SkillSetList"
 * plugin parameter. Register more skill information under it.
 *
 * You can specify conditions for the skill set,
 * such as which actors to target.
 * If no conditions are specified, the skills are common to all.
 *
 * Other conditions, such as prerequisite skills,
 * can be specified for each skill.
 *
 * Selecting the "Learn Skills" command
 * from the menu will bring up the Skill Learning System screen.
 *
 * -------------------------------------------------------------------
 * [Setting Skill Points]
 * -------------------------------------------------------------------
 * You can choose between "Each Actor" and "Party Sharing"
 * as your skill point management method.
 *
 * In the case of Party Sharing, skill points are stored in variables,
 * so they can be controlled by "Control Variables"
 * in the event command.
 *
 * -------------------------------------------------------------------
 * [Note of Enemies]
 * -------------------------------------------------------------------
 * <SkillPoint:?>
 * Specify the skill points to be earned.
 *
 * You can also specify a default value with a plugin parameter.
 * If it is too much trouble to specify the details,
 * it is easier to set the value proportional to exp or level.
 *
 * <SkillPointRate:?>
 * Change the skill points earned to the specified %.
 * For example, 200 would be 200% (double).
 * Intended to be used in combination with the default value.
 *
 * -------------------------------------------------------------------
 * [Note of Items]
 * -------------------------------------------------------------------
 * <AddSkillPoint:?>
 * Increases the actor's skill points by a numerical value.
 *
 * -------------------------------------------------------------------
 * [Plugin Commands]
 * -------------------------------------------------------------------
 * ◆SceneStart
 * Calls up the skill learning scene.
 * If no actor is specified,
 * the actor selection scene is also displayed.
 *
 * ◆ChangeSkillPoint
 * Increases or decreases the actor's skill points.
 * It cannot be less than 0.
 *
 * ◆ResetSkill
 * Forget the skills learned and restore the skill points.
 *
 * -------------------------------------------------------------------
 * [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.
 *
 * @-----------------------------------------------------
 * @ [Plugin Commands]
 * @-----------------------------------------------------
 *
 * @command SceneStart
 * @desc Calls up the skill learning scene. If no actor is specified, the actor selection scene is also displayed.
 *
 * @arg Actor
 * @type actor
 * @desc Actor to be targeted. If not specified, the selected scene of the actor is displayed.
 *
 * @arg VariableActor
 * @type variable
 * @desc Specify the target actor by variable.
 * This one takes precedence over the other.
 *
 * @-----------------------------------------------------
 *
 * @command ChangeSkillPoint
 * @desc Change skill points.
 * Specify the target condition (AND).
 *
 * @arg SkillPoint
 * @type number @min -9999999 @max 9999999
 * @desc The amount of skill points to increase or decrease. Negative value can be specified.
 *
 * @arg VariableSkillPoint
 * @type variable
 * @desc The variable specifies the amount of skill points to increase or decrease. This takes precedence.
 *
 * @arg <Condition>
 *
 * @arg Actor
 * @parent <Condition>
 * @type actor
 * @desc Actor to target.
 * If unspecified, the entire party is targeted.
 *
 * @arg VariableActor
 * @parent <Condition>
 * @type variable
 * @desc Specify the target actor by variable.
 * This one takes precedence over the other.
 *
 * @-----------------------------------------------------
 *
 * @command ResetSkill
 * @desc Forget the skills learned and restore the skill points.
 *
 * @arg Actor
 * @type actor
 * @desc Actor to target.
 * If unspecified, the entire party is targeted.
 *
 * @arg VariableActor
 * @type variable
 * @desc Specify the target actor by variable.
 * This one takes precedence over the other.
 *
 * @-----------------------------------------------------
 * @ [Plugin Parameters]
 * @-----------------------------------------------------
 *
 * @param SkillSetList
 * @type struct<SkillSet>[]
 * @desc Define the skill set to be learned.
 *
 * @param <SkillPoint>
 * @desc This section is about skill points.
 *
 * @param SkillPointName
 * @parent <SkillPoint>
 * @type string
 * @default SP
 * @desc The display name for the skill points.
 *
 * @param MaxSkillPoint
 * @parent <SkillPoint>
 * @type number
 * @default 999999
 * @desc The maximum value of skill points.
 * It cannot be greater than this value.
 *
 * @param SkillPointType
 * @parent <SkillPoint>
 * @type select
 * @option Each Actor @value actor
 * @option Party Sharing @value party
 * @default actor
 * @desc How to hold skill points.
 * You can choose between each actor or party sharing.
 *
 * @param SkillPointVariable
 * @parent <SkillPoint>
 * @type variable
 * @desc This variable stores skill points. Valid only when party sharing is selected for SkillPointType.
 *
 * @param SkillPointMessage
 * @parent <SkillPoint>
 * @type string
 * @default %1 %2 received!
 * @desc Displays a statement of skill points earned.
 * %1=number, %2=name of skill points to be displayed.
 *
 * @param DefaultEnemySkillPoint
 * @parent <SkillPoint>
 * @type string
 * @desc Default value of skill points dropped by enemies.
 * Formula acceptable (e.g: 1 + Math.floor(a.exp() / 100))
 *
 * @param SkillPointSwitch
 * @parent <SkillPoint>
 * @type switch
 * @desc If the switch is on, the increase or decrease in skill points is valid. If blank, always enabled.
 *
 * @param BenchSkillPointRate
 * @parent <SkillPoint>
 * @type string
 * @default 1.00
 * @desc The percentage of SP earned by reserve members. If blank, the same rate as normal experience is used.
 *
 * @param LevelUpSkillPoint
 * @parent <SkillPoint>
 * @type string
 * @desc Skill points earned upon level-up.
 * Formula acceptable (e.g: a.level)
 *
 * @param <SkillListWindow>
 * @desc This item relates to the Skill List window.
 *
 * @param LearnedSkillDisplayStyle
 * @parent <SkillListWindow>
 * @type select
 * @option Display @value display
 * @option Hide @value hide
 * @option Display Below @value below
 * @default display
 * @desc This is how the learned skills are displayed.
 *
 * @param UseIcon
 * @parent <SkillListWindow>
 * @type boolean
 * @default true
 * @desc Whether the icon should appear before the name of the skill?
 *
 * @param SkillPointColor
 * @parent <SkillListWindow>
 * @type number
 * @default 0
 * @desc Skill point text color.
 * Specify the number of the system color.
 *
 * @param LearnedText
 * @parent <SkillListWindow>
 * @type string
 * @default Learned
 * @desc The wording to be displayed on the learned skills.
 * This is displayed at the location of the skill point.
 *
 * @param LearnedTextColor
 * @parent <SkillListWindow>
 * @type number
 * @default 6
 * @desc The color of the learned skill statement.
 * Specify the number of the system color.
 *
 * @param ShowHiddenSkills
 * @parent <SkillListWindow>
 * @type boolean
 * @default false
 * @desc Display skills that do not meet the conditions.
 * If you want to display conditions, expand help.
 *
 * @param HiddenSymbol
 * @parent ShowHiddenSkills
 * @type string
 * @default *
 * @desc Symbols to be displayed on hidden skills.
 *
 * @param HelpLines
 * @parent ShowHiddenSkills
 * @type number
 * @desc Change the number of lines of help.
 * Set to display hidden skill conditions.
 *
 * @param HiddenSkillMask
 * @parent ShowHiddenSkills
 * @type string
 * @desc Mask hidden skills with this string.
 * It will be displayed when the condition is met.
 *
 * @param HiddenHelp
 * @parent ShowHiddenSkills
 * @type boolean
 * @default false
 * @desc Hide hidden skills help (except for postscripts).
 * It will be displayed when the conditions are met.
 *
 * @param <ActorWindow>
 * @desc This item is related to the actor window.
 *
 * @param ActorWindowWidth
 * @parent <ActorWindow>
 * @type number
 * @default 240
 * @desc The width of the actor window.
 *
 * @param ActorWindowHeight
 * @parent <ActorWindow>
 * @type number
 * @default 280
 * @desc The height of the actor window.
 * If blank, it is extended to the maximum.
 *
 * @param <ConfirmWindow>
 * @desc This item relates to the confirmation window when learning the skill system.
 *
 * @param ConfirmMessage
 * @parent <ConfirmWindow>
 * @type multiline_string
 * @default Do you want to learn %1?
 * @desc A message confirming the acquisition of a skill.
 * %1=Skill Name %2=Icon %3=Skill Points
 *
 * @param ConfirmButtonOk
 * @parent <ConfirmWindow>
 * @type string
 * @default OK
 * @desc The display of a button to confirm the message confirming the acquisition of a skill.
 *
 * @param ConfirmButtonCancel
 * @parent <ConfirmWindow>
 * @type string
 * @default Cancel
 * @desc The display of a button to cancel the message confirming the acquisition of a skill.
 *
 * @param ConfirmOkSe
 * @parent <ConfirmWindow>
 * @type file
 * @dir audio/se
 * @default Decision5
 * @desc The sound effect when the learning of a skill is confirmed.
 *
 * @param <Menu Command>
 * @desc This is the relevant section for displaying the skill system in the menu commands.
 *
 * @param ShowMenuCommandPosition
 * @parent <Menu Command>
 * @type number
 * @default 4
 * @desc The position where the function is inserted into the menu command. 0 is the first position.
 *
 * @param CommandName
 * @parent <Menu Command>
 * @type text
 * @default Learn Skills
 * @desc Sets the display command name for the skill system.
 *
 * @param MenuCommandSwitch
 * @parent <Menu Command>
 * @type switch
 * @desc Displays the command only when the switch is on.
 * If blank, it is always displayed.
 *
 * @param MaskString
 * @parent MenuCommandSwitch
 * @type string
 * @desc If MenuCommandSwitch is off, displays the specified string. If blank, hides the command itself.
 *
 * @param DisableSwitch
 * @parent <Menu Command>
 * @type switch
 * @desc Disallow command only when switch is on.
 * Always allow if blank.
 */

/*~struct~SkillSet:
 * @param Note
 * @type string
 * @desc Identification note.
 *
 * @param SkillList
 * @type struct<SkillData>[]
 * @desc Define the skill list.
 *
 * @param <Condition>
 *
 * @param Actor
 * @parent <Condition>
 * @type actor
 * @desc Actor to display skill set.
 * If blank, it will be the same for all.
 *
 * @param Switch
 * @parent <Condition>
 * @type switch
 * @desc This switch is a condition for displaying skill sets.
 *
 * @param Script
 * @parent <Condition>
 * @type string
 * @desc This script is the condition for displaying skill sets.
 * e.g: a.isLearnedSkill(1) && a.isLearnedSkill(2)
 */

/*~struct~SkillData:
 * @param Note
 * @type string
 * @desc Identification note.
 *
 * @param Skill
 * @type skill
 * @desc Skills to be learned.
 *
 * @param SkillPoint
 * @type number
 * @desc Skill points required for learning.
 *
 * @param DisplayName
 * @type string
 * @desc This is the name displayed on the learning screen.
 * %1:Skill Name, %2:Icon If blank, skill name.
 *
 * @param HelpPostscript
 * @type multiline_string
 * @desc Text to be added to the help.
 * Mainly intended to describe learning conditions.
 *
 * @param LearnedSkillDisplayStyle
 * @type select
 * @option display
 * @option hide
 * @desc How the learned skills are displayed.
 * If blank, the overall setting is applied.
 *
 * @param <Condition>
 *
 * @param ConditionSkill
 * @parent <Condition>
 * @type skill
 * @desc Only display skills if they have mastered the specified skill.
 *
 * @param Switch
 * @parent <Condition>
 * @type switch
 * @desc This switch is a condition for displaying skill.
 *
 * @param Script
 * @parent <Condition>
 * @type string
 * @desc This script is the condition for displaying skill.
 * e.g: a.isLearnedSkill(1) && a.isLearnedSkill(2)
 */

/*:ja
 * @target MZ
 * @plugindesc v1.04 リスト形式のスキル習得システム。
 * @author 砂川赳（https://newrpg.seesaa.net/）
 * @url https://newrpg.seesaa.net/article/499059518.html
 *
 * @help リスト形式のスキル習得システムを実装します。
 *
 * 獲得したスキルポイントを消費し、
 * 表から覚えたいスキルを選択するシンプルな仕組みです。
 *
 * スキルポイントは敵から入手したり、
 * レベルアップ時に入手したりといった方法を選択できます。
 *
 * -------------------------------------------------------------------
 * ■スキルリストの作成
 * -------------------------------------------------------------------
 * まずプラグインパラメータの『スキルセットのリスト』に
 * スキルセットを登録し、その下へさらにスキル情報を登録してください。
 *
 * スキルセットには対象とするアクターなどの条件を指定できます。
 * 条件を指定しなかった場合は全員共通のスキルとなります。
 *
 * 他にも、スキル毎に前提スキルなどの条件を指定できます。
 *
 * メニューから『スキル習得』のコマンドを選択すれば、
 * スキル習得システムの画面が表示されるようになります。
 *
 * -------------------------------------------------------------------
 * ■スキルポイントの設定
 * -------------------------------------------------------------------
 * スキルポイントの保有方法として『アクター毎』と『パーティ共有』の
 * 二種類から選択できます。
 *
 * パーティ共有の場合は変数内に格納するため、
 * イベントコマンドの『変数の操作』での制御が可能となります。
 *
 * -------------------------------------------------------------------
 * ■敵キャラのメモ欄
 * -------------------------------------------------------------------
 * <SkillPoint:?>
 * 獲得できるスキルポイントを指定します。
 *
 * また、プラグインパラメータで既定値を指定することもできます。
 * 細かい指定が面倒なら、経験値やレベルに比例する値にしてしまえば楽です。
 *
 * <SkillPointRate:?>
 * 獲得できるスキルポイントを指定した%に変更します。
 * 例えば、200ならば200%（２倍）になります。
 * 既定値とのセットで使うことを想定しています。
 *
 * -------------------------------------------------------------------
 * ■アイテムのメモ欄
 * -------------------------------------------------------------------
 * <AddSkillPoint:?>
 * アクターのスキルポイントを数値分増加させます。
 *
 * -------------------------------------------------------------------
 * ■プラグインコマンド
 * -------------------------------------------------------------------
 * ◆シーン開始
 * スキル習得画面を呼び出します。
 * アクターを指定しない場合は、アクター選択画面も表示します。
 *
 * ◆スキルポイントの増減
 * アクターのスキルポイントを増減させます。
 * なお、0未満にはなりません。
 *
 * ◆スキルリセット
 * 習得したスキルを忘れて、スキルポイントを元に戻します。
 *
 * -------------------------------------------------------------------
 * ■利用規約
 * -------------------------------------------------------------------
 * 特に制約はありません。
 * 改変、再配布自由、商用可、権利表示も任意です。
 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。
 *
 * @-----------------------------------------------------
 * @ プラグインコマンド
 * @-----------------------------------------------------
 *
 * @command SceneStart
 * @text シーン開始
 * @desc スキル習得画面を呼び出します。
 * アクターを指定しない場合は、アクター選択画面も表示。
 *
 * @arg Actor
 * @text アクター
 * @type actor
 * @desc 対象とするアクターです。
 * 指定がない場合は、アクターの選択画面を表示します。
 *
 * @arg VariableActor
 * @text アクター（変数）
 * @type variable
 * @desc 対象とするアクターを変数で指定します。
 * こちらのほうが優先されます。
 *
 * @-----------------------------------------------------
 *
 * @command ChangeSkillPoint
 * @text スキルポイントの増減
 * @desc スキルポイントを変更します。
 * 対象条件（ＡＮＤ）を指定してください。
 *
 * @arg SkillPoint
 * @text スキルポイント
 * @type number @min -9999999 @max 9999999
 * @desc 増減するスキルポイントの量です。マイナス指定可。
 *
 * @arg VariableSkillPoint
 * @text スキルポイント（変数）
 * @type variable
 * @desc 増減するスキルポイントの量を変数で指定します。
 * こちらのほうが優先されます。
 *
 * @arg <Condition>
 * @text ＜対象条件＞
 *
 * @arg Actor
 * @parent <Condition>
 * @text アクター
 * @type actor
 * @desc 対象とするアクターです。
 * 未指定ならパーティ全体を対象とします。
 *
 * @arg VariableActor
 * @parent <Condition>
 * @text アクター（変数）
 * @type variable
 * @desc 対象とするアクターを変数で指定します。
 * こちらのほうが優先されます。
 *
 * @-----------------------------------------------------
 *
 * @command ResetSkill
 * @text スキルリセット
 * @desc 習得したスキルを忘れて、スキルポイントを元に戻します。
 *
 * @arg Actor
 * @text アクター
 * @type actor
 * @desc 対象とするアクターです。
 * 未指定ならパーティ全体を対象とします。
 *
 * @arg VariableActor
 * @text アクター（変数）
 * @type variable
 * @desc 対象とするアクターを変数で指定します。
 * こちらのほうが優先されます。
 *
 * @-----------------------------------------------------
 * @ プラグインパラメータ
 * @-----------------------------------------------------
 *
 * @param SkillSetList
 * @text スキルセットのリスト
 * @type struct<SkillSet>[]
 * @desc 習得するスキルセットを定義します。
 *
 * @param <SkillPoint>
 * @text ＜スキルポイント＞
 * @desc スキルポイントに関する項目です。
 *
 * @param SkillPointName
 * @text スキルポイントの表示名
 * @parent <SkillPoint>
 * @type string
 * @default SP
 * @desc スキルポイントを表す表示名です。
 *
 * @param MaxSkillPoint
 * @text スキルポイントの最大値
 * @parent <SkillPoint>
 * @type number
 * @default 999999
 * @desc スキルポイントの最大値です。
 * これ以上の値にはなりません。
 *
 * @param SkillPointType
 * @text スキルポイントの保有方法
 * @parent <SkillPoint>
 * @type select
 * @option アクター毎 @value actor
 * @option パーティ共有 @value party
 * @default actor
 * @desc スキルポイントの保有方法です。
 * アクター毎かパーティ共有かを選択できます。
 *
 * @param SkillPointVariable
 * @text スキルポイントの変数
 * @parent <SkillPoint>
 * @type variable
 * @desc スキルポイントを格納する変数です。
 * 保有方法にパーティ共有を選んだ場合のみ有効です。
 *
 * @param SkillPointMessage
 * @parent <SkillPoint>
 * @text スキルポイント獲得文
 * @type string
 * @default %1 の%2を獲得！
 * @desc スキルポイントの獲得文を表示します。
 * %1=数値, %2=スキルポイントの表示名となります。
 *
 * @param DefaultEnemySkillPoint
 * @text 敵スキルポイントの既定値
 * @parent <SkillPoint>
 * @type string
 * @desc 敵が落とすスキルポイントの既定値を設定します。
 * 数式可（例：1 + Math.floor(a.exp() / 100)）
 *
 * @param SkillPointSwitch
 * @text ＳＰ有効化スイッチ
 * @parent <SkillPoint>
 * @type switch
 * @desc 指定のスイッチがオンの際、スキルポイントの増減を有効化します。空白なら常に有効。
 *
 * @param BenchSkillPointRate
 * @text 控えの獲得率
 * @parent <SkillPoint>
 * @type string
 * @default 1.00
 * @desc 控えメンバーのスキルポイントの獲得率です。数式可
 * 空白の場合は通常経験値と同率を使用。
 *
 * @param LevelUpSkillPoint
 * @text レベルアップ時のSP
 * @parent <SkillPoint>
 * @type string
 * @desc レベルアップ時に獲得できるスキルポイントです。
 * 数式可（例：a.level）
 *
 * @param <SkillListWindow>
 * @text ＜スキルリスト関連＞
 * @desc スキルリストウィンドウに関する項目です。
 *
 * @param LearnedSkillDisplayStyle
 * @text 習得済スキルの表示方法
 * @parent <SkillListWindow>
 * @type select
 * @option そのまま @value display
 * @option 非表示 @value hide
 * @option 下に表示 @value below
 * @default display
 * @desc 習得したスキルの表示方法です。
 *
 * @param UseIcon
 * @text アイコンを表示
 * @parent <SkillListWindow>
 * @type boolean
 * @default true
 * @desc アイコンをスキル名の前に表示するかどうか？
 *
 * @param SkillPointColor
 * @text スキルポイントの色
 * @parent <SkillListWindow>
 * @type number
 * @default 0
 * @desc スキルポイントの文字色です。
 * システムカラーの番号を指定してください。
 *
 * @param LearnedText
 * @text 習得済の表示文
 * @parent <SkillListWindow>
 * @type string
 * @default 済
 * @desc 習得済スキルに表示する文言です。
 * スキルポイントの場所に表示されます。
 *
 * @param LearnedTextColor
 * @text 習得済の色
 * @parent <SkillListWindow>
 * @type number
 * @default 6
 * @desc 習得済スキルに表示する文言の色です。
 * システムカラーの番号を指定してください。
 *
 * @param ShowHiddenSkills
 * @text 隠しスキルを表示
 * @parent <SkillListWindow>
 * @type boolean
 * @default false
 * @desc 条件を満たしていないスキルを表示します。
 * 条件表示する場合はヘルプの行数は３以上に。
 *
 * @param HiddenSymbol
 * @text 隠しスキルの記号
 * @parent ShowHiddenSkills
 * @type string
 * @default ※
 * @desc 隠しスキルに表示する記号です。
 *
 * @param HelpLines
 * @text ヘルプの行数
 * @parent ShowHiddenSkills
 * @type number
 * @desc ヘルプの行数を変更します。
 * 隠しスキルの条件表示を行うための設定です。
 *
 * @param HiddenSkillMask
 * @text 隠しスキルのマスク
 * @parent ShowHiddenSkills
 * @type string
 * @desc 隠しスキルを指定した文字列（？など）で隠します。
 * 条件を満たすと表示されるようになります。
 *
 * @param HiddenHelp
 * @text ヘルプを隠す
 * @parent ShowHiddenSkills
 * @type boolean
 * @default false
 * @desc 隠しスキルのヘルプ（追記除く）を隠します。
 * 条件を満たすと表示されるようになります。
 *
 * @param <ActorWindow>
 * @text ＜アクターウィンドウ関連＞
 * @desc アクターウィンドウに関する項目です。
 *
 * @param ActorWindowWidth
 * @text アクターウィンドウの横幅
 * @parent <ActorWindow>
 * @type number
 * @default 240
 * @desc アクターウィンドウの横幅です。
 *
 * @param ActorWindowHeight
 * @text アクターウィンドウの縦幅
 * @parent <ActorWindow>
 * @type number
 * @default 280
 * @desc アクターウィンドウの縦幅です。
 * 空白の場合は最大まで伸ばします。
 *
 * @param <ConfirmWindow>
 * @text ＜確認ウィンドウ関連＞
 * @desc スキルシステムを習得する際の確認ウィンドウに関する項目です。
 *
 * @param ConfirmMessage
 * @text 確認メッセージ
 * @parent <ConfirmWindow>
 * @type multiline_string
 * @default %1を習得しますか？
 * @desc スキルの習得確認メッセージの内容です。
 * %1=スキル名、%2=アイコン、%3=スキルポイントです。
 *
 * @param ConfirmButtonOk
 * @text ＯＫの文言
 * @parent <ConfirmWindow>
 * @type string
 * @default ＯＫ
 * @desc スキルの習得確認メッセージを確定する際のボタンの表示です。
 *
 * @param ConfirmButtonCancel
 * @text キャンセルの文言
 * @parent <ConfirmWindow>
 * @type string
 * @default キャンセル
 * @desc スキルの習得確認メッセージをキャンセルする際のボタンの表示です。
 *
 * @param ConfirmOkSe
 * @text 確定時のＳＥ
 * @parent <ConfirmWindow>
 * @type file
 * @dir audio/se
 * @default Decision5
 * @desc スキルの習得を確定した際の効果音です。
 *
 * @param <Menu Command>
 * @text ＜メニューコマンド関連＞
 * @desc メニューコマンドにスキルシステムを表示する際の関連項目です。
 *
 * @param ShowMenuCommandPosition
 * @parent <Menu Command>
 * @text メニューコマンド挿入位置
 * @type number
 * @default 4
 * @desc メニューコマンドにスキル習得を挿入する位置です。
 * 0が先頭。不要ならDELで消去してください。
 *
 * @param CommandName
 * @parent <Menu Command>
 * @text メニュー表示名
 * @type text
 * @default スキル習得
 * @desc スキルシステムの表示コマンド名を設定します。
 *
 * @param MenuCommandSwitch
 * @parent <Menu Command>
 * @text 表示許可するスイッチ
 * @type switch
 * @desc スイッチがオンの時のみコマンドを表示します。
 * 空白なら常に表示します。
 *
 * @param MaskString
 * @parent MenuCommandSwitch
 * @text マスク文字列
 * @type string
 * @desc 表示許可するスイッチがオフの際、指定した文字列でコマンドを表示します。空欄ならコマンド自体を非表示。
 *
 * @param DisableSwitch
 * @parent <Menu Command>
 * @text 禁止するスイッチ
 * @type switch
 * @desc スイッチがオンの時のみコマンドを禁止（灰色）します。
 * 空白なら常に許可します。
 */

/*~struct~SkillSet:ja
 * @param Note
 * @text メモ
 * @type string
 * @desc 識別用のメモです。
 *
 * @param SkillList
 * @text スキルリスト
 * @type struct<SkillData>[]
 * @desc スキルリストを定義します。
 *
 * @param <Condition>
 * @text ＜条件＞
 *
 * @param Actor
 * @parent <Condition>
 * @text アクター
 * @type actor
 * @desc スキルセットを表示するアクターです。
 * 空欄なら全員共通になります。
 *
 * @param Switch
 * @parent <Condition>
 * @text スイッチ
 * @type switch
 * @desc スキルセットを表示する条件となるスイッチです。
 *
 * @param Script
 * @parent <Condition>
 * @text スクリプト
 * @type string
 * @desc スキルセットを表示する条件となるスクリプトです。
 * 例：a.isLearnedSkill(1) && a.isLearnedSkill(2)
 */

/*~struct~SkillData:ja
 * @param Note
 * @text メモ
 * @type string
 * @desc 識別用のメモです。
 *
 * @param Skill
 * @text スキル
 * @type skill
 * @desc 習得するスキルです。
 *
 * @param SkillPoint
 * @text スキルポイント
 * @type number
 * @desc 習得に必要なスキルポイントです。
 *
 * @param DisplayName
 * @text 表示名
 * @type string
 * @desc 習得画面での表示名です。
 * %1:スキル名,%2:アイコン。空白ならスキル名を使用。
 *
 * @param HelpPostscript
 * @text ヘルプに追記
 * @type multiline_string
 * @desc ヘルプに追記する文章です。
 * 主に習得条件の記述を想定しています。
 *
 * @param LearnedSkillDisplayStyle
 * @text 習得済スキルの表示方法
 * @type select
 * @option そのまま @value display
 * @option 非表示 @value hide
 * @desc 習得したスキルの表示方法です。
 * こちらはスキル個別の設定。空欄だと全体設定を適用。
 *
 * @param <Condition>
 * @text ＜条件＞
 *
 * @param ConditionSkill
 * @parent <Condition>
 * @text スキル
 * @type skill
 * @desc 指定のスキルを習得している場合のみスキルを表示します。
 *
 * @param Switch
 * @parent <Condition>
 * @text スイッチ
 * @type switch
 * @desc スキルを表示する条件となるスイッチです。
 *
 * @param Script
 * @parent <Condition>
 * @text スクリプト
 * @type string
 * @desc スキルを表示する条件となるスクリプトです。
 * 例：a.isLearnedSkill(1) && a.isLearnedSkill(2)
 */
(function () {
  "use strict";

  /**
   * ●構造体をJSで扱えるように変換
   */
  function parseStruct1(arg) {
    var ret = [];

    JSON.parse(arg).forEach(function (str) {
      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 toNumber(str, def) {
    if (str == undefined || str == "") {
      return def;
    }
    return isNaN(str) ? def : +(str || def);
  }
  function toBoolean(str, def) {
    if (str === true || str === "true") {
      return true;
    } else if (str === false || str === "false") {
      return false;
    }
    return def;
  }
  function setDefault(str, def) {
    if (str == undefined || str == "") {
      return def;
    }
    return str;
  }

  const PLUGIN_NAME = "NRP_LearnSkillList";
  const parameters = PluginManager.parameters(PLUGIN_NAME);
  const pSkillSetList = parseStruct2(parameters["SkillSetList"]);
  // スキルポイント
  const pSkillPointName = setDefault(parameters["SkillPointName"], "");
  const pMaxSkillPoint = toNumber(parameters["MaxSkillPoint"], 999999);
  const pSkillPointType = setDefault(parameters["SkillPointType"]);
  const pSkillPointVariable = setDefault(parameters["SkillPointVariable"]);
  const pSkillPointMessage = setDefault(parameters["SkillPointMessage"], "");
  const pDefaultEnemySkillPoint = setDefault(
    parameters["DefaultEnemySkillPoint"]
  );
  const pSkillPointSwitch = toNumber(parameters["SkillPointSwitch"]);
  const pBenchSkillPointRate = setDefault(parameters["BenchSkillPointRate"]);
  const pLevelUpSkillPoint = setDefault(parameters["LevelUpSkillPoint"]);
  // スキルリストウィンドウ関連
  const pLearnedSkillDisplayStyle = parameters["LearnedSkillDisplayStyle"];
  const pSkillPointColor = toNumber(parameters["SkillPointColor"], 0);
  const pLearnedText = setDefault(parameters["LearnedText"]);
  const pLearnedTextColor = toNumber(parameters["LearnedTextColor"], 0);
  const pUseIcon = toBoolean(parameters["UseIcon"]);
  const pShowHiddenSkills = toBoolean(parameters["ShowHiddenSkills"]);
  const pHiddenSymbol = setDefault(parameters["HiddenSymbol"]);
  const pHelpLines = toNumber(parameters["HelpLines"]);
  const pHiddenSkillMask = setDefault(parameters["HiddenSkillMask"]);
  const pHiddenHelp = toBoolean(parameters["HiddenHelp"]);
  // アクターウィンドウ関連
  const pActorWindowWidth = toNumber(parameters["ActorWindowWidth"]);
  const pActorWindowHeight = toNumber(parameters["ActorWindowHeight"]);
  // 確認ウィンドウ関連
  const pConfirmMessage = parameters["ConfirmMessage"];
  const pConfirmButtonOk = parameters["ConfirmButtonOk"];
  const pConfirmButtonCancel = parameters["ConfirmButtonCancel"];
  const pConfirmOkSe = setDefault(parameters["ConfirmOkSe"]);
  // メニューコマンド関連
  const pShowMenuCommandPosition = toNumber(
    parameters["ShowMenuCommandPosition"]
  );
  const pCommandName = parameters["CommandName"];
  const pMenuCommandSwitch = toNumber(parameters["MenuCommandSwitch"]);
  const pMaskString = setDefault(parameters["MaskString"]);
  const pDisableSwitch = toNumber(parameters["DisableSwitch"]);

  // 定数
  const SYMBOL_SKILL_SYSTEM = "skillSystem";
  const SKILL_POINT_KEY = "skillPoint";

  //-----------------------------------------------------------------------------
  // ＭＺ用プラグインコマンド
  //-----------------------------------------------------------------------------

  /**
   * ●シーン開始
   */
  PluginManager.registerCommand(PLUGIN_NAME, "SceneStart", function (args) {
    // アクターを取得
    const actor = getActor(args);
    // 対象に設定
    if (actor) {
      $gameParty.setMenuActor(actor);
      // 指定がない場合はクリア
    } else {
      $gameParty._menuActorId = 0;
    }

    // 選択肢ウィンドウが存在する場合は非表示
    // ※ゴミが残らないようにするため
    if (SceneManager._scene._choiceListWindow) {
      SceneManager._scene._choiceListWindow.hide();
    }

    // シーン開始
    if ($gameParty._menuActorId) {
      SceneManager.push(Scene_LearnSkillList);
    } else {
      SceneManager.push(Scene_LearnSkillSelectActor);
    }
  });

  /**
   * ●スキルポイントの増減
   */
  PluginManager.registerCommand(
    PLUGIN_NAME,
    "ChangeSkillPoint",
    function (args) {
      // スキルポイント
      const skillPoint = getSkillPoint(args);

      // パーティ共有の場合
      if (pSkillPointType == "party") {
        const variableNo = eval(pSkillPointVariable);
        const currentSp = $gameVariables.value(variableNo);

        let newValue = currentSp + skillPoint;
        if (newValue > pMaxSkillPoint) {
          newValue = pMaxSkillPoint;
          // マイナスの場合は0をセット
        } else if (newValue < 0) {
          newValue = 0;
        }
        // 変数の値を加算
        $gameVariables.setValue(variableNo, newValue);
        return;
      }

      // アクターを取得
      const actor = getActor(args);
      if (actor) {
        actor.changeSkillPoint(skillPoint);

        // アクターの指定がない場合は全体を対象化
      } else if (isForParty(args)) {
        // 通常時
        for (const actor of $gameParty.members()) {
          actor.changeSkillPoint(skillPoint);
        }
      }
    }
  );

  /**
   * ●スキルリセット
   */
  PluginManager.registerCommand(PLUGIN_NAME, "ResetSkill", function (args) {
    // アクターを取得
    const actor = getActor(args);
    if (actor) {
      // リセット実行
      actor.resetLearnSkill();

      // アクターの指定がない場合は全体を対象化
    } else if (isForParty(args)) {
      for (const actor of $gameParty.members()) {
        // リセット実行
        actor.resetLearnSkill();
      }
    }
  });

  /**
   * ●スキルポイントを取得
   */
  function getSkillPoint(args) {
    let skillPoint = setDefault(args.SkillPoint);

    // 変数の指定がある場合は優先
    const variablSp = setDefault(args.VariableSkillPoint);
    if (variablSp) {
      skillPoint = $gameVariables.value(variablSp);
    }

    return eval(skillPoint);
  }

  /**
   * ●アクターを取得
   */
  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 isForParty(args) {
    const actorId = setDefault(args.Actor);
    const variablActor = setDefault(args.VariableActor);
    return !actorId && !variablActor;
  }

  //-----------------------------------------------------------------------------
  // Scene_LearnSkillSelectActor
  //
  // アクター選択シーン用クラス

  function Scene_LearnSkillSelectActor() {
    this.initialize(...arguments);
  }

  Scene_LearnSkillSelectActor.prototype = Object.create(
    Scene_MenuBase.prototype
  );
  Scene_LearnSkillSelectActor.prototype.constructor =
    Scene_LearnSkillSelectActor;

  Scene_LearnSkillSelectActor.prototype.initialize = function () {
    Scene_MenuBase.prototype.initialize.call(this);
  };

  /**
   * ●ウィンドウの生成
   */
  Scene_LearnSkillSelectActor.prototype.create = function () {
    Scene_MenuBase.prototype.create.call(this);

    // アクター選択用ウィンドウ
    this.createStatusWindow();
  };

  /**
   * ●アクター選択用ウィンドウの作成
   */
  Scene_LearnSkillSelectActor.prototype.createStatusWindow = function () {
    const rect = this.statusWindowRect();
    this._statusWindow = new Window_MenuStatus(rect);
    this._statusWindow.setHandler("ok", this.onActorOk.bind(this));
    this._statusWindow.setHandler("cancel", this.popScene.bind(this));
    this.addWindow(this._statusWindow);
  };

  /**
   * ●ステータスウィンドウ用の領域を確保
   */
  Scene_LearnSkillSelectActor.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);
  };

  /**
   * ●ヘルプウィンドウの縦幅
   * ※存在しないので0
   */
  Scene_LearnSkillSelectActor.prototype.helpAreaHeight = function () {
    return 0;
  };

  /**
   * ●処理開始
   */
  Scene_LearnSkillSelectActor.prototype.start = function () {
    Scene_MenuBase.prototype.start.call(this);

    // アクター選択用ウィンドウを表示＆フォーカス
    this._statusWindow.show();
    this._statusWindow.activate();

    // スキルシステムから戻ってきた際は選択状況を再現
    this._statusWindow.smoothSelect($gameParty.menuActor().index() || 0);

    // 描画更新（顔グラ）
    this._statusWindow.refresh();
  };

  /**
   * ●アクターの選択確定
   */
  Scene_LearnSkillSelectActor.prototype.onActorOk = function () {
    // アクター選択ウィンドウの選択結果を反映
    const actor = this._statusWindow.actor(this._statusWindow.index());
    $gameParty.setMenuActor(actor);
    // スキルシステムへ遷移
    SceneManager.push(Scene_LearnSkillList);
  };

  //-----------------------------------------------------------------------------
  // Scene_LearnSkillList
  //
  // スキルシステムシーン用クラス

  function Scene_LearnSkillList() {
    this.initialize(...arguments);
  }

  Scene_LearnSkillList.prototype = Object.create(Scene_MenuBase.prototype);
  Scene_LearnSkillList.prototype.constructor = Scene_LearnSkillList;

  Scene_LearnSkillList.prototype.initialize = function () {
    Scene_MenuBase.prototype.initialize.call(this);
    Scene_Message.prototype.initialize.call(this);
  };

  /**
   * ●ウィンドウの生成
   */
  Scene_LearnSkillList.prototype.create = function () {
    Scene_MenuBase.prototype.create.call(this);

    // ヘルプウィンドウ
    this.createHelpWindow();

    // アクター用ウィンドウ
    this.createActorWindow();

    // スキルリストウィンドウ
    this.createSkillListWindow();

    // 確認ウィンドウ
    this.createConfirmWindow();

    // // メッセージ表示用の設定
    // this.createMessageWindows();
  };

  /**
   * ●ヘルプウィンドウの縦幅
   */
  Scene_LearnSkillList.prototype.helpAreaHeight = function () {
    if (pHelpLines != null) {
      return this.calcWindowHeight(pHelpLines, false);
    }
    return Scene_MenuBase.prototype.helpAreaHeight.call(this);
  };

  /**
   * ●スキルリストウィンドウの作成
   */
  Scene_LearnSkillList.prototype.createSkillListWindow = function () {
    let wx = this._actorWindow.width;
    let wy = this.mainAreaTop();
    const ww = Graphics.boxWidth - wx;
    const wh =
      Graphics.boxHeight - this.buttonAreaHeight() - this.helpAreaHeight();
    this._skillListWindow = new Window_LearnSkillList(
      new Rectangle(wx, wy, ww, wh)
    );
    this._skillListWindow.setHelpWindow(this._helpWindow);
    this._skillListWindow.setHandler("ok", this.onSkillListOk.bind(this));
    this._skillListWindow.setHandler(
      "cancel",
      this.onSkillListCancel.bind(this)
    );
    this._skillListWindow.setHandler("pagedown", this.nextActor.bind(this));
    this._skillListWindow.setHandler("pageup", this.previousActor.bind(this));
    this.addWindow(this._skillListWindow);
  };

  /**
   * ●アクターウィンドウの作成
   */
  Scene_LearnSkillList.prototype.createActorWindow = function () {
    const rect = this.actorWindowRect();
    this._actorWindow = new Window_LearnSkillActor(rect);
    this.addWindow(this._actorWindow);
  };

  /**
   * ●アクターウィンドウの表示領域
   */
  Scene_LearnSkillList.prototype.actorWindowRect = function () {
    const wx = 0;
    const wy = this.mainAreaTop();
    const ww = pActorWindowWidth;
    const wh = pActorWindowHeight ? pActorWindowHeight : this.mainAreaHeight();
    return new Rectangle(wx, wy, ww, wh);
  };

  /**
   * ●確認ウィンドウの作成
   */
  Scene_LearnSkillList.prototype.createConfirmWindow = function () {
    const rect = this.confirmWindowRect();
    this._confirmWindow = new Window_LearnSkillConfirm(rect);
    this._confirmWindow.setHandler("ok", this.confirmLearnOk.bind(this));
    this._confirmWindow.setHandler(
      "cancel",
      this.confirmLearnCancel.bind(this)
    );
    // addWindowだと下が見えなくなるのでaddChildで追加する。
    this.addChild(this._confirmWindow);

    this._confirmWindow.hide();
    this._confirmWindow.close();
  };

  /**
   * ●確認ウィンドウの表示領域
   */
  Scene_LearnSkillList.prototype.confirmWindowRect = function () {
    // ww,whは後で調整するため適当に画面全体を指定
    const ww = Graphics.boxWidth;
    const wh = Graphics.boxHeight;
    const wx = (Graphics.boxWidth - ww) / 2;
    const wy = (Graphics.boxHeight - wh) / 2;
    return new Rectangle(wx, wy, ww, wh);
  };

  /**
   * ●確認確定
   */
  Scene_LearnSkillList.prototype.confirmLearnOk = function () {
    // スキルを習得
    const dataSkill = this._confirmWindow.dataSkill();
    const item = this._confirmWindow.item();
    this.actor().learnSkill(dataSkill.id);

    // スキルポイントを減算
    if (item.SkillPoint) {
      this.actor().changeSkillPoint(eval(item.SkillPoint) * -1);
    }

    // 効果音を演奏
    if (pConfirmOkSe) {
      AudioManager.playSe({
        name: pConfirmOkSe,
        volume: 90,
        pitch: 100,
        pan: 0,
      });
    }

    // 確認ウィンドウを閉じる
    this._confirmWindow.close();
    // スキルリストに戻る
    this._skillListWindow.activate();
    // リフレッシュ
    this._skillListWindow.refresh();
    this._actorWindow.refresh();
  };

  /**
   * ●確認キャンセル
   */
  Scene_LearnSkillList.prototype.confirmLearnCancel = function () {
    // 確認ウィンドウを閉じる
    this._confirmWindow.close();
    // スキルリストに戻る
    this._skillListWindow.activate();
  };

  /**
   * ●処理開始
   */
  Scene_LearnSkillList.prototype.start = function () {
    Scene_MenuBase.prototype.start.call(this);
    Scene_Message.prototype.start.call(this);
    this.refreshActor();

    // スキルリストウィンドウを更新してフォーカス
    this._skillListWindow.refresh();
    this._skillListWindow.activate();
    this._skillListWindow.select(0);
    this._actorWindow.deactivate();

    // // 開始時コモンイベントがある場合は始動
    // if (pStartCommonEvent) {
    //     this._interpreter = new Game_Interpreter();
    //     $gameTemp.reserveCommonEvent(pStartCommonEvent);
    //     this._interpreter.setupReservedCommonEvent();
    // }
  };

  Scene_LearnSkillList.prototype.refreshActor = function () {
    const actor = this.actor();
    this._actorWindow.setActor(actor);
    this._skillListWindow.setActor(actor);
  };

  /**
   * ●地点の選択開始
   */
  Scene_LearnSkillList.prototype.onSkillListStart = function () {
    // 地点選択ウィンドウの表示＆フォーカス
    this._skillListWindow.show();
    this._skillListWindow.activate();
    this._skillListWindow.refresh();
  };

  /**
   * ●スキルリスト選択時
   */
  Scene_LearnSkillList.prototype.onSkillListOk = function () {
    const item = this._skillListWindow.item();

    // 確認ウィンドウにスキルデータを設定
    this._confirmWindow.setSkillData(item);
    // 確認ウィンドウを表示
    this._confirmWindow.show();
    this._confirmWindow.open();
    this._confirmWindow.activate();
    this._confirmWindow.select(0);
  };

  /**
   * ●スキルリストキャンセル
   */
  Scene_LearnSkillList.prototype.onSkillListCancel = function () {
    // 前シーンへ遷移
    this.popScene();
  };

  /**
   * ●アクター切替
   */
  Scene_LearnSkillList.prototype.onActorChange = function () {
    Scene_MenuBase.prototype.onActorChange.call(this);
    this.refreshActor();
    this._skillListWindow.activate();
  };

  //-----------------------------------------------------------------------------
  // Window_LearnSkillList
  //
  // 習得スキルウィンドウクラス

  function Window_LearnSkillList() {
    this.initialize(...arguments);
  }

  Window_LearnSkillList.prototype = Object.create(Window_Selectable.prototype);
  Window_LearnSkillList.prototype.constructor = Window_LearnSkillList;

  /**
   * ●初期化
   */
  Window_LearnSkillList.prototype.initialize = function (rect, windowParam) {
    this._windowParam = windowParam;
    Window_Selectable.prototype.initialize.call(this, rect);
  };

  /**
   * ●アクター情報の設定
   */
  Window_LearnSkillList.prototype.setActor = function (actor) {
    if (this._actor !== actor) {
      this._actor = actor;
      this.refresh();
    }
  };

  /**
   * ●列の余白
   */
  Window_LearnSkillList.prototype.colSpacing = function () {
    return 0;
  };

  /**
   * ●表示更新
   */
  Window_LearnSkillList.prototype.refresh = function () {
    this.contents.clear();

    this._data = [];

    // 条件を満たすスキルセットのみを取得
    const skillSetList = pSkillSetList.filter((skillSet) =>
      this.isMatchSkillSet(skillSet)
    );
    // さらにスキルセットの中で条件を満たすスキルのみを追加
    for (const skillSet of skillSetList) {
      const skillList = parseStruct1(skillSet.SkillList);
      for (const skillData of skillList) {
        const parseSkillData = JSON.parse(skillData);
        if (this.isDisplaySkillData(parseSkillData)) {
          this._data.push(parseSkillData);
        }
      }
    }

    // 習得スキルは下に表示する設定の場合
    if (pLearnedSkillDisplayStyle == "below") {
      this._data.sort((a, b) => {
        const skillIdA = Number(a.Skill);
        const skillIdB = Number(b.Skill);
        // 習得していないスキルを優先表示
        return (
          this._actor.isLearnedSkill(skillIdA) -
          this._actor.isLearnedSkill(skillIdB)
        );
      });
    }

    this.paint();
    this.updateHelp();
  };

  /**
   * ●スキルセットの条件を満たすかどうか？
   */
  Window_LearnSkillList.prototype.isMatchSkillSet = function (skillSet) {
    // eval参照用
    const a = this._actor;

    const switchNo = Number(skillSet.Switch);
    // スイッチを満たしていない場合は不可
    if (skillSet.Switch && !$gameSwitches.value(switchNo)) {
      return false;
      // 対象のアクターではない場合は不可
    } else if (skillSet.Actor && skillSet.Actor != this._actor.actorId()) {
      return false;
      // スクリプト条件を満たしていない場合は不可
    } else if (skillSet.Script && !eval(skillSet.Script)) {
      return false;
    }
    return true;
  };

  /**
   * ●スキルの表示条件を満たすかどうか？
   */
  Window_LearnSkillList.prototype.isDisplaySkillData = function (skillData) {
    const skillId = Number(skillData.Skill);

    // 習得スキルの表示方法
    const learnedSkillDisplayStyle = getLearnedSkillDisplayStyle(skillData);

    // 習得済スキルは表示しない設定の場合
    if (
      learnedSkillDisplayStyle == "hide" &&
      this._actor.isLearnedSkill(skillId)
    ) {
      return false;
      // 隠しスキルも表示する場合は表示
    } else if (pShowHiddenSkills) {
      return true;
    }

    // スキルを習得できるかどうか？
    return this.isMatchSkillData(skillData);
  };

  /**
   * ●スキルを習得条件を満たしているかどうか？
   * ※ポイントは除く
   */
  Window_LearnSkillList.prototype.isMatchSkillData = function (skillData) {
    // eval参照用
    const a = this._actor;

    const conditionSkillId = Number(skillData.ConditionSkill);
    const switchNo = Number(skillData.Switch);

    // スイッチを満たしていない場合は不可
    if (skillData.Switch && !$gameSwitches.value(switchNo)) {
      return false;
      // 条件スキルを満たしていない場合は不可
    } else if (
      skillData.ConditionSkill &&
      !this._actor.isLearnedSkill(conditionSkillId)
    ) {
      return false;
      // スクリプト条件を満たしていない場合は不可
    } else if (skillData.Script && !eval(skillData.Script)) {
      return false;
    }
    return true;
  };

  /**
   * ●習得スキルの表示方法
   */
  function getLearnedSkillDisplayStyle(skillData) {
    // 個別設定がある場合は優先
    if (skillData.LearnedSkillDisplayStyle) {
      return skillData.LearnedSkillDisplayStyle;
    }
    // それ以外は全体設定
    return pLearnedSkillDisplayStyle;
  }

  /**
   * ●選択中の項目を取得
   * ※dataSkillではなくプラグインパラメータのSkillData
   */
  Window_LearnSkillList.prototype.item = function () {
    return this.itemAt(this.index());
  };

  /**
   * ●選択中の項目を取得
   * ※dataSkill
   */
  Window_LearnSkillList.prototype.dataSkill = function () {
    return $dataSkills[this.item().Skill];
  };

  /**
   * ●指定した番号の項目を取得
   * ※dataSkillではなくプラグインパラメータのSkillData
   */
  Window_LearnSkillList.prototype.itemAt = function (index) {
    return this._data && index >= 0 ? this._data[index] : null;
  };

  /**
   * ●全項目を表示
   */
  Window_LearnSkillList.prototype.drawAllItems = function () {
    const topIndex = this.topIndex();
    for (let i = 0; i < this.maxVisibleItems(); i++) {
      const index = topIndex + i;
      if (index < this.maxItems()) {
        this.drawItemBackground(index);
        this.drawItem(index);
      }
    }
  };

  /**
   * ●項目数を定義
   */
  Window_LearnSkillList.prototype.maxItems = function () {
    return this._data ? this._data.length : 1;
  };

  /**
   * ●項目を描画
   */
  Window_LearnSkillList.prototype.drawItem = function (index) {
    const learnSkillData = this.itemAt(index);
    if (learnSkillData) {
      const costWidth = this.costWidth();
      const rect = this.itemLineRect(index);
      this.changePaintOpacity(this.isEnabled(learnSkillData));
      this.drawItemName(learnSkillData, rect.x, rect.y, rect.width - costWidth);
      this.drawSkillCost(learnSkillData, rect.x, rect.y, rect.width);
      this.changePaintOpacity(1);
    }
  };

  /**
   * ●現在の項目が有効かどうか？
   */
  Window_LearnSkillList.prototype.isCurrentItemEnabled = function () {
    return this.isEnabled(this.item());
  };

  /**
   * ●スキルを習得できるかどうか？
   */
  Window_LearnSkillList.prototype.isEnabled = function (item) {
    // 覚えられるスキルが一つもない場合
    if (!item) {
      return false;
    }
    // 習得済の場合
    const skillId = eval(item.Skill);
    if (this._actor.isLearnedSkill(skillId)) {
      return false;
    }
    // ＳＰが足りない
    const skillPoint = eval(item.SkillPoint);
    if (this._actor.currentSkillPoint() < skillPoint) {
      return false;
    }
    // 条件を満たしていない
    if (!this.isMatchSkillData(item)) {
      return false;
    }

    return true;
  };

  /**
   * ●項目名を表示
   */
  Window_LearnSkillList.prototype.drawItemName = function (
    learnSkillData,
    x,
    y,
    width
  ) {
    const skillId = Number(learnSkillData.Skill);
    const dataSkill = $dataSkills[skillId];
    const iconY = y + (this.lineHeight() - ImageManager.iconHeight) / 2;
    const textMargin = ImageManager.iconWidth + 4;
    const itemWidth = Math.max(0, width - textMargin);
    this.resetTextColor();

    let skillName = dataSkill.name;

    // マスク表示を行う場合は隠す
    if (pHiddenSkillMask && !this.isMatchSkillData(learnSkillData)) {
      skillName = pHiddenSkillMask;
    }

    // 表示名の指定がある場合
    if (learnSkillData.DisplayName) {
      // %1=スキル名, %2=アイコン
      const displayName = learnSkillData.DisplayName.format(
        skillName,
        "\\i[" + dataSkill.iconIndex + "]"
      );
      this.drawTextEx(displayName, x, y, itemWidth);

      // 通常表示
    } else {
      // アイコンを使用
      if (pUseIcon) {
        this.drawIcon(dataSkill.iconIndex, x, iconY);
        x += textMargin;
      }
      this.drawText(skillName, x, y, itemWidth);
    }
  };

  /**
   * ●消費ＳＰの幅
   */
  Window_LearnSkillList.prototype.costWidth = function () {
    return this.textWidth("0000");
  };

  /**
   * ●消費ＳＰの描画
   */
  Window_LearnSkillList.prototype.drawSkillCost = function (
    learnSkillData,
    x,
    y,
    width
  ) {
    const skillId = Number(learnSkillData.Skill);

    // 習得済スキルの場合
    if (this._actor.isLearnedSkill(skillId)) {
      if (pLearnedText) {
        this.changePaintOpacity(1);
        this.changeTextColor(ColorManager.textColor(pLearnedTextColor));
        this.drawText(pLearnedText, x, y, width, "right");
        this.resetTextColor();
      }
      return;
    }

    // 文字色変更
    this.changeTextColor(ColorManager.textColor(pSkillPointColor));

    // 条件を満たしていないスキルの場合は記号を表示
    if (!this.isMatchSkillData(learnSkillData)) {
      this.drawText(
        pHiddenSymbol,
        x,
        y,
        width - this.costWidth() - this.itemPadding(),
        "right"
      );
    }

    // スキルポイントを表示
    if (learnSkillData.SkillPoint != null) {
      this.drawText(learnSkillData.SkillPoint, x, y, width, "right");
    }
  };

  /**
   * ●ヘルプを表示
   */
  Window_LearnSkillList.prototype.updateHelp = function () {
    const learnSkillData = this.item();
    if (learnSkillData) {
      // ヘルプを隠す場合は追記のみ表示
      if (pHiddenHelp && !this.isMatchSkillData(learnSkillData)) {
        this._helpWindow.setText(learnSkillData.HelpPostscript);
        return;
      }

      const dataSkill = $dataSkills[learnSkillData.Skill];
      this.setHelpWindowItem(dataSkill);

      // 追記があれば設定
      if (learnSkillData.HelpPostscript) {
        const newText =
          this._helpWindow._text + "\n" + learnSkillData.HelpPostscript;
        this._helpWindow.setText(newText);
      }
    }
  };

  /**
   * ●文字列描画処理
   * ※Window_Base.prototype.drawTextExとほぼ同じだがフォントリセットしない。
   */
  Window_LearnSkillList.prototype.drawTextEx = function (text, x, y, width) {
    const textState = this.createTextState(text, x, y, width);
    this.processAllText(textState);
    return textState.outputWidth;
  };

  //-----------------------------------------------------------------------------
  // Window_LearnSkillActor
  //
  // 習得スキル用アクタークラス

  function Window_LearnSkillActor() {
    this.initialize(...arguments);
  }

  Window_LearnSkillActor.prototype = Object.create(Window_StatusBase.prototype);
  Window_LearnSkillActor.prototype.constructor = Window_LearnSkillActor;

  Window_LearnSkillActor.prototype.initialize = function (rect) {
    Window_Selectable.prototype.initialize.call(this, rect);
  };

  Window_LearnSkillActor.prototype.setActor = function (actor) {
    if (this._actor !== actor) {
      this._actor = actor;
      this.refresh();
    }
  };

  Window_LearnSkillActor.prototype.refresh = function () {
    this.contents.clear();
    if (this._actor) {
      const nameRect = this.itemLineRect(0);
      this.drawActorName(
        this._actor,
        nameRect.x,
        this.itemPadding(),
        nameRect.width
      );
      this.drawActorFace(
        this._actor,
        nameRect.x,
        this.itemPadding() + nameRect.height + this.itemPadding()
      );
      this.drawSkillPoint();
    }
  };

  /**
   * ●スキルポイントの描画
   */
  Window_LearnSkillActor.prototype.drawSkillPoint = function () {
    const x = this.itemPadding();
    const y = this.paramY(0);

    this.changeTextColor(ColorManager.systemColor());
    this.drawText(pSkillPointName, x, y);
    this.resetTextColor();

    const skillPoint = this._actor.currentSkillPoint();
    const width = this.innerWidth - this.itemPadding() * 2;
    this.drawText(skillPoint, x, y, width, "right");
  };

  /**
   * ●スキルポイントのＹ座標
   */
  Window_LearnSkillActor.prototype.paramY = function (index) {
    const faceHeight = ImageManager.faceHeight;
    return (
      faceHeight +
      Math.floor(this.lineHeight() * (index + 1.5)) +
      this.itemPadding() * 2
    );
  };

  //-----------------------------------------------------------------------------
  // Window_LearnSkillConfirm
  //
  // 習得確認用のウィンドウ

  function Window_LearnSkillConfirm() {
    this.initialize(...arguments);
  }

  Window_LearnSkillConfirm.prototype = Object.create(Window_Command.prototype);
  Window_LearnSkillConfirm.prototype.constructor = Window_LearnSkillConfirm;

  Window_LearnSkillConfirm.prototype.initialize = function (rect) {
    // Window_Selectable.prototype.initialize.call(this, rect);
    Window_Command.prototype.initialize.call(this, rect);
  };

  /**
   * ●スキルデータの設定
   * ※dataSkillではなくプラグインパラメータのSkillData
   */
  Window_LearnSkillConfirm.prototype.setSkillData = function (skillData) {
    this._skillData = skillData;
    this.refresh();
  };

  /**
   * ●選択中の項目を取得
   * ※dataSkillではなくプラグインパラメータのSkillData
   */
  Window_LearnSkillConfirm.prototype.item = function () {
    return this._skillData;
  };

  /**
   * ●選択中の項目を取得
   * ※dataSkill
   */
  Window_LearnSkillConfirm.prototype.dataSkill = function () {
    if (this._skillData) {
      return $dataSkills[this._skillData.Skill];
    }
    return null;
  };

  Window_LearnSkillConfirm.prototype.makeCommandList = function () {
    this.addCommand(pConfirmButtonOk, "ok");
    this.addCommand(pConfirmButtonCancel, "cancel");
  };

  Window_LearnSkillConfirm.prototype.drawAllItems = function () {
    const paramSkill = this._skillData;
    const dataSkill = this.dataSkill();
    if (!dataSkill) {
      return;
    }

    // 文字列の最大長を求める。
    let maxWidth = 0;
    // 行数カウント用
    let lineCount = 0;

    let skillPoint = 0;
    if (paramSkill.SkillPoint) {
      skillPoint = eval(paramSkill.SkillPoint);
    }

    for (const line of pConfirmMessage.split("\n")) {
      // %1をスキル名に%2をアイコンに%3をスキルポイントに変換
      const message = line.format(
        dataSkill.name,
        "\\i[" + dataSkill.iconIndex + "]",
        skillPoint
      );
      // 文字列の最大長を保持しておく。
      const newWidth = this.textSizeEx(message).width + this.itemPadding() * 4;
      maxWidth = Math.max(maxWidth, newWidth);

      // 一行ずつ描画
      this.drawTextEx(
        message,
        this.itemPadding(),
        this.itemPadding() + lineCount * this.lineHeight()
      );
      lineCount++;
    }
    lineCount++;

    // ウィンドウの幅と座標を文字列に合わせて調整
    this.width = maxWidth;
    this.height = this.lineHeight() * lineCount + this.fittingHeight(2);
    this.x = (Graphics.boxWidth - this.width) / 2;
    this.y = (Graphics.boxHeight - this.height) / 2;

    const topIndex = this.topIndex();
    for (let i = 0; i < this.maxVisibleItems(); i++) {
      const index = topIndex + i;
      if (index < this.maxItems()) {
        this.drawItemBackground(index);
        this.drawItem(index);
      }
    }
  };

  Window_LearnSkillConfirm.prototype.drawItem = function (index) {
    const rect = this.itemLineRect(index);
    const align = this.itemTextAlign();
    this.resetTextColor();
    this.changePaintOpacity(this.isCommandEnabled(index));
    this.drawText(this.commandName(index), rect.x, rect.y, rect.width, align);
  };

  const _Window_LearnSkillConfirm_itemRect =
    Window_LearnSkillConfirm.prototype.itemRect;
  Window_LearnSkillConfirm.prototype.itemRect = function (index) {
    const rect = _Window_LearnSkillConfirm_itemRect.apply(this, arguments);

    const lineCount = pConfirmMessage.split("\n").length;
    rect.y += lineCount * this.lineHeight() + this.itemPadding() * 4;

    return rect;
  };

  /**
   * ●文字列描画処理
   * ※Window_Base.prototype.drawTextExとほぼ同じだがフォントリセットしない。
   */
  Window_LearnSkillConfirm.prototype.drawTextEx = function (text, x, y, width) {
    const textState = this.createTextState(text, x, y, width);
    this.processAllText(textState);
    return textState.outputWidth;
  };

  //-----------------------------------------------------------------------------
  // Game_Actor
  //-----------------------------------------------------------------------------

  /**
   * ●変数初期化
   */
  const _Game_Actor_initMembers = Game_Actor.prototype.initMembers;
  Game_Actor.prototype.initMembers = function () {
    _Game_Actor_initMembers.apply(this, arguments);
    this.initSkillPoint();
  };

  /**
   * 【独自】スキルポイントの初期化
   * ※プラグインの途中適用を考慮した初期化処理
   */
  Game_Actor.prototype.initSkillPoint = function () {
    // パーティ共有の場合は不要なので無視
    if (pSkillPointType == "party") {
      return;
    }

    // アクター毎の場合
    // 値が未設定の場合は0を設定
    if (this[SKILL_POINT_KEY] == null) {
      this[SKILL_POINT_KEY] = 0;
    }
  };

  /**
   * 【独自】スキルポイントの取得
   */
  Game_Actor.prototype.currentSkillPoint = function () {
    this.initSkillPoint();

    // パーティ共有の場合
    if (pSkillPointType == "party") {
      return $gameVariables.value(eval(pSkillPointVariable));
    }

    return this[SKILL_POINT_KEY];
  };

  /**
   * 【独自】スキルポイントの変更
   */
  Game_Actor.prototype.changeSkillPoint = function (changePoint) {
    this.initSkillPoint();

    // 現在のスキルポイント
    const currentSp = this.currentSkillPoint();
    let newValue = currentSp + changePoint;
    if (newValue > pMaxSkillPoint) {
      newValue = pMaxSkillPoint;
      // マイナスの場合は0をセット
    } else if (newValue < 0) {
      newValue = 0;
    }

    // パーティ共有の場合
    if (pSkillPointType == "party") {
      const variableNo = eval(pSkillPointVariable);
      // 変数の値を加算
      $gameVariables.setValue(variableNo, newValue);
      // アクター毎の場合
    } else {
      this[SKILL_POINT_KEY] = newValue;
    }
  };

  /**
   * 【独自】スキルリセット
   */
  Game_Actor.prototype.resetLearnSkill = function () {
    const skillList = this.resetLearnSkillList();

    // スキル毎にループ
    for (const skillData of skillList) {
      const skillId = Number(skillData.Skill);
      // スキルを習得済だった場合
      if (this.isLearnedSkill(skillId)) {
        // スキルを忘れる
        this.forgetSkill(skillId);
        //----------------------------------
        // ポイント返却
        //----------------------------------
        let skillPoint = 0;
        if (skillData.SkillPoint) {
          skillPoint = eval(skillData.SkillPoint);
        }
        this.changeSkillPoint(skillPoint);
      }
    }
  };

  /**
   * 【独自】スキルリセット用のスキルリストを取得
   */
  Game_Actor.prototype.resetLearnSkillList = function () {
    const restSkillList = [];

    // 対象アクターのスキルセットのみを取得
    const skillSetList = pSkillSetList.filter(
      (skillSet) => !skillSet.Actor || skillSet.Actor == this.actorId()
    );
    // さらにスキルセットの中で条件を満たすスキルのみを追加
    for (const skillSet of skillSetList) {
      const skillList = parseStruct1(skillSet.SkillList);
      for (const skillData of skillList) {
        const parseSkillData = JSON.parse(skillData);
        restSkillList.push(parseSkillData);
      }
    }

    return restSkillList;
  };

  //-----------------------------------------------------------------------------
  // メニューコマンド（Window_MenuCommand, Scene_Menu）
  //-----------------------------------------------------------------------------

  if (pShowMenuCommandPosition != null) {
    /**
     * ●メニューコマンド追加（独自コマンド）
     */
    const _Window_MenuCommand_addOriginalCommands =
      Window_MenuCommand.prototype.addOriginalCommands;
    Window_MenuCommand.prototype.addOriginalCommands = function () {
      // 元処理実行
      _Window_MenuCommand_addOriginalCommands.call(this);

      // 非表示スイッチが存在かつオフの場合は無効
      if (pMenuCommandSwitch && !$gameSwitches.value(pMenuCommandSwitch)) {
        // 文字列の指定がある場合は表示
        if (pMaskString) {
          this._list.splice(pShowMenuCommandPosition, 0, {
            name: pMaskString,
            symbol: SYMBOL_SKILL_SYSTEM,
            enabled: false,
            ext: null,
          });
        }
        return;
      }

      let isEnabled = true;
      // 禁止スイッチが存在かつオンの場合は禁止
      if (pDisableSwitch && $gameSwitches.value(pDisableSwitch)) {
        isEnabled = false;
      }

      // 指定位置にスキル習得コマンドを挿入
      // ※標準ではステータスの下
      this._list.splice(pShowMenuCommandPosition, 0, {
        name: pCommandName,
        symbol: SYMBOL_SKILL_SYSTEM,
        enabled: isEnabled,
        ext: null,
      });
    };

    /**
     * ●メニューコマンド呼び出し先の設定
     */
    const _Scene_Menu_createCommandWindow =
      Scene_Menu.prototype.createCommandWindow;
    Scene_Menu.prototype.createCommandWindow = function () {
      _Scene_Menu_createCommandWindow.call(this);

      // コマンド追加
      this._commandWindow.setHandler(
        SYMBOL_SKILL_SYSTEM,
        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() == SYMBOL_SKILL_SYSTEM) {
        SceneManager.push(Scene_LearnSkillList);
      }
    };
  }

  //-----------------------------------------------------------------------------
  // スキルポイントの取得
  // （BattleManager, Game_System, Game_Troop, Game_Enemy, Game_Actor）
  //-----------------------------------------------------------------------------

  /**
   * ●報酬の作成
   */
  const _BattleManager_makeRewards = BattleManager.makeRewards;
  BattleManager.makeRewards = function () {
    _BattleManager_makeRewards.apply(this, arguments);

    // 報酬にＳＰを追加
    this._rewards["skillPoint"] = $gameTroop.skillPointTotal();
  };

  /**
   * ●報酬の獲得
   */
  const _BattleManager_gainRewards = BattleManager.gainRewards;
  BattleManager.gainRewards = function () {
    _BattleManager_gainRewards.apply(this, arguments);

    // ＳＰが有効なら加算
    if ($gameSystem.isSkiiPointEnabled()) {
      this.gainSkillPoint();
    }
  };

  /**
   * 【独自】スキルポイントの獲得
   */
  BattleManager.gainSkillPoint = function () {
    const skillPoint = this._rewards["skillPoint"];

    // パーティ共有の場合
    if (pSkillPointType == "party") {
      // 現在のスキルポイントを取得
      const variableNo = eval(pSkillPointVariable);
      const currentSkillPoint = $gameVariables.value(variableNo);
      // 変数の値を加算
      const newValue = currentSkillPoint + skillPoint;
      $gameVariables.setValue(variableNo, newValue);
      return;
    }

    // 通常時はアクター毎に加算
    for (const actor of $gameParty.allMembers()) {
      actor.gainSkillPoint(skillPoint);
    }
  };

  /**
   * ●経験値の表示
   * ※BattleManager.displayRewardsを上書きしたくないので
   * 　こちらの末尾に追加
   */
  const _BattleManager_displayExp = BattleManager.displayExp;
  BattleManager.displayExp = function () {
    _BattleManager_displayExp.apply(this, arguments);

    // 獲得スキルポイントの表示
    const skillPoint = this._rewards["skillPoint"];
    if (skillPoint > 0 && pSkillPointMessage) {
      const text = pSkillPointMessage.format(skillPoint, pSkillPointName);
      $gameMessage.add("\\." + text);
    }
  };

  /**
   * ●スキルポイントが有効かどうか？
   */
  Game_System.prototype.isSkiiPointEnabled = function () {
    // 有効スイッチがオフの場合は変更禁止
    if (pSkillPointSwitch && !$gameSwitches.value(pSkillPointSwitch)) {
      return false;
    }
    return true;
  };

  /**
   * 【独自】スキルポイントの合計
   */
  Game_Troop.prototype.skillPointTotal = function () {
    // ＳＰが有効でない場合は0
    if (!$gameSystem.isSkiiPointEnabled()) {
      return 0;
    }

    return this.deadMembers().reduce((r, enemy) => r + enemy.skillPoint(), 0);
  };

  /**
   * 【独自】スキルポイントの取得
   */
  Game_Enemy.prototype.skillPoint = function () {
    const a = this; // eval参照用

    let skillPoint = 0;

    // 設定値が存在する場合
    const metaSkillPoint = this.enemy().meta.SkillPoint;

    if (metaSkillPoint != undefined) {
      skillPoint = eval(metaSkillPoint);

      // 既定値が存在する場合
    } else if (pDefaultEnemySkillPoint != undefined) {
      skillPoint = eval(pDefaultEnemySkillPoint);
    }

    // rateを乗算する。
    const rate = this.enemy().meta.SkillPointRate;
    if (rate != undefined) {
      skillPoint = Math.round((skillPoint * rate) / 100);
    }
    return skillPoint;
  };

  /**
   * 【独自】スキルポイントの獲得（アクター）
   */
  Game_Actor.prototype.gainSkillPoint = function (skillPoint) {
    this.changeSkillPoint(Math.round(skillPoint * this.finalSkillPointRate()));
  };

  /**
   * 【独自】スキルポイントの獲得率
   */
  Game_Actor.prototype.finalSkillPointRate = function () {
    return this.isBattleMember() ? 1 : this.benchMembersSkillPointRate();
  };

  /**
   * 【独自】控えメンバーのスキルポイント比率
   */
  Game_Actor.prototype.benchMembersSkillPointRate = function () {
    if (pBenchSkillPointRate != undefined) {
      const a = this; // eval計算用
      return eval(pBenchSkillPointRate);
    }
    return $dataSystem.optExtraExp ? 1 : 0;
  };

  //-----------------------------------------------------------------------------
  // スキルポイントの取得（レベルアップ時）
  // （Game_Actor）
  //-----------------------------------------------------------------------------

  // レベルアップ時の増加ＳＰを保持する。
  // ※複数レベルアップも想定
  let mLevelSpTotal = 0;

  /**
   * ●経験値の変更
   * ※レベルアップ処理の前に必ず通る想定
   */
  const _Game_Actor_changeExp = Game_Actor.prototype.changeExp;
  Game_Actor.prototype.changeExp = function (exp, show) {
    mLevelSpTotal = 0;

    _Game_Actor_changeExp.apply(this, arguments);
  };

  /**
   * ●レベルアップ
   */
  const _Game_Actor_levelUp = Game_Actor.prototype.levelUp;
  Game_Actor.prototype.levelUp = function () {
    _Game_Actor_levelUp.apply(this, arguments);

    if (pLevelUpSkillPoint) {
      const a = this; // eval参照用
      // ＳＰを獲得
      const levelUpSkillPoint = eval(pLevelUpSkillPoint);
      this.changeSkillPoint(levelUpSkillPoint);
      // 表示用に保持
      mLevelSpTotal += levelUpSkillPoint;
    }
  };

  /**
   * ●レベルダウン
   */
  const _Game_Actor_levelDown = Game_Actor.prototype.levelDown;
  Game_Actor.prototype.levelDown = function () {
    if (pLevelUpSkillPoint) {
      const a = this; // eval参照用
      // ＳＰを獲得
      const levelUpSkillPoint = eval(pLevelUpSkillPoint);
      this.changeSkillPoint(levelUpSkillPoint * -1);
      // 表示用に保持
      mLevelSpTotal -= levelUpSkillPoint;
    }

    _Game_Actor_levelDown.apply(this, arguments);
  };

  /**
   * ●レベルアップの表示
   */
  const _Game_Actor_displayLevelUp = Game_Actor.prototype.displayLevelUp;
  Game_Actor.prototype.displayLevelUp = function (newSkills) {
    _Game_Actor_displayLevelUp.apply(this, arguments);

    if (mLevelSpTotal) {
      $gameMessage.add(
        pSkillPointMessage.format(mLevelSpTotal, pSkillPointName)
      );
    }

    // 終了したので初期化
    mLevelSpTotal = 0;
  };

  //-----------------------------------------------------------------------------
  // スキルポイントの取得（アイテム）
  // （Game_Action）
  //-----------------------------------------------------------------------------

  /**
   * ●効果適用
   */
  const _Game_Action_apply = Game_Action.prototype.apply;
  Game_Action.prototype.apply = function (target) {
    _Game_Action_apply.apply(this, arguments);

    // スキルポイントを加算
    const addSkillPoint = this.item().meta.AddSkillPoint;
    if (addSkillPoint) {
      const result = target.result();
      if (result.isHit()) {
        target.changeSkillPoint(eval(addSkillPoint));
        this.makeSuccess(target);
      }
    }
  };

  /**
   * ●効果適用判定
   */
  const _Game_Action_hasItemAnyValidEffects =
    Game_Action.prototype.hasItemAnyValidEffects;
  Game_Action.prototype.hasItemAnyValidEffects = function (target) {
    const ret = _Game_Action_hasItemAnyValidEffects.apply(this, arguments);
    // 効果が存在する場合は判定を有効にする。
    return ret || this.item().meta.AddSkillPoint;
  };
})();


code:
//=============================================================================
// NumbStates.js (Ver1.2.1)
//=============================================================================
// 2015.Oct.30 Ver1.0.0  First Release
// 2019.Jul.03 Ver1.1.0  Solve the conflict with BeforeCommon.js
// 2019.Dec.08 Ver1.2.0  (closed release) Update to run under also MZ
// 2020.Feb.20 Ver1.2.1  displaying message become selectable

/*:
 * @target MV MZ
 * @plugindesc Make the state that battler become numb.
 * @author Sasuke KANNAZUKI
 *
 * @param dispMsgType
 * @text Display Message Type
 * @desc Where to set message displays when numb occur
 * @type select
 * @option This plugin's option
 * @value plugin
 * @option State Messages in Data Base
 * @value state
 * @default plugin
 *
 * @param NumbMsg
 * @text Numb Message
 * @desc Text to display when one cannot move by numb.
 * %1 is replaced to battler's name, %2 is state's name.
 * @type string
 * @default %1 cannot move by the numb!
 *
 * @help This plugin does not provide plugin commands.
 * This plugin runs under RPG Maker MV and MZ.
 *
 * This plugin enables to make the state numb (different from paralysis).
 *
 * [Summary]
 * The numb is the state that sometimes the battler cannot move in spite of
 * the command is inputtable.
 *
 * [State Note]
 * To invoke this state, write down the state's note as follows.
 *   <numb_rate:35> # cannot execute action by 35%
 *
 * [About 'Display Message Type' Option]
 * The message display when numb occur is selectable from followings:
 * - When you select 'This plugin's option',
 *  it will display this plugin's 'Numb Message' option.
 * - When you select 'State Messages in Data Base',
 *  it will display the state's message "If the state persists".
 *  If you select this, when the battler avoid to occur numb,
 *  it will not display the message.
 *
 * When you make plural states that numb occur,
 * latter setting may be useful.
 *
 * [Note]
 * It's preferred that the numb state's restriction is None.
 *
 * [License]
 * this plugin is released under MIT license.
 * http://opensource.org/licenses/mit-license.php
 */

/*:ja
 * @target MV MZ
 * @plugindesc 一定確率で行動できないステート(Ver1.2)
 * @author 神無月サスケ
 *
 * @param dispMsgType
 * @text 発動時メッセージタイプ
 * @desc 動けない時に表示するメッセージの設定箇所
 * @type select
 * @option パラメータで直接設定
 * @value plugin
 * @option データベースのステート
 * @value state
 * @default plugin
 *
 * @param NumbMsg
 * @parent dispMsgType
 * @text 発動時表示文
 * @desc 身体が痺れて動けない場合に表示する文章。
 * %1がバトラー名に置き換えられます
 * @type string
 * @default %1は身体がしびれて動けない！
 *
 * @help このプラグインにプラグインコマンドはありません。
 * このプラグインはRPGツクールMVおよびMZに対応しています。
 *
 * 痺れ(numb)は、入力は常に受け付けるものの特定の確率で動けなくなる状態で
 * ツクール標準の眠り/麻痺とは異なります。
 *
 * ■書式
 * 「ステート」のメモに以下のように書いてください。
 *   <numb_rate:35>
 *  この場合、このステートになったら 35% の確率で行動できなくなります。
 *
 * ■オプション「発動時メッセージタイプ」について：
 * この状態が発動し、動けなくなった際に表示する文章は、
 * オプションの「発動時メッセージタイプ」で指定します。
 * ・「パラメータで直接設定」を選ぶと、
 * このプラグインで設定した「発動時表示文」が表示されます。
 * ・「データベースのステート」を選ぶと
 * 「この状態が継続しているとき」のメッセージが表示されます。
 * こちらを選ぶと、通常に行動できた時は、
 * このメッセージは表示されません。
 *
 * この状態が発動するステートを複数作りたい場合は、
 * 後者が便利です。
 *
 * ■注意
 * ステートの「行動制約」は「なし（＝入力可）」にするのが望ましいです。
 *
 * ■ライセンス表記
 * このプラグインは MIT ライセンスで配布されます。
 * ご自由にお使いください。
 * http://opensource.org/licenses/mit-license.php
 */

(function () {
  //
  // process parameters
  //
  var parameters = PluginManager.parameters("NumbState");
  var dispMsgType = parameters["dispMsgType"] || "plugin";
  var NumbText = parameters["NumbMsg"] || "%1 cannot move by the numb!";

  //
  // select the message type and display occasion
  //
  var _Game_BattlerBase_mostImportantStateText =
    Game_BattlerBase.prototype.mostImportantStateText;
  Game_BattlerBase.prototype.mostImportantStateText = function () {
    var _stateTmp;
    if (dispMsgType === "state") {
      _statesTmp = this._states.clone();
      this._states = this._states.filter(function (stateId) {
        return !$dataStates[stateId].meta.numb_rate;
      });
    }
    var text = _Game_BattlerBase_mostImportantStateText.call(this);
    if (dispMsgType === "state") {
      this._states = _statesTmp;
    }
    return text;
  };

  //
  // evaluate and execute numb
  //
  Game_BattlerBase.prototype.numb_occur = function () {
    for (var id = 0; id < this._states.length; id++) {
      var stateId = this._states[id];
      var result = $dataStates[stateId].meta.numb_rate;
      if (result) {
        if (Math.randomInt(100) < Number(result)) {
          return stateId;
        }
      }
    }
    return 0;
  };

  var _BattleManager_processTurn = BattleManager.processTurn;
  BattleManager.processTurn = function () {
    var subject = this._subject;
    var action = subject.currentAction();
    // from BeforeCommon.js
    if (this._execBeforeCommon) {
      _BattleManager_processTurn.call(this);
      return;
    }
    var stateId;
    if (action && (stateId = subject.numb_occur())) {
      subject.clearActions();
      this._logWindow.displayNumbOccur(subject, stateId);
    }
    _BattleManager_processTurn.call(this);
  };

  Window_BattleLog.prototype.displayNumbOccur = function (subject, stateId) {
    var text = "";
    var state = $dataStates[stateId];
    switch (dispMsgType) {
      case "plugin":
        text = NumbText;
        break;
      case "state":
        text = state.message3;
        break;
    }
    this.push("addText", text.format(subject.name(), state.name));
    this.push("clear");
  };
})();

repo_name: dazed/translations

license: unknown


code:
//
//  パッシブスキル ver1.063
//
// ------------------------------------------------------
// Copyright (c) 2016 Yana
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
// ------------------------------------------------------
//
// author Yana
//

var Imported = Imported || {};
Imported["yPassiveSkill"] = 1.063;

/*:
 * @target MZ MV
 * @url https://raw.githubusercontent.com/munokura/Yana-MV-plugins/master/Item_Skill/PassiveSkill.js
 * @plugindesc ver1.063/スキルに特徴を設定できるようにします。
 * @author Yana
 *
 * @param Passive Skill Type ID
 * @desc パッシブスキルとして扱うスキルタイプID。
 * ここで設定されたIDのスキルタイプは、戦闘時に表示されません。
 * @default 3
 *
 * @param Add Multi Order
 * @desc パラメータの加算と乗算の順番。
 * trueだと加算→乗算、falseだと乗算→加算になります。
 * @default true
 *
 * @help
 * ------------------------------------------------------
 * 設定方法
 * ------------------------------------------------------
 * ・攻撃力や最大HP等のパラメータが1つのパッシブスキルの設定
 * <パッシブスキル:xxx+y>
 * <パッシブスキル:xxx-y>
 * <パッシブスキル:xxx+y%>
 * <パッシブスキル:xxx-y%>
 * <パッシブスキル:xxxy>
 * xxxのステータスをyポイント(%)増加(減少)させます。
 * ※最大HP、最大MP、攻撃力、防御力、魔法力、魔法防御、敏捷性、運の
 * 通常能力値のいずれかの場合、
 * %が付いていない時はその数値通りの値が適用されます。
 * %が付いている時は、その数値に100を加算し、
 * 算出した数値を通常の特徴で設定した時と同じように適用します。
 *
 * ※命中率、回避率、会心率、会心回避、魔法回避、魔法反射、反撃率、HP再生率、
 * MP再生率、TP再生率の等の追加能力値のいずれかの場合、
 * %が付いている時と%がついてない時の動作は同じになります。
 *
 * ※狙われ率、防御効果率、回復効果率、薬の知識、MP消費率、TPチャージ率、
 * 物理ダメージ率、魔法ダメージ率、床ダメージ率、経験値獲得率等の
 * 特殊能力地のいずれかの場合、
 * %が付いていない時はその数値通りの値が適用されます。
 * %が付いている時は、その数値に100を加算し、算出した数値を
 * 通常の特徴で設定した時と同じように適用します。
 *
 * ※ステート無効化、攻撃時属性、攻撃速度補正、攻撃追加回数、
 * スキルタイプ追加、スキルタイプ封印、スキル追加、スキル封印、
 * 武器タイプ装備、防具タイプ装備、装備固定、装備封印、行動回数追加
 * のいずれかの場合も、これで設定します。
 * これらは%が付いていても付いていなくても同じです。
 *
 * 例：
 * <パッシブスキル:最大HP+50>
 * 最大HPが50ポイント増加します。
 *
 * <パッシブスキル:攻撃力+20%>
 * 特徴、攻撃力120%と同じ意味です。
 *
 * <パッシブスキル:命中率+20%>
 * <パッシブスキル:命中率+20>
 * 特徴、命中率+20%と同じ意味です。
 *
 * <パッシブスキル:狙われ率+30>
 * 狙われ率が30%増加します。
 *
 * <パッシブスキル:狙われ率+30%>
 * 特徴、狙われ率130%と同じ意味です。
 *
 * <パッシブスキル:ステート無効化5>
 * 特徴、ステート無効化5番のステートと同じ意味です。
 *
 * <パッシブスキル:行動回数追加+20%>
 * 特徴、行動回数追加20%と同じ意味です。
 *
 * ・属性有効度やステート有効度などのパラメータが2つのパッシブスキルの設定
 * <パッシブスキル:xxxy+z>
 * <パッシブスキル:xxxy-z>
 * <パッシブスキル:xxxy+z%>
 * <パッシブスキル:xxxy-z%>
 * xxxのy番のレートをz(%)増加(減少)します。
 * ※属性有効度、弱体有効度、ステート有効度のいずれかの場合、
 * %が付いていない時は、その数値の値を直接加算(減算)します。
 * %が付いている時は、その数値に100を加算し、
 * 算出した数値を通常の特徴で設定した時と同じように適用します。
 *
 * ※攻撃時ステートの場合、%が付いていても付いていなくても同じです。
 *
 * 例:
 * <パッシブスキル:属性有効度4-30%>
 * 特徴、属性有効度4番の属性70%と同じ意味です。
 *
 * <パッシブスキル:属性有効度4-30>
 * 4番の属性の属性有効度を30%減少させます。
 *
 * ・二刀流や自動戦闘など、パラメータを持たないパッシブスキルの設定
 * <パッシブスキル:xxx>
 * xxxの特徴を付与します。
 *
 * 例:
 * <パッシブスキル:二刀流>
 * 特徴、スロットタイプ二刀流と同じ意味です。
 *
 * <パッシブスキル:自動戦闘>
 * 特徴、特殊フラグ自動戦闘と同じ意味です。
 *
 * ------------------------------------------------------
 * 仕様と解説
 * ------------------------------------------------------
 * ・特徴で追加されたスキルはパッシブスキルとして機能しません。
 * ・AddMultiOrderがtrueだと、加算の計算→乗算の計算となるので、
 * 攻撃力100で攻撃力+50と攻撃力+50%の特徴を持っていた場合、
 * (100+50)x1.5=225となります。
 * falseの場合は、乗算→加算と計算されるので、
 * 100x1.5+50=200となります。
 * ・対応するスキルタイプが封印されたり、パッシブスキル自体が封印された場合、
 * そのスキルは効果がなくなります。
 * ・必要武器タイプが設定されていた場合、それらの条件を満たしていないと
 * そのスキルは効果がなくなります。
 * ・PassiveSkillTypeIDで指定したスキルタイプでないと
 * パッシブスキルとして機能しない、という事はありません。
 * ・PassiveSkillTypeIDはあくまで、
 * 戦闘中に表示しないスキルタイプのIDというのみです。
 * ------------------------------------------------------
 *  プラグインコマンドはありません。
 * ------------------------------------------------------
 * ------------------------------------------------------
 * 利用規約
 * ------------------------------------------------------
 * 当プラグインはMITライセンスで公開されています。
 * 使用に制限はありません。商用、アダルト、いずれにも使用できます。
 * 二次配布も制限はしませんが、サポートは行いません。
 * 著作表示は任意です。行わなくても利用できます。
 * 要するに、特に規約はありません。
 * バグ報告や使用方法等のお問合せはネ実ツクールスレ、
 * または、Twitterにお願いします。
 * https://twitter.com/yanatsuki_
 * 素材利用は自己責任でお願いします。
 * ------------------------------------------------------
 * 更新履歴:
 * ver1.061:
 * ステータスクラス+クラスチェンジシーンと併用時、
 * レベルアップ時に無限ループに入ってしまうバグを修正。
 * ver1.06:
 * イベントコマンドでスキルを習得した際、
 * パッシブスキルが反映されないバグを修正。
 * ver1.051:
 * console.logを削除。
 * ver1.05:
 * いくつかの記述ミスを修正。
 * 機能していなかったプラグインパラメータを削除。
 * ver1.04:
 * 最大MPのキーワードが間違っていたバグを修正。
 * システムで設定した用語でのパッシブスキル化が正常に機能していなかった
 * バグを修正。
 * ver1.03:
 * 特徴を持っていないスキルもパッシブスキルとして判定されていたバグを修正。
 * sparamの数値が100%基準になっていなかったバグを修正。
 * ver1.02:
 * PassiveSkillManagerをfunctionの外に移動
 * ver1.01:
 * パッシブスキルのスキルタイプが一番上に追加されていると、
 * 正常に非表示にできないバグを修正。
 * ver1.00:
 * 公開
 */

function PassiveSkillManager() {
  throw new Error("This is a static class");
}

(function () {
  var parameters = PluginManager.parameters("PassiveSkill");
  var passiveSkillTypeId = Number(parameters["Passive Skill Type ID"]);
  var addMultiOrder = String(parameters["Add Multi Order"]) === "true";

  PassiveSkillManager.checkPassive = function (text) {
    if (text.match(/<(?:パッシブスキル|パッシブ|passive|PS):(.+)>/)) {
      var reg = RegExp.$1;
      var trait = this.makePassive("<" + reg + ">");
      if (trait) {
        return trait;
      }
    }
    return false;
  };

  PassiveSkillManager.makePassive = function (reg) {
    if (reg.match(/<(.+?)(\d+),?([+-]\d+)(%)?>/)) {
      return this.makeNumTrait([RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$4]);
    } else if (reg.match(/<(.+?),?([+-]?\d+)(%)?>/)) {
      return this.makeParamTrait([RegExp.$1, RegExp.$2, RegExp.$3]);
    } else if (reg.match(/<(.+)>/)) {
      return this.makeExTrait(RegExp.$1);
    }

    return false;
  };

  PassiveSkillManager.makeNumTrait = function (ary) {
    var code = null;
    var id = parseInt(ary[1]);
    var value = parseInt(ary[2]);
    var parc = ary[3];
    switch (ary[0]) {
      case "属性有効度":
      case "ElementRate":
        code = parc == "" ? 111 : 11;
        break;
      case "弱体有効度":
      case "DebuffRate":
        code = parc == "" ? 112 : 12;
        break;
      case "ステート有効度":
      case "StateRate":
        code = parc == "" ? 113 : 13;
        break;
      case "攻撃時ステート":
      case "AttackState":
        code = 32;
        break;
    }
    if (code === null) {
      return false;
    }
    value = value / 100;
    if (code < 100) {
      value += 1;
    }
    return { code: code, dataId: id, value: value };
  };

  PassiveSkillManager.makeParamTrait = function (ary) {
    var code = null;
    var id = null;
    var value = parseInt(ary[1]);
    var parc = ary[2];
    switch (ary[0]) {
      // param
      case "最大HP":
      case "最大ＨＰ":
      case TextManager.basic(2):
      case TextManager.basic(3):
      case TextManager.param(0):
        id = 0;
        code = parc == "" ? 121 : 21;
        break;
      case "最大MP":
      case "最大ＭＰ":
      case TextManager.basic(4):
      case TextManager.basic(5):
      case TextManager.param(1):
        id = 1;
        code = parc == "" ? 121 : 21;
        break;
      case "ATK":
      case "ＡＴＫ":
      case "攻撃力":
      case TextManager.param(2):
        id = 2;
        code = parc == "" ? 121 : 21;
        break;
      case "DEF":
      case "ＤＥＦ":
      case "防御力":
      case TextManager.param(3):
        id = 3;
        code = parc == "" ? 121 : 21;
        break;
      case "MAT":
      case "ＭＡＴ":
      case "魔法力":
      case TextManager.param(4):
        id = 4;
        code = parc == "" ? 121 : 21;
        break;
      case "MDF":
      case "ＭＤＦ":
      case "魔法防御":
      case TextManager.param(5):
        id = 5;
        code = parc == "" ? 121 : 21;
        break;
      case "AGI":
      case "ＡＧＩ":
      case "敏捷性":
      case TextManager.param(6):
        id = 6;
        code = parc == "" ? 121 : 21;
        break;
      case "LUK":
      case "ＬＵＫ":
      case "運":
      case TextManager.param(7):
        id = 7;
        code = parc == "" ? 121 : 21;
        break;
      // xparams
      case "HIT":
      case "ＨＩＴ":
      case "命中率":
      case TextManager.param(8):
        id = 0;
        code = 22;
        break;
      case "EVA":
      case "ＥＶＡ":
      case "回避率":
        id = 1;
        code = 22;
        break;
      case TextManager.param(9):
      case "CRI":
      case "ＣＲＩ":
      case "会心率":
        id = 2;
        code = 22;
        break;
      case "CEV":
      case "ＣＥＶ":
      case "会心回避率":
        id = 3;
        code = 22;
        break;
      case "MEV":
      case "ＭＥＶ":
      case "魔法回避率":
        id = 4;
        code = 22;
        break;
      case "MRF":
      case "ＭＲＦ":
      case "魔法反射率":
        id = 5;
        code = 22;
        break;
      case "CNT":
      case "ＣＮＴ":
      case "反撃率":
        id = 6;
        code = 22;
        break;
      case "HRG":
      case "ＨＲＧ":
      case "HP再生率":
      case "ＨＰ再生率":
        id = 7;
        code = 22;
        break;
      case "MRG":
      case "ＭＲＧ":
      case "MP再生率":
      case "ＭＰ再生率":
        id = 8;
        code = 22;
        break;
      case "TRG":
      case "ＴＲＧ":
      case "TP再生率":
      case "ＴＰ再生率":
        id = 9;
        code = 22;
        break;
      //sparams
      case "TGR":
      case "ＴＧＲ":
      case "狙われ率":
        id = 0;
        code = parc == "" ? 123 : 23;
        break;
      case "GRD":
      case "ＧＲＤ":
      case "防御効果率":
        id = 1;
        code = parc == "" ? 123 : 23;
        break;
      case "REC":
      case "ＲＥＣ":
      case "回復効果率":
        id = 2;
        code = parc == "" ? 123 : 23;
        break;
      case "PHA":
      case "ＰＨＡ":
      case "薬の知識":
        id = 3;
        code = parc == "" ? 123 : 23;
        break;
      case "MCR":
      case "ＭＣＲ":
      case "MP消費率":
      case "ＭＰ消費率":
        id = 4;
        code = parc == "" ? 123 : 23;
        break;
      case "TCR":
      case "ＴＣＲ":
      case "TPチャージ率":
      case "ＴＰチャージ率":
        id = 5;
        code = parc == "" ? 123 : 23;
        break;
      case "PDR":
      case "ＰＤＲ":
      case "物理ダメージ率":
        id = 6;
        code = parc == "" ? 123 : 23;
        break;
      case "MDR":
      case "ＭＤＲ":
      case "魔法ダメージ率":
        id = 7;
        code = parc == "" ? 123 : 23;
        break;
      case "FDR":
      case "ＦＤＲ":
      case "床ダメージ率":
        id = 8;
        code = parc == "" ? 123 : 23;
        break;
      case "EXR":
      case "ＥＸＲ":
      case "経験値獲得率":
        id = 9;
        code = parc == "" ? 123 : 23;
        break;
      //その他
      case "ステート無効化":
      case "StateResist":
        id = value;
        code = 14;
        break;
      case "攻撃時属性":
      case "AttackElement":
        id = value;
        code = 31;
        break;
      case "攻撃速度補正":
      case "AttackSpeed":
        id = value;
        code = 33;
        break;
      case "攻撃追加回数":
      case "AttackTimes+":
        id = value;
        code = 34;
        break;
      case "スキルタイプ追加":
      case "AddSkillType":
        id = value;
        code = 41;
        break;
      case "スキルタイプ封印":
      case "SealSkillType":
        id = value;
        code = 42;
        break;
      case "スキル追加":
      case "AddSkill":
        id = value;
        code = 43;
        break;
      case "スキル封印":
      case "SealSkill":
        id = value;
        code = 44;
        break;
      case "武器タイプ装備":
      case "EquipWeapon":
        id = value;
        code = 51;
        break;
      case "防具タイプ装備":
      case "EquipArmor":
        id = value;
        code = 52;
        break;
      case "装備固定":
      case "LockEquip":
        id = value;
        code = 53;
        break;
      case "装備封印":
      case "SealEquip":
        id = value;
        code = 54;
        break;
      case "行動回数追加":
      case "ActionTime+":
        id = value;
        code = 61;
        break;
      default:
    }
    if (code === null) {
      return false;
    }
    if ((code > 20 && code < 30) || code === 123) {
      value = value / 100;
    }
    if (code === 21) {
      value += 1;
    }
    if (code === 23) {
      value += 1;
    }
    return { code: code, dataId: id, value: value };
  };

  PassiveSkillManager.makeExTrait = function (reg) {
    var code = null;
    var id = null;
    var value = 1;
    switch (reg) {
      case "二刀流":
      case "DualWield":
        code = 55;
        id = 1;
        break;
      case "自動戦闘":
      case "AutoBattle":
        code = 62;
        id = 0;
        break;
      case "防御":
      case "Guard":
        code = 62;
        id = 1;
        break;
      case "身代わり":
      case "Substitute":
        code = 62;
        id = 2;
        break;
      case "TP持ち越し":
      case "PreserveTP":
        code = 62;
        id = 3;
        break;
      case "エンカウント半減":
      case "EncounterHalf":
        code = 64;
        id = 0;
        break;
      case "エンカウント無効":
      case "EncounterNone":
        code = 64;
        id = 1;
        break;
      case "不意打ち無効":
      case "CancelSurprise":
        code = 64;
        id = 2;
        break;
      case "先制攻撃率アップ":
      case "RaisePreemptive":
        code = 64;
        id = 3;
        break;
      case "獲得金額二倍":
      case "獲得金額2倍":
      case "獲得金額２倍":
      case "GoldDouble":
        code = 64;
        id = 4;
        break;
      case "アイテム入手率二倍":
      case "アイテム入手率2倍":
      case "アイテム入手率２倍":
      case "ItemDropDouble":
        code = 64;
        id = 5;
        break;
      default:
    }
    if (code === null) {
      return false;
    }
    return { code: code, dataId: id, value: value };
  };

  PassiveSkillManager.initPassiveSkill = function (skill) {
    if (skill.traits) {
      return;
    }
    skill.traits = [];
    var texts = skill.note.split("\n");
    for (var i = 0; i < texts.length; i++) {
      var trait = this.checkPassive(texts[i]);
      if (trait) {
        skill.traits.push(trait);
      }
    }
  };

  var _pS_GActor_traitObjects = Game_Actor.prototype.traitObjects;
  Game_Actor.prototype.traitObjects = function () {
    var objects = _pS_GActor_traitObjects.call(this);
    if (this.traitNest) {
      return objects;
    }
    this.traitNest = true;
    this.enableSkills().forEach(function (skill) {
      if (!skill.traits) PassiveSkillManager.initPassiveSkill(skill);
      if (skill.traits.length > 0) {
        objects.push(skill);
      }
    }, this);
    this.traitNest = false;
    return objects;
  };

  var _pS_GBBase_addedSkillTypes = Game_BattlerBase.prototype.addedSkillTypes;
  Game_BattlerBase.prototype.addedSkillTypes = function () {
    var types = _pS_GBBase_addedSkillTypes.call(this);
    if (!$gameParty.inBattle()) {
      return types;
    }
    var id = types.indexOf(passiveSkillTypeId);
    if (id >= 0) {
      types.splice(id, 1);
    }
    return types;
  };

  Game_Actor.prototype.enableSkills = function () {
    if (!this._enableSkills || this._passiveRefresh) {
      this._enableSkills = [];
      this._skills.forEach(function (skillId) {
        var skill = $dataSkills[skillId];
        if (!skill.traits) PassiveSkillManager.initPassiveSkill(skill);
        if (this.isUsableSkill(skill) && skill.traits.length > 0) {
          this._enableSkills.push(skill.id);
        }
      }, this);
      this._passiveRefresh = false;
    }
    return this._enableSkills.reduce(function (r, id) {
      return r.concat([$dataSkills[id]]);
    }, []);
  };

  var _pS_GActor_refresh = Game_Actor.prototype.refresh;
  Game_Actor.prototype.refresh = function () {
    this._passiveRefresh = true;
    _pS_GActor_refresh.call(this);
  };

  var _pS_GActor_learnSkill = Game_Actor.prototype.learnSkill;
  Game_Actor.prototype.learnSkill = function (skillId) {
    _pS_GActor_learnSkill.call(this, skillId);
    if (!(Imported["VXandAceHybridClass"] || Imported.YEP_ClassChangeCore))
      this.refresh();
  };

  Game_Actor.prototype.isUsableSkill = function (skill) {
    return (
      this.isSkillWtypeOk(skill) &&
      !this.isSkillSealed(skill.id) &&
      !this.isSkillTypeSealed(skill.stypeId)
    );
  };

  Game_Party.prototype.refreshSkills = function () {
    this.members().forEach(function (actor) {
      actor._passiveRefresh = true;
    });
  };

  var _pS_BManager_startInput = BattleManager.startInput;
  BattleManager.startInput = function () {
    $gameParty.refreshSkills();
    _pS_BManager_startInput.call(this);
  };

  if (addMultiOrder) {
    var _pS_GBBase_paramPlus = Game_BattlerBase.prototype.paramPlus;
    Game_BattlerBase.prototype.paramPlus = function (paramId) {
      var pr = _pS_GBBase_paramPlus.call(this, paramId);
      pr += this.traitsSum(121, paramId);
      return pr;
    };

    var _pS_GBBase_sparam = Game_BattlerBase.prototype.sparam;
    Game_BattlerBase.prototype.sparam = function (paramId) {
      var pr = this.traitsSum(123, paramId) + 1.0;
      pr *= _pS_GBBase_sparam.call(this, paramId);
      return pr;
    };

    var _pS_GBBase_elementRate = Game_BattlerBase.prototype.elementRate;
    Game_BattlerBase.prototype.elementRate = function (elementId) {
      var rate = this.traitsSum(111, elementId) + 1.0;
      rate *= _pS_GBBase_elementRate.call(this, elementId);
      return rate;
    };

    var _pS_GBBase_debuffRate = Game_BattlerBase.prototype.debuffRate;
    Game_BattlerBase.prototype.debuffRate = function (debuffId) {
      var rate = this.traitsSum(112, debuffId) + 1.0;
      rate *= _pS_GBBase_debuffRate.call(this, debuffId);
      return rate;
    };

    var _pS_GBBase_stateRate = Game_BattlerBase.prototype.stateRate;
    Game_BattlerBase.prototype.stateRate = function (stateId) {
      var rate = this.traitsSum(113, stateId) + 1.0;
      rate *= _pS_GBBase_stateRate.call(this, stateId);
      return rate;
    };
  } else {
    var _pS_GBBase_param = Game_BattlerBase.prototype.param;
    Game_BattlerBase.prototype.param = function (paramId) {
      var pr = _pS_GBBase_param.call(this, paramId);
      pr += this.traitsSum(121, paramId);
      var maxValue = this.paramMax(paramId);
      var minValue = this.paramMin(paramId);
      return Math.round(pr.clamp(minValue, maxValue));
    };

    var _pS_GBBase_sparam = Game_BattlerBase.prototype.sparam;
    Game_BattlerBase.prototype.sparam = function (paramId) {
      var pr = _pS_GBBase_sparam.call(this, paramId);
      pr += this.traitsSum(123, paramId) + 1.0;
      return pr;
    };

    var _pS_GBBase_elementRate = Game_BattlerBase.prototype.elementRate;
    Game_BattlerBase.prototype.elementRate = function (elementId) {
      var rate = _pS_GBBase_elementRate.call(this, elementId);
      rate += this.traitsSum(111, elementId) + 1.0;
      return rate;
    };

    var _pS_GBBase_debuffRate = Game_BattlerBase.prototype.debuffRate;
    Game_BattlerBase.prototype.debuffRate = function (debuffId) {
      var rate = _pS_GBBase_debuffRate.call(this, debuffId);
      rate += this.traitsSum(112, debuffId) + 1.0;
      return rate;
    };

    var _pS_GBBase_stateRate = Game_BattlerBase.prototype.stateRate;
    Game_BattlerBase.prototype.stateRate = function (stateId) {
      var rate = _pS_GBBase_stateRate.call(this, stateId);
      rate += this.traitsSum(113, stateId) + 1.0;
      return rate;
    };
  }
})();