//============================================================================= // NRP_SkillEX.js //============================================================================= /*: * @target MV MZ * @plugindesc v1.076 Extend the effect of the skill. * @author Takeshi Sunagawa (http://newrpg.seesaa.net/) * @url https://newrpg.seesaa.net/article/500569896.html * * @help Extend the effect of the skill. * For example, the following skills can be created * * - High critical rate skills. * - Skills that have a success rate greater than 100. * - Skills that add states at random. * - Skills that change elements or scope depending on conditions. * - Skills that consume all MP. * * ------------------------------------------------------------------- * [Note (skill, item)] * ------------------------------------------------------------------- * All of the following can use formulas. * * ◆Add Critical Rate * * Add 50% to the critical rate. * * ◆Change Success Rate * * Set the skill success rate at 150%. * (Original value is ignored.) * * For example, the hit rate will increase as the level increases * if you do the following * * * ◆Change State Rate * * Set the State Rate of the effects to 150%. * (Original value is ignored.) * * ◆Add State * * * Add state number 4 50% of the time. * ※If is omitted, the rate is 100%. * * For example, the formula below adds 4, 5, and 6 states at random. * * ※Math.randomInt(3) means 0 to 2. * * ◆Add State To The User * * Adds state number 4 to the user of the skill. * * ◆Change Element * * Change the element to 2:Flame. * * ◆Change Scope * * Changes the scope to the specified value. * 0:None, 1:One Enemy, 2:All Enemies, 3:Enemy Random 1, * 4:Enemy Random 2, 5:Enemy Random 3, 6:Enemy Random 4, * 7:One Ally, 8:All Allies, 9:One Ally(Dead), * 10:All Allies(Dead), 11:User, 12:One Ally(Unconditional), * 13:All Allies(Unconditional), 14:Everyone * * Example: If you remember skill 100, * the all enemies. Otherwise, one enemy. * * * ◆Change Damage Type * * Changes the damage type to the specified value. * 1:HP Damage, 2:MP Damage, 3:HP Recover, 4:MP Recover, * 5:HP Drain, 6:MP Drain * * Example: Restores the HP of all allies, but the user takes damage. * * * ◆Change Number of Repeats * * Changes the number of repeats to the specified value. * * ◆Change Number of Random Times * * Changes the number of targets to the specified value * when scope is random. * It is valid for more than 5 times, which is normally not possible. * * Example: Randomly run 2-4 times. * * * ◆Recover TP * * Recovers 100 TP. * If it is negative, it will be damage. * * Example: It heals TP by a value equal to the user's mat. * * * ◆Damage To User * * It damages the user for 1/10 of the maximum HP. * * ◆Change Mp Cost * * Changes the MP cost to the specified value. * * Example: Consume all MP. * * * Note that the Mp Cost Rate will be ignored. * If you wish to include it, * please incorporate Mp Cost Rate (mcr) into the formula. * Example: * * If you want to use the MP before consumption in the damage formula, * you can refer to it below. * a.startMp() * * ◆Change Tp Cost * * Changes the TP cost to the specified value. * * If you want to use the MP before consumption in the damage formula, * you can refer to it below. * a.startTp() * * ◆Ignore Guard State * * Ignores guard state and deals damage without being halved. * * ------------------------------------------------------------------- * ■Formula Variables * ------------------------------------------------------------------- * The plugin's formulas can use the following variables * * ◆targetNo * For example, if the range was "Random 4 Enemies", * it can be distinguished by the numbers 0,1,2,3. * The following will be fire element only for the 4th shot, * and physical element for the rest. * * * * ------------------------------------------------------------------- * [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 Parameters] * @----------------------------------------------------- */ /*:ja * @target MV MZ * @plugindesc v1.076 スキルの効果を拡張します。 * @author 砂川赳(http://newrpg.seesaa.net/) * @url https://newrpg.seesaa.net/article/500569896.html * * @help スキルの効果に対して様々な拡張を行います。 * 例えば、以下のようなスキルが作成できます。 * * ・会心率の高いスキル * ・成功率が100を超えるスキル * ・ランダムでステートを付加するスキル * ・条件によって属性や範囲が変化するスキル * ・全てのMPを消費するスキル * * ------------------------------------------------------------------- * ■スキル、アイテムのメモ欄 * ------------------------------------------------------------------- * 以下はいずれも数式が使用できます。 * * ◆会心率を加算 * * 会心率を50%加算します。 * * ◆成功率を変更 * * スキルの成功率を150%にします。 * (元の値は無視されます。) * * 例えば、以下のようにすればレベルが上がるに従い命中率が上がります。 * * * ◆ステート付加率を変更 * * 使用効果のステート付加率を150%にします。 * (元の値は無視されます。) * * ◆追加ステートを付与 * * * 4番のステートを50%の確率で付加します。 * ※を省略すると100%になります。 * * 例えば、以下は4,5,6のステートをランダムで付加します。 * * ※Math.randomInt(3)は0~2の意味です。 * * ◆自身にステートを付与 * * スキルの使用者に4番のステートを付加します。 * * ◆属性を変更 * * 属性を2:炎に変更します。 * * ◆範囲を変更 * * 範囲を指定した値へ変更します。 * 0:なし, 1:敵単体, 2:敵全体, 3:敵1体ランダム, 4:敵2体ランダム, * 5:敵3体ランダム, 6:敵4体ランダム, 7:味方単体, 8:味方全体, * 9:味方単体(戦闘不能), 10:味方全体(戦闘不能), 11:使用者, * 12:味方単体(無条件), 13:味方全体(無条件), 14:敵味方全体 * * 例:スキル100を覚えている場合は敵全体。それ以外は敵単体 * * * ◆ダメージタイプを変更 * * ダメージタイプを指定した値へ変更します。 * 1:HPダメージ, 2:MPダメージ, 3:HP回復, 4:MP回復, 5:HP吸収, 6:MP回復 * * 例:味方全体のHPを回復するが、自分はダメージを受ける。 * * * ◆連続回数を変更 * * 連続回数を指定した値へ変更します。 * * ◆ランダム回数を変更 * * 範囲がランダムの場合の対象数を指定した値へ変更します。 * 通常は不可能な5回以上も有効です。 * * 例:2~4回、ランダムに実行する。 * * * ◆TP回復 * * TPを100回復します。 * マイナスならダメージになります。 * * 例:使用者の魔力分だけTPを回復。 * * * ◆自身にダメージ * * 自身に最大HPの1/10のダメージを与えます。 * * ◆消費MPを変更 * * 消費MPを指定した値へ変更します。 * * 例:全MPを消費 * * * なお、MP消費率は無視されるようになります。 * もし、含みたい場合は数式にMP消費率(mcr)を組み込んでください。 * 例: * * ダメージ計算式に消費前のMPを使用したい場合は以下で参照できます。 * a.startMp() * * ◆消費TPを変更 * * 消費TPを指定した値へ変更します。 * * ダメージ計算式に消費前のTPを使用したい場合は以下で参照できます。 * a.startTp() * * ◆防御ステートを無視 * * 防御ステートを無視して、半減されずにダメージを与えます。 * * ------------------------------------------------------------------- * ■数式用の変数 * ------------------------------------------------------------------- * 当プラグインの数式では以下の変数を使用できます。 * * ◆targetNo(対象番号) * 例えば、範囲が『敵4体 ランダム』だった場合、0,1,2,3の数値で区別できます。 * 以下は4撃目のみ炎属性、それ以外は物理属性となります。 * * * * ------------------------------------------------------------------- * ■利用規約 * ------------------------------------------------------------------- * 特に制約はありません。 * 改変、再配布自由、商用可、権利表示も任意です。 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。 * * @----------------------------------------------------- * @ プラグインパラメータ * @----------------------------------------------------- */ (function() { "use strict"; 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_SkillEX"; const parameters = PluginManager.parameters(PLUGIN_NAME); // NRP_CalcResultFirstが登録されている場合 const mIsCalcResultFirst = PluginManager._scripts.some(name => name == "NRP_CalcResultFirst"); // ---------------------------------------------------------------------------- // BattleManager // ---------------------------------------------------------------------------- // 対象が何番目か?(eval用の項目) let targetNo = 0; // 対象 let mTarget = null; /** * ●アクション開始 */ const _BattleManager_startAction = BattleManager.startAction; BattleManager.startAction = function() { targetNo = 0; _BattleManager_startAction.apply(this, arguments); }; /** * ●アクション結果呼び出し */ const _BattleManager_invokeAction = BattleManager.invokeAction; BattleManager.invokeAction = function(subject, target) { _BattleManager_invokeAction.apply(this, arguments); // 対象番号加算 targetNo++; } /** * ●アクション終了 */ const _BattleManager_endAction = BattleManager.endAction; BattleManager.endAction = function() { // アクションが取得できない場合は終了 if (!this._action) { _BattleManager_endAction.apply(this, arguments); return; } const a = this._subject; const b = a; // 自身への反動ダメージ const selfDamage = this._action.item().meta.SelfDamage; if (selfDamage) { const damage = Math.round(eval(selfDamage)); this._action.executeDamage(this._subject, damage); this._subject.result().used = true; // メッセージ表示 this._logWindow.displayActionResults(this._subject, this._subject); } // 自身への追加ステート const addSelfState = this._action.item().meta.AddSelfState; if (addSelfState) { const stateId = eval(addSelfState); this._subject.addState(stateId); this._action.makeSuccess(this._subject); // メッセージ表示 this._logWindow.displayAddedStates(this._subject); } _BattleManager_endAction.apply(this, arguments); }; // ---------------------------------------------------------------------------- // Window_BattleLog // ---------------------------------------------------------------------------- /** * ●アクション開始 * ※NRP_CalcResultFirst.js用の調整 */ const _Window_BattleLog_startAction = Window_BattleLog.prototype.startAction; Window_BattleLog.prototype.startAction = function(subject, action, targets) { targetNo = 0; _Window_BattleLog_startAction.apply(this, arguments); }; // ---------------------------------------------------------------------------- // Game_Action // ---------------------------------------------------------------------------- /** * ●成功率計算 */ const _Game_Action_itemHit = Game_Action.prototype.itemHit; Game_Action.prototype.itemHit = function(target) { // 成功率の指定がある場合は優先 const metaSuccessRate = this.item().meta.SuccessRate; if (metaSuccessRate != null) { // eval計算 const a = this.subject(); const b = target; const successRate = eval(metaSuccessRate); if (this.isPhysical()) { return successRate * 0.01 * this.subject().hit; } else { return successRate * 0.01; } } return _Game_Action_itemHit.apply(this, arguments); }; /** * ●効果反映 */ const _Game_Action_apply = Game_Action.prototype.apply; Game_Action.prototype.apply = function(target) { // 対象を保持 mTarget = target; _Game_Action_apply.apply(this, arguments); // eval計算用 const a = this.subject(); const b = target; // 命中していない場合は中止 if (!target.result().isHit()) { return; } // TP回復 const recoverTp = this.item().meta.RecoverTp; if (recoverTp) { target.gainTp(Math.round(eval(recoverTp))); this.makeSuccess(target); } // 追加ステートの処理 // ※NRP_CalcResultFirst.jsと併用する場合はここでは処理しない。 if (!mIsCalcResultFirst) { // 追加ステートの指定がなければ終了 const addState = this.item().meta.AddState; if (!addState) { return; } const stateId = eval(addState); // 計算結果が0ならば終了 if (!stateId) { return; } // AddStateRateの値を100で割ってから計算。 let chance = this.item().meta.AddStateRate ? this.item().meta.AddStateRate : 100; chance = eval(chance) / 100; if (!this.isCertainHit()) { chance *= target.stateRate(stateId); chance *= this.lukEffectRate(target); } if (Math.random() < chance) { target.addState(stateId); this.makeSuccess(target); } } } /** * ●反映確認 * ※NRP_CalcResultFirst.js用 */ const _Game_Action_testApply = Game_Action.prototype.testApply; Game_Action.prototype.testApply = function(target) { // 対象を保持 mTarget = target; return _Game_Action_testApply.apply(this, arguments); }; /** * ●効果反映 * ※NRP_CalcResultFirst.js用 */ const _Game_Action_calcResultFirst = Game_Action.prototype.calcResultFirst; Game_Action.prototype.calcResultFirst = function(target) { const keepEffects = this.item().effects; // eval計算用 const a = this.subject(); const b = target; // 追加ステートの指定がある場合 const addState = this.item().meta.AddState; if (addState) { const stateId = eval(addState); if (stateId) { // AddStateRateの値を100で割ってから計算。 let chance = this.item().meta.AddStateRate ? this.item().meta.AddStateRate : 100; chance = eval(chance) / 100; // effectsに追加する。 const effect = {code: Game_Action.EFFECT_ADD_STATE, dataId: stateId, value1: chance}; const effects = []; for (const e of this.item().effects) { effects.push(e); } effects.push(effect); this.item().effects = effects; } } _Game_Action_calcResultFirst.apply(this, arguments); // effectsを元に戻す。 this.item().effects = keepEffects; // 対象番号加算 targetNo++; }; /** * ●ステートの付加 */ const _Game_Action_itemEffectAddNormalState = Game_Action.prototype.itemEffectAddNormalState; Game_Action.prototype.itemEffectAddNormalState = function(target, effect) { // ステート付加率の指定がある場合 const stateRate = this.item().meta.StateRate; if (stateRate != null) { // ステート付加率を記憶 const keepEffectValue1 = effect.value1; // eval計算用 const a = this.subject(); const b = target; // 一時的にステート付加率を書き換え effect.value1 = eval(stateRate) / 100; // 実行 _Game_Action_itemEffectAddNormalState.apply(this, arguments); // 元に戻す effect.value1 = keepEffectValue1; return; } _Game_Action_itemEffectAddNormalState.apply(this, arguments); }; /** * ●属性ダメージの計算 */ const _Game_Action_calcElementRate = Game_Action.prototype.calcElementRate; Game_Action.prototype.calcElementRate = function(target) { // 属性IDの指定がある場合 const changeElement = this.item().meta.ChangeElement; if (changeElement != null) { // 属性IDを記憶 const keepElementId = this.item().damage.elementId; // eval計算用 const a = this.subject(); const b = target; // 一時的に属性IDを書き換え this.item().damage.elementId = Number(eval(changeElement)); // 実行 const ret = _Game_Action_calcElementRate.apply(this, arguments); // 元に戻す this.item().damage.elementId = keepElementId; return ret; } return _Game_Action_calcElementRate.apply(this, arguments); }; /** * ●スキル/アイテムの範囲確認 */ const _Game_Action_checkItemScope = Game_Action.prototype.checkItemScope; Game_Action.prototype.checkItemScope = function(list) { // eval参照用 const a = this.subject(); // 範囲を変更する場合 const changeScope = this.item().meta.ChangeScope; if (changeScope) { return list.includes(eval(changeScope)); } return _Game_Action_checkItemScope.apply(this, arguments); }; /** * ●会心率を取得 */ const _Game_Action_itemCri = Game_Action.prototype.itemCri; Game_Action.prototype.itemCri = function(target) { const ret = _Game_Action_itemCri.apply(this, arguments); // eval参照用 const a = this.subject(); const b = target; // 会心率を加算する場合 const addCriticalRate = this.item().meta.AddCriticalRate; if (addCriticalRate) { return ret + eval(addCriticalRate) / 100; } return ret; }; /** * ●対象毎の評価 */ const _Game_Action_evaluateWithTarget = Game_Action.prototype.evaluateWithTarget; Game_Action.prototype.evaluateWithTarget = function(target) { mTarget = target; return _Game_Action_evaluateWithTarget.apply(this, arguments); }; /** * ●ダメージ実行 */ const _Game_Action_executeDamage = Game_Action.prototype.executeDamage; Game_Action.prototype.executeDamage = function(target, value) { mTarget = target; _Game_Action_executeDamage.apply(this, arguments); }; /** * ●ダメージタイプの確認 */ const _Game_Action_checkDamageType = Game_Action.prototype.checkDamageType; Game_Action.prototype.checkDamageType = function(list) { // eval参照用 const a = this.subject(); const b = mTarget; // ダメージタイプを記憶 const keepDamageType = this.item().damage.type; try { // ダメージタイプの変更 // ※エラーになった場合はスルー const damageType = this.item().meta.ChangeDamageType; if (damageType != null) { // 一時的にダメージタイプを書き換えて実行 this.item().damage.type = eval(damageType); const ret = _Game_Action_checkDamageType.apply(this, arguments); this.item().damage.type = keepDamageType; return ret; } } catch (e) {} return _Game_Action_checkDamageType.apply(this, arguments); }; /** * ●ダメージ計算式 */ const _Game_Action_evalDamageFormula = Game_Action.prototype.evalDamageFormula; Game_Action.prototype.evalDamageFormula = function(target) { const damageType = this.item().meta.ChangeDamageType; if (damageType != null) { // ダメージタイプを記憶 const keepDamageType = this.item().damage.type; // eval参照用 const a = this.subject(); const b = target; // 一時的にダメージタイプを書き換え this.item().damage.type = eval(damageType); const ret = _Game_Action_evalDamageFormula.apply(this, arguments); this.item().damage.type = keepDamageType; return ret; } return _Game_Action_evalDamageFormula.apply(this, arguments); }; /** * ●連続回数 */ const _Game_Action_numRepeats = Game_Action.prototype.numRepeats; Game_Action.prototype.numRepeats = function() { const metaChangeNumRepeats = this.item().meta.ChangeNumRepeats; if (metaChangeNumRepeats) { const keepRepeats = this.item().repeats; // eval参照用 const a = this.subject(); const action = this; // 一時的に連続回数を書き換える。 this.item().repeats = eval(metaChangeNumRepeats); const numRepeats = _Game_Action_numRepeats.apply(this, arguments); // 値を戻す。 this.item().repeats = keepRepeats; return numRepeats; } return _Game_Action_numRepeats.apply(this, arguments);; }; /** * ●範囲がランダムの際の対象数 */ const _Game_Action_numTargets = Game_Action.prototype.numTargets; Game_Action.prototype.numTargets = function() { const metaChangeNumRandom = this.item().meta.ChangeNumRandom; if (metaChangeNumRandom) { // 既に設定済みなら取得 if (this._numTargets != null) { return this._numTargets; } // eval参照用 const a = this.subject(); const numTargets = eval(metaChangeNumRandom); // actionに設定して記憶する。 // ※値がランダムの場合に以降の処理を固定させるため this._numTargets = numTargets; return numTargets; } return _Game_Action_numTargets.apply(this, arguments); }; /** * ●防御状態を反映 */ const _Game_Action_applyGuard = Game_Action.prototype.applyGuard; Game_Action.prototype.applyGuard = function(damage, target) { // 防御状態無視の場合 const ignoreGuard = this.item().meta.IgnoreGuard; if (ignoreGuard) { return damage; } return _Game_Action_applyGuard.apply(this, arguments); }; // ---------------------------------------------------------------------------- // Game_BattlerBase // ---------------------------------------------------------------------------- /** * ●消費MP */ const _Game_BattlerBase_skillMpCost = Game_BattlerBase.prototype.skillMpCost; Game_BattlerBase.prototype.skillMpCost = function(skill) { this._startMp = this.mp; const changeMpCost = skill.meta.ChangeMpCost if (changeMpCost != null) { const a = this; return Math.floor(eval(changeMpCost)); } return _Game_BattlerBase_skillMpCost.apply(this, arguments); }; /** * ●消費TP */ const _Game_BattlerBase_skillTpCost = Game_BattlerBase.prototype.skillTpCost; Game_BattlerBase.prototype.skillTpCost = function(skill) { this._startTp = this.tp; const changeTpCost = skill.meta.ChangeTpCost; if (changeTpCost != null) { const a = this; return Math.floor(eval(changeTpCost)); } return _Game_BattlerBase_skillTpCost.apply(this, arguments); }; /** * 【独自】スキル使用前のMP */ Game_BattlerBase.prototype.startMp = function() { return this._startMp; }; /** * 【独自】スキル使用前のTP */ Game_BattlerBase.prototype.startTp = function() { return this._startTp; }; })();