//============================================================================= // SideEffectSkill.js // ---------------------------------------------------------------------------- // (C) 2016 Triacontane // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // ---------------------------------------------------------------------------- // Version // 1.8.2 2025/07/20 特定条件化で敵が自滅した場合、戦闘終了処理が二重に行われてしまう問題を修正 // 1.8.1 2024/12/01 アイテムの副作用に関する説明を追加 // 1.8.0 2023/12/04 副作用スキルを実行したアクターのIDを変数に格納できる機能を追加 // 1.7.3 2023/08/17 コモンイベントを複数定義したとき、最初のひとつしか実行されない問題を修正 // 1.7.2 2022/09/20 ID問わずすべての副作用を無効化できる特徴を追加 // 1.7.1 2022/09/20 1.7.0のメモ欄の仕様を変更 // 1.7.0 2022/09/20 副作用を無効化できる特徴を追加 // 1.6.5 2022/04/02 ステートおよびバフが解除されたとき、解除メッセージが二重に出力される場合がある問題を修正 // 1.6.4 2022/01/13 BattleEffectPopup.jsと併用したとき、使用者に対する効果ポップアップが二重に出力される場合がある問題を修正 // 1.6.3 2021/12/27 1.6.2の修正が一部不十分だった問題を修正 // 1.6.2 2021/11/29 使用者に対する行動結果が出力されない場合がある問題を修正 // 1.6.1 2021/10/20 メニュー画面でスキルを使用するとエラーになる問題を修正 // 1.6.0 2021/10/16 MZで動作するよう全面的に修正 // 1.5.0 2021/06/13 行動が耐性だったのときのみ適用する副作用を指定できる機能を追加 // 1.4.2 2020/05/22 反撃された場合などスキルを使用しなかったケースで「弱点時のみ」などの判定が無条件で有効になってしまう問題を修正 // 1.4.1 2019/07/15 BattleEffectPopup.jsと併用したとき、フロントビューだと戦闘開始時などにInvalidポップが余分に表示される競合を解消 // 1.4.0 2019/02/16 行動が無効(ダメージ0)だった場合のみ副作用を適用できる機能を追加 // 行動が反射された場合のみ副作用を適用できる機能を追加 // 1.3.0 2018/11/29 行動が会心だった場合のみ副作用を適用できる機能を追加 // 1.2.3 2017/10/10 0ターン目に戦闘行動の強制を実行するとエラーになる問題の修正 // 1.2.2 2017/10/07 ターン終了時の副作用を持つスキルでトドメをさした場合、次の戦闘のターン終了時に副作用が発生する問題を修正 // 1.2.1 2017/06/10 自動戦闘が有効なアクターがいる場合に一部機能が正常に動作しない問題を修正 // 1.2.0 2017/06/01 弱点時のみ副作用が適用できる機能を追加 // 1.1.1 2017/01/24 副作用設定時にターン終了時にダメージのポップアップ等が出なくなる問題を修正 // 1.1.0 2016/12/13 フロントビュー時にエフェクト効果のメッセージが重複して表示される問題を修正 // 1.0.2 2016/10/10 行動パターンが何も設定されていない敵キャラが行動しようとするとエラーになる問題を修正 // 1.0.1 2016/10/10 タイミングが「スキル使用時」「ターン開始時」以外のものについて、対象者にも効果が適用されていた問題を修正 // 1.0.0 2016/09/25 初版 // ---------------------------------------------------------------------------- // [Blog] : https://triacontane.blogspot.jp/ // [Twitter]: https://twitter.com/triacontane/ // [GitHub] : https://github.com/triacontane/ //============================================================================= /*: @target MZ @url https://github.com/triacontane/RPGMakerMV/tree/mz_master/SideEffectSkill.js @plugindesc Skill Side Effects Plugin @author Triacontane @license MIT License @help English Help Translator: munokura This is an unofficial English translation of the plugin help, created to support global RPG Maker users. Feedback is welcome to improve translation quality (see: https://github.com/munokura/triacontane-MZ-plugins ). Original plugin by Triacontane. Please check the latest official version at: https://triacontane.blogspot.com ----- SideEffectSkill.js You can set the effect applied to the user when using a skill or item. You can choose the timing of side effects: ・When Skill Input (Only applicable to enemy characters) The side effect is applied before allies input their actions. This is only applicable to enemy characters. ・Before Skill Use The side effect is applied immediately before using a skill. It is already applied when the skill is used. ・When Skill Use The side effect is applied at the same time as the effect is applied to the enemy when the skill is used. ・After Skill Use The side effect is applied after the effect is applied to the enemy when the skill is used. Apart from the slight difference in timing, this is almost the same as "When Skill Use." ・At the Start of Turn (Only applicable to turn-based combat) The side effect is applied the moment the turn begins after allies finish inputting their actions. ・At the End of Turn (Only applicable to turn-based combat) The side effect is applied the moment all players have completed their actions and the turn ends. Additionally, you can also apply side effects only if the skill is set to "Only on Success," "Only on Failure," or "Only on Weak Point." Specify the following in the skill or item's memo field. The effect with the specified number will affect the skill's user instead of the original effect range. (It will no longer be applied to the target.) # When skill input is performed, effect [4][3] is applied to the user (enemy only). # As above # Before skill use, effect [3] is applied to the user. # As above # When skill use, effect [3] is applied to the user. # As above # After skill use, effect [1][5] is applied to the user (separated by [,]). # As above # At the start of the turn, effect [2][4] is applied to the user. # As above # At the end of the turn, effect [8] is applied to the user. # Same as above # Apply the side effect only if the action is successful. # Same as above # Apply the side effect only if the action fails. # Same as above # Apply the side effect only if the action exploits a weak spot. # Same as above # Apply the side effect only if the action is a resistance. # Same as above # Apply the side effect only if the action is a critical hit. # Same as above # Apply the side effect only if the action is a magic reflection. # Same as above # Apply the side effect only if the action's damage is 0. # Same as above When specifying multiple effects, separate them with [,]. The effect number [1] comes first. Also, the input side effect is only for enemy characters. Conditions such as "Only on Success" and "Only on Failure" cannot be used at the following times before the skill is executed. When entering a skill Before using a skill At the start of a turn To disable a skill's side effect, write the following in the memo field of a state or equipment. # Disables the side effect of the skill with ID [3] # Same as above # Disables the side effect of the item with ID [3] # Same as above # Disables the side effects of all skills and items # Same as above The "Common Event" effect is only executed at the appropriate time if the timing is "At the start of a turn," "When using a skill," "After using a skill," or "At the end of a turn." This plugin requires the base plugin "PluginCommonBase.js." "PluginCommonBase.js" is located in the following folder under the RPG Maker MZ installation folder. dlc/BasicResources/plugins/official Terms of Use: You may modify and redistribute this plugin without permission from the author, and there are no restrictions on its use (commercial, 18+, etc.). This plugin is now yours. @param sideEffectActorVariable @text Actor variables that affect side effects @desc The variable number that stores the actor ID that is the target of the side effect. @type variable @default 0 */ /*:ja @plugindesc スキルの副作用プラグイン @target MZ @url https://github.com/triacontane/RPGMakerMV/tree/mz_master/SideEffectSkill.js @base PluginCommonBase @orderAfter PluginCommonBase @author トリアコンタン @param sideEffectActorVariable @text 副作用対象アクター変数 @desc 副作用の対象となるアクターIDを格納する変数番号です。 @default 0 @type variable @help SideEffectSkill.js スキルやアイテム使用時に、使用者に対して適用される効果を設定できます。 副作用が適用されるタイミングは以下の中から選択できます。 ・スキル入力時(敵キャラのみ有効) 味方の行動入力前に副作用が適用されます。敵キャラ専用です。 ・スキル使用前 スキルを使用する直前に副作用が適用されます。スキルを使用する時点では すでに適用済みの状態になっています。 ・スキル使用時 スキルを使用して、相手に効果が適用されるのと同じタイミングで 副作用が適用されます。 ・スキル使用後 スキルを使用して、相手に効果が適用された後で、副作用が適用されます。 微妙なタイミングの違い以外は、ほぼ「スキル使用時」と同じです。 ・ターン開始時(ターン制戦闘のみ有効) 味方の行動入力が終わってターンが開始された瞬間に 副作用が適用されます。 ・ターン終了時(ターン制戦闘のみ有効) 全員の行動が完了してターンが終了した瞬間に 副作用が適用されます。 さらにスキルが「成功時のみ」「失敗時のみ」「弱点時のみ」の場合だけ 副作用を適用することもできます。 スキルやアイテムのメモ欄に以下の通り指定してください。 使用効果のうち指定された番号の効果の適用対象がもとの効果範囲の対象者ではなく スキル使用者に変更されます。(対象者には適用されなくなります) <スキル入力時:4,3> # スキル入力時、効果[4][3]を使用者に適用(敵専用) # 同上 <スキル使用前:3> # スキル使用前、効果[3]を使用者に適用 # 同上 <スキル使用時:3> # スキル使用時、効果[3]を使用者に適用 # 同上 <スキル使用後:1,5> # スキル使用後、効果[1][5]を使用者に適用([,]区切り) # 同上 <ターン開始時:2,4> # ターン開始時、効果[2][4]を使用者に適用 # 同上 <ターン終了時:8> # ターン終了時、効果[8]を使用者に適用 # 同上 <成功時のみ> # 行動が成功した場合のみ副作用を適用 # 同上 <失敗時のみ> # 行動が失敗した場合のみ副作用を適用 # 同上 <弱点時のみ> # 行動が弱点を突いた場合のみ副作用を適用 # 同上 <耐性時のみ> # 行動が耐性だった場合のみ副作用を適用 # 同上 <会心時のみ> # 行動が会心だった場合のみ副作用を適用 # 同上 <反射時のみ> # 行動が魔法反射された場合のみ副作用を適用 # 同上 <無効時のみ> # 行動のダメージが0だった場合のみ副作用適用 # 同上 複数指定する場合、[,]で区切ってください。効果の番号が[1]が先頭です。 また入力時副作用は敵キャラ専用です。 「成功時のみ」「失敗時のみ」といった条件は、以下のタイミングでは スキルを実行前なので使用できません。  スキル入力時  スキル使用前  ターン開始時 スキルの副作用を無効化したい場合は、ステートや装備品のメモ欄に 以下の通り記述します。 <スキル副作用無効化_3> # ID[3]のスキルの副作用を無効化 # 同上 <アイテム副作用無効化_3> # ID[3]のアイテムの副作用を無効化 # 同上 <スキル副作用無効化> # すべてのスキル、アイテムの副作用を無効化 # 同上 効果「コモンイベント」はタイミングが 「ターン開始時」「スキル使用時」「スキル使用後」「ターン終了時」 の場合のみ適切なタイミングで実行されます。 このプラグインの利用にはベースプラグイン『PluginCommonBase.js』が必要です。 『PluginCommonBase.js』は、RPGツクールMZのインストールフォルダ配下の 以下のフォルダに格納されています。 dlc/BasicResources/plugins/official 利用規約: 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) についても制限はありません。 このプラグインはもうあなたのものです。 */ (()=> { 'use strict'; const script = document.currentScript; const param = PluginManagerEx.createParameter(script); //============================================================================= // DataManager // データベースのロード時にスキルとアイテムの使用効果から副作用対象を抜き取ります。 // 以下のプロパティを新規で追加します。 // sideEffectOnInput : スキル入力時副作用 // sideEffectOnBefore : スキル使用前副作用 // sideEffectOnAfter : スキル使用後副作用 // sideEffectOnStart : ターン開始時副作用 // sideEffectOnEnd : ターン終了時副作用 //============================================================================= const _DataManager_loadDatabase = DataManager.loadDatabase; DataManager.loadDatabase = function() { this._itemEffectsCategorize = false; _DataManager_loadDatabase.apply(this, arguments); }; const _DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded; DataManager.isDatabaseLoaded = function() { const result = _DataManager_isDatabaseLoaded.apply(this, arguments); if (result && !this._itemEffectsCategorize) { this._itemEffectsCategorize = true; $dataItems.forEach(item => this.categorizeItemEffects(item)); $dataSkills.forEach(item => this.categorizeItemEffects(item)); } return result; }; DataManager.categorizeItemEffects = function(data) { if (!data) return; const sideEffectOnEnd = [], sideEffectOnUsing = [], sideEffectOnBefore = [], sideEffectOnStart = [], sideEffectOnInput = [], sideEffectOnAfter = []; const numbersOnInput = this.getSideEffectNumbers(data, ['OnSkillInput', 'スキル入力時']); const numbersOnBefore = this.getSideEffectNumbers(data, ['OnSkillBefore', 'スキル使用前']); const numbersOnUsing = this.getSideEffectNumbers(data, ['OnSkillUsing', 'スキル使用時']); const numbersOnAfter = this.getSideEffectNumbers(data, ['OnSkillAfter', 'スキル使用後']); const numbersOnStart = this.getSideEffectNumbers(data, ['OnTurnStart', 'ターン開始時']); const numbersOnEnd = this.getSideEffectNumbers(data, ['OnTurnEnd', 'ターン終了時']); const effects = data.effects; for (let i = 0; i < effects.length; i++) { const effectIndex = i + 1; if (numbersOnInput.contains(effectIndex)) { sideEffectOnInput.push(effects[i]); effects[i].sideEffect = true; } if (numbersOnBefore.contains(effectIndex)) { sideEffectOnBefore.push(effects[i]); effects[i].sideEffect = true; } if (numbersOnUsing.contains(effectIndex)) { sideEffectOnUsing.push(effects[i]); effects[i].sideEffect = true; } if (numbersOnAfter.contains(effectIndex)) { sideEffectOnAfter.push(effects[i]); effects[i].sideEffect = true; } if (numbersOnStart.contains(effectIndex)) { sideEffectOnStart.push(effects[i]); effects[i].sideEffect = true; } if (numbersOnEnd.contains(effectIndex)) { sideEffectOnEnd.push(effects[i]); effects[i].sideEffect = true; } } data.effects = effects.filter(effect => !effect.sideEffect); data.sideEffectOnInput = sideEffectOnInput; data.sideEffectOnBefore = sideEffectOnBefore; data.sideEffectOnUsing = sideEffectOnUsing; data.sideEffectOnAfter = sideEffectOnAfter; data.sideEffectOnStart = sideEffectOnStart; data.sideEffectOnEnd = sideEffectOnEnd; }; DataManager.getSideEffectNumbers = function(data, names) { const metaValue = PluginManagerEx.findMetaValue(data, names); if (metaValue) { if (metaValue === String(metaValue)) { return metaValue.split(',').map(item => parseInt(item)); } else { return [metaValue]; } } return []; }; //============================================================================= // BattleManager // ターン開始時に開始時副作用を適用します。 //============================================================================= const _BattleManager_startTurn = BattleManager.startTurn; BattleManager.startTurn = function() { if (BattleManager.isTpb()) { _BattleManager_startTurn.apply(this, arguments); } else { this.makeActionOrders(); this._sideEffectBattlers = this._actionBattlers.clone(); _BattleManager_startTurn.apply(this, arguments); this.applyItemSideEffectStart(); } }; const _BattleManager_endTurn = BattleManager.endTurn; BattleManager.endTurn = function() { _BattleManager_endTurn.apply(this, arguments); if (!BattleManager.isTpb()) { if (this._sideEffectBattlers) { this.applyItemSideEffectEnd(); } } }; const _BattleManager_startAction = BattleManager.startAction; BattleManager.startAction = function() { _BattleManager_startAction.apply(this, arguments); this._action.applyItemSideEffect('sideEffectOnBefore'); }; const _BattleManager_endAction = BattleManager.endAction; BattleManager.endAction = function() { _BattleManager_endAction.apply(this, arguments); if (this._action) { this._action.applyItemSideEffect('sideEffectOnAfter'); } }; BattleManager.applyItemSideEffectStart = function() { this._sideEffectBattlers.forEach(function(battler) { const number = battler.numActions(); for (let i = 0; i < number; i++) { battler.action(i).applyItemSideEffect('sideEffectOnStart'); } }, this); }; BattleManager.applyItemSideEffectEnd = function() { this._sideEffectBattlers.forEach(function(battler) { const actions = battler.getEndActions(); actions.forEach(function(action) { action.applyItemSideEffect('sideEffectOnEnd'); }, this); battler.resetEndActions(); }, this); }; BattleManager.displaySideEffectResult = function(subject) { this._logWindow.displaySideEffectResult(subject); switch (this._phase) { case 'input': case 'turn': this._logWindow.waitForLong(); } }; //============================================================================= // Game_Battler // 終了した行動を別変数に保持します。 //============================================================================= const _Game_Battler_removeCurrentAction = Game_Battler.prototype.removeCurrentAction; Game_Battler.prototype.removeCurrentAction = function() { const action = this.currentAction(); if (action) { this._endActions = this.getEndActions(); this._endActions.push(action); } _Game_Battler_removeCurrentAction.apply(this, arguments); }; Game_Battler.prototype.getEndActions = function() { return this._endActions || []; }; Game_Battler.prototype.resetEndActions = function() { this._endActions = null; }; const _Game_Battler_onBattleEnd = Game_Battler.prototype.onBattleEnd; Game_Battler.prototype.onBattleEnd = function() { _Game_Battler_onBattleEnd.apply(this, arguments); this.resetEndActions(); }; //============================================================================= // Game_Enemy // 行動入力時に副作用を適用します。 //============================================================================= const _Game_Enemy_makeActions = Game_Enemy.prototype.makeActions; Game_Enemy.prototype.makeActions = function() { _Game_Enemy_makeActions.apply(this, arguments); const number = this.numActions(); for (let i = 0; i < number; i++) { this.action(i).applyItemSideEffect('sideEffectOnInput'); } }; //============================================================================= // Game_Action // 副作用を適用します。 //============================================================================= const _Game_Action_apply = Game_Action.prototype.apply; Game_Action.prototype.apply = function(target) { if (this._reflectionTarget) { this._reflectionForSideEffect = true; } _Game_Action_apply.apply(this, arguments); this.applyItemSideEffect('sideEffectOnUsing', target); }; const _Game_Action_makeDamageValue = Game_Action.prototype.makeDamageValue; Game_Action.prototype.makeDamageValue = function(target, critical) { this._criticalForSideEffect = critical; return _Game_Action_makeDamageValue.apply(this, arguments); }; const _Game_Action_applyItemUserEffect = Game_Action.prototype.applyItemUserEffect; Game_Action.prototype.applyItemUserEffect = function(target) { _Game_Action_applyItemUserEffect.apply(this, arguments); this._successForSideEffect = true; }; const _Game_Action_calcElementRate = Game_Action.prototype.calcElementRate; Game_Action.prototype.calcElementRate = function(target) { const rate = _Game_Action_calcElementRate.apply(this, arguments); if (!BattleManager.isInputting()) { if (rate >= 1.1) { this._effectiveForSideEffect = true; } if (rate <= 0.9) { this._resistForSideEffect = true; } } return rate; }; const _Game_Action_executeDamage = Game_Action.prototype.executeDamage; Game_Action.prototype.executeDamage = function(target, value) { if (value === 0) { this._invalidForSideEffect = true; } _Game_Action_executeDamage.apply(this, arguments); }; Game_Action.prototype.applyItemSideEffect = function(property, target = null) { if (!this.isValidSideEffect(property)) { return; } if (!this._applySideEffect) { this._applySideEffect = {}; } if (this._applySideEffect[property]) { return; } this._applySideEffect[property] = true; if (this.subject() === target) { return; } this.item()[property].forEach(function(effect) { this.applyItemEffect(this.subject(), effect); }, this); this.applyItemSideEffectGlobal(property); if (this.isNeedDisplaySideEffect(property)) { BattleManager.displaySideEffectResult(this.subject()); this.subject().result().clear(); } }; Game_Action.prototype.isValidSideEffect = function(property) { if (!this.item() || this.item()[property].length === 0) { return false; } else { return this.isValidSideEffectForSuccess() && this.isValidSideEffectForFailure() && this.isValidSideEffectForEffective() && this.isValidSideEffectForResist() && this.isValidSideEffectForCritical() && this.isValidSideEffectForInvalid() && this.isValidSideEffectForReflection() && this.isValidSideEffectForTag(); } }; Game_Action.prototype.isValidSideEffectForSuccess = function() { return this._successForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['HitOnly', '成功時のみ']); }; Game_Action.prototype.isValidSideEffectForFailure = function() { return !this._successForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['MissOnly', '失敗時のみ']); }; Game_Action.prototype.isValidSideEffectForEffective = function() { return this._effectiveForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['EffectiveOnly', '弱点時のみ']); }; Game_Action.prototype.isValidSideEffectForResist = function() { return this._resistForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['ResistOnly', '耐性時のみ']); }; Game_Action.prototype.isValidSideEffectForCritical = function() { return this._criticalForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['CriticalOnly', '会心時のみ']); }; Game_Action.prototype.isValidSideEffectForInvalid = function() { return this._invalidForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['InvalidOnly', '無効時のみ']); }; Game_Action.prototype.isValidSideEffectForReflection = function() { return this._reflectionForSideEffect || !PluginManagerEx.findMetaValue(this.item(), ['ReflectionOnly', '反射時のみ']); }; Game_Action.prototype.isValidSideEffectForTag = function() { const id = this.item().id; const allInvalidate = this.subject().traitObjects() .some(obj => PluginManagerEx.findMetaValue(obj, [`SESkillInvalidate`, `スキル副作用無効化`])); if (allInvalidate) { return false; } if (DataManager.isSkill(this.item())) { return this.subject().traitObjects() .every(obj => !PluginManagerEx.findMetaValue(obj, [`SESkillInvalidate_${id}`, `スキル副作用無効化_${id}`])); } else { return this.subject().traitObjects() .every(obj => PluginManagerEx.findMetaValue(obj, [`SEItemInvalidate_${id}`, `アイテム副作用無効化_${id}`])); } }; Game_Action.prototype.applyItemSideEffectGlobal = function(property) { this.item()[property].forEach(function(effect) { if (effect.code === Game_Action.EFFECT_COMMON_EVENT) { $gameTemp.reserveCommonEvent(effect.dataId); $gameTemp.reserveCommonEventSubject(this.subject()); } }, this); }; Game_Action.prototype.isNeedDisplaySideEffect = function(property) { if (!$gameParty.inBattle()) { return false; } return !BattleManager.isTpb() || property !== 'sideEffectOnInput'; }; const _Game_Temp_initialize = Game_Temp.prototype.initialize; Game_Temp.prototype.initialize = function() { _Game_Temp_initialize.apply(this, arguments); this._commonEventSubjectQueue = []; }; Game_Temp.prototype.reserveCommonEventSubject = function(subject) { this._commonEventSubjectQueue.push(subject); }; const _Game_Temp_retrieveCommonEvent = Game_Temp.prototype.retrieveCommonEvent; Game_Temp.prototype.retrieveCommonEvent = function() { const subject = this._commonEventSubjectQueue.shift(); const id = param.sideEffectActorVariable; if (subject && subject.isActor() && id > 0) { $gameVariables.setValue(id, subject.actorId()); } else { $gameVariables.setValue(id, 0); } return _Game_Temp_retrieveCommonEvent.apply(this, arguments); }; //============================================================================= // Window_BattleLog // 副作用効果を出力します。 //============================================================================= Window_BattleLog.prototype.displaySideEffectResult = function(subject) { this.displayChangedStates(subject); this.displayChangedBuffs(subject); subject.startDamagePopup(); if (!$gameSystem.isSideView() && subject.result().used) { this.displayDamage(subject); } }; Window_BattleLog.prototype.waitForLong = function() { if (this.countTextStack() > 0) { this.push('waitForSideEffectMessage'); this.push('clear'); } }; Window_BattleLog.prototype.waitForSideEffectMessage = function() { this._waitCount = 30; }; Window_BattleLog.prototype.countTextStack = function() { return this._methods.reduce(function(prevValue, method) { return prevValue + (method.name === 'addText' ? 1 : 0); }, 0); }; })();