/*============================================================================= RemoveStateExtend.js ---------------------------------------------------------------------------- (C)2022 Triacontane This software is released under the MIT License. http://opensource.org/licenses/mit-license.php ---------------------------------------------------------------------------- Version 1.3.0 2025/08/07 行動を受けることでステート解除できる機能を追加 1.2.0 2024/02/22 魔法反射や回避など特定行動でステート解除できる機能を追加 ステートの付与によって別のステートを解除できる機能を追加 1.1.1 2023/10/23 解除条件に属性を指定したとき、スキルの指定が「通常攻撃」の場合、解除の対象にならない問題を修正 1.1.0 2022/06/08 解除条件にスクリプトを設定、解除確率を補正するタグを追加 1.0.0 2022/03/23 初版 ---------------------------------------------------------------------------- [Blog] : https://triacontane.blogspot.jp/ [Twitter]: https://twitter.com/triacontane/ [GitHub] : https://github.com/triacontane/ =============================================================================*/ /*: * @plugindesc 条件付きステート解除プラグイン * @target MZ * @url https://github.com/triacontane/RPGMakerMV/tree/mz_master/RemoveStateExtend.js * @base PluginCommonBase * @orderAfter PluginCommonBase * @author トリアコンタン * * @param byDamageList * @text ダメージで解除のリスト * @desc ダメージを受けたときのステート解除を条件付きにします。データベースの当該項目とは独立して動作します。 * @default [] * @type struct[] * * @param byAcceptedList * @text 受けた行動で解除のリスト * @desc 行動を受けたときにステートを解除します。味方や自分自身の行動も対象に含まれます。 * @default [] * @type struct[] * * @param byCountList * @text 継続ターン数で解除のリスト * @desc 継続ターン数を指定したステートの減少条件が、ターン数ではなく指定した条件になります。 * @default [] * @type struct[] * * @param byAddList * @text 付与ステートで解除のリスト * @desc 付与されたステートによって解除されるステートを設定します。 * @default [] * @type struct[] * * @help RemoveStateExtend.js * * ステート解除の条件を拡張します。 * 特定の属性を含む(含まない)攻撃を受けたときや、魔法攻撃を受けたとき * HP割合が指定値を下回った場合のみ解除されるステートなどが作成できます。 * パラメータから条件リストを設定します。 * * ステートを解除するときの確率を補正(加算)するメモ欄です。 * アクター、職業、武器、防具、敵キャラ、ステートのメモ欄で有効です。 * ex:ステートID[3]のステート解除確率が20%加算されます。 * <ステート解除補正3:20> *  * このプラグインの利用にはベースプラグイン『PluginCommonBase.js』が必要です。 * 『PluginCommonBase.js』は、RPGツクールMZのインストールフォルダ配下の * 以下のフォルダに格納されています。 * dlc/BasicResources/plugins/official * * 利用規約: * 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) * についても制限はありません。 * このプラグインはもうあなたのものです。 */ /*~struct~DAMAGE: * * @param stateId * @text ステートID * @desc 解除条件を設定するステートIDです。同一ステートを複数定義したときは『いずれか』の条件を満たすと解除されます。 * @default 1 * @type state * * @param skillId * @text スキルID * @desc 受けた行動が特定のスキルを使用したときに解除されます。0を指定すると全てのスキルが対象になります。 * @default 0 * @type skill * * @param elementId * @text 属性ID * @desc 受けた行動が特定の属性を含んでいたときに解除されます。 * @default 0 * @type number * * @param hitType * @text 命中タイプ * @desc 命中タイプが指定したものと一致するときに解除されます。 * @default 0 * @type select * @option 指定なし * @value 0 * @option 物理攻撃 * @value 1 * @option 魔法攻撃 * @value 2 * @option 必中 * @value 3 * * @param hpRate * @text HP割合(%) * @desc HPが指定した割合以下の場合に解除されます。 * @default 0 * @type number * @min 0 * @max 100 * * @param mpRate * @text MP割合(%) * @desc MPが指定した割合以下の場合に解除されます。 * @default 0 * @type number * @min 0 * @max 100 * * @param tpRate * @text TP割合(%) * @desc TPが指定した割合以下の場合に解除されます。 * @default 0 * @type number * @min 0 * @max 100 * * @param script * @text スクリプト * @desc 指定した場合、スクリプトの評価結果がtrueを返した場合に解除されます。thisでバトラー、stateでステートが参照できます。 * @default * @type multiline_string * * @param reverse * @text 条件反転 * @desc 上記の条件を『満たさなかった』場合に解除されるよう変更します。 * @default false * @type boolean * * @param chanceByDamage * @text 解除確率 * @desc 条件を満たしたときに解除される確率です。100%にすると常に解除されます。 * @default 100 * @type number * @min 0 * @max 100 * */ /*~struct~COUNT: * * @param stateId * @text ステートID * @desc 解除条件を設定するステートIDです。 * @default 1 * @type state * * @param condition * @text 解除条件 * @desc 継続ターンの代わりになる条件です。ターン数で指定した回数分これらが行われると解除されます。 * @type select * @option 回避 * @value evasion * @option 魔法回避 * @value magicEvasion * @option 魔法反射 * @value reflection * @option 反撃 * @value counter * @option 身代わり * @value substitute * */ /*~struct~ADD: * * @param removeStates * @text 解除ステート一覧 * @desc 対象ステート一覧で指定したステートが付与されたときに解除されるステートの一覧です。 * @default [] * @type state[] * * @param targetStates * @text 対象ステート一覧 * @desc ここで指定したステートが付与されると解除ステートで指定したステートが解除されます。 * @default [] * @type state[] * */ (() => { 'use strict'; const script = document.currentScript; const param = PluginManagerEx.createParameter(script); if (!param.byDamageList) { param.byDamageList = []; } if (!param.byCountList) { param.byCountList = []; } if (!param.byAddList) { param.byAddList = []; } if (!param.byAcceptedList) { param.byAcceptedList = []; } const _Game_BattlerBase_updateStateTurns = Game_BattlerBase.prototype.updateStateTurns; Game_BattlerBase.prototype.updateStateTurns = function() { for (const stateId of this._states) { if (this._stateTurns[stateId] > 0 && param.byCountList.some(item => item.stateId === stateId)) { this._stateTurns[stateId]++; } } _Game_BattlerBase_updateStateTurns.apply(this, arguments); }; Game_BattlerBase.prototype.findAltConditionStates = function(condition) { return this._states.filter(stateId => param.byCountList.some(item => { return item.stateId === stateId && item.condition === condition; })); }; Game_Battler.prototype.removeStateTurnsByAltCondition = function(condition) { this.findAltConditionStates(condition).forEach(stateId => { if (this._stateTurns[stateId] > 0) { this._stateTurns[stateId]--; if (this.isStateExpired(stateId)) { this.removeState(stateId); } } }); }; const _Game_Battler_performEvasion = Game_Battler.prototype.performEvasion; Game_Battler.prototype.performEvasion = function() { _Game_Battler_performEvasion.apply(this, arguments); this.removeStateTurnsByAltCondition('evasion'); }; const _Game_Battler_performMagicEvasion = Game_Battler.prototype.performMagicEvasion; Game_Battler.prototype.performMagicEvasion = function() { _Game_Battler_performMagicEvasion.apply(this, arguments); this.removeStateTurnsByAltCondition('magicEvasion'); }; const _Game_Battler_performReflection = Game_Battler.prototype.performReflection; Game_Battler.prototype.performReflection = function() { _Game_Battler_performReflection.apply(this, arguments); this.removeStateTurnsByAltCondition('reflection'); }; const _Game_Battler_performCounter = Game_Battler.prototype.performCounter; Game_Battler.prototype.performCounter = function() { _Game_Battler_performCounter.apply(this, arguments); this.removeStateTurnsByAltCondition('counter'); }; const _Game_Battler_performSubstitute = Game_Battler.prototype.performSubstitute; Game_Battler.prototype.performSubstitute = function(target) { _Game_Battler_performSubstitute.apply(this, arguments); this.removeStateTurnsByAltCondition('substitute'); }; const _Game_Battler_addState = Game_Battler.prototype.addState; Game_Battler.prototype.addState = function(stateId) { _Game_Battler_addState.apply(this, arguments); if (this.isStateAffected(stateId)) { param.byAddList .filter(item => item.targetStates.includes(stateId)) .forEach(item => item.removeStates.forEach(id => this.removeState(id))); } }; const _Game_Action_applyItemUserEffect = Game_Action.prototype.applyItemUserEffect; Game_Action.prototype.applyItemUserEffect = function(target) { _Game_Action_applyItemUserEffect.apply(this, arguments); if (target) { target.removeStatesByDamageExtend(param.byAcceptedList); } }; const _Game_Battler_removeStatesByDamage = Game_Battler.prototype.removeStatesByDamage; Game_Battler.prototype.removeStatesByDamage = function() { _Game_Battler_removeStatesByDamage.apply(this, arguments); this.removeStatesByDamageExtend(param.byDamageList); }; Game_Battler.prototype.removeStatesByDamageExtend = function(list) { if (!this._acceptAction) { return; } this.states().forEach(state => { list.filter(item => this.isRemoveStateExtend(state, item)) .forEach(item => this.removeState(item.stateId)); }); }; Game_Battler.prototype.isRemoveStateExtend = function(state, paramItem) { if (state.id !== paramItem.stateId) { return false; } const acceptItem = this._acceptAction.item(); let result = true; if (paramItem.elementId && !this._acceptAction.hasElement(paramItem.elementId)) { result = false; } if (paramItem.skillId && acceptItem.id !== paramItem.skillId) { result = false; } if (paramItem.hitType && acceptItem.hitType !== paramItem.hitType) { result = false; } if (paramItem.hpRate && this.hpRate() > paramItem.hpRate / 100) { result = false; } if (paramItem.mpRate && this.mpRate() > paramItem.mpRate / 100) { result = false; } if (paramItem.tpRate && this.tpRate() > paramItem.tpRate / 100) { result = false; } if (paramItem.script && !eval(paramItem.script)) { result = false; } if (paramItem.reverse) { result = !result; } return Math.randomInt(100) < this.findRemoveStateRate(paramItem, state) ? result : false; } Game_Battler.prototype.findRemoveStateRate = function(paramItem, state) { const tag = `ステート解除補正${state.id}` const rate = this.traitObjects() .reduce((prev, obj) => prev + (PluginManagerEx.findMetaValue(obj, tag) || 0), 0); return paramItem.chanceByDamage + rate; } Game_Battler.prototype.setAcceptedAction = function(action) { this._acceptAction = action; } Game_Action.prototype.hasElement = function(elementId) { if (this.item().damage.type === 0) { return false; } const skillElementId = this.item().damage.elementId; // Normal attack elementID[-1] if (skillElementId === -1) { return this.subject().attackElements().contains(elementId); } else { return elementId === skillElementId; } }; const _Game_Action_apply = Game_Action.prototype.apply; Game_Action.prototype.apply = function(target) { target.setAcceptedAction(this); _Game_Action_apply.apply(this, arguments); target.setAcceptedAction(null); }; })();