//============================================================================= // NRP_DamageEffect.js //============================================================================= /*: * @target MV MZ * @plugindesc v1.04 ダメージ処理の演出を変更し、特定のステートの場合に追加アニメーションを重ねて表示します。 * @author 砂川赳 * @url http://newrpg.seesaa.net/article/475586753.html * * @help ダメージ処理の演出を変更します。 * * ■できること * ・敵味方の点滅演出の有効・無効化 * ・クリティカル、弱点、耐性時にアニメーションで演出 * ・ダメージポップアップの表示位置変更 * ・対象が特定のステートの場合に追加アニメーションを表示 * * ※各アニメーションはMV/MZ両対応 * * ■利用規約 * 特に制約はありません。改変、再配布自由、商用可、権利表示も任意です。 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。 * * @param enemyBlink * @type boolean * @default true * @desc ダメージ時に敵を点滅させます。(初期値: true) * * @param actorBlink * @type boolean * @default false * @desc ダメージ時にアクターを点滅させます。(初期値: false) * * @param blinkDuration * @type number * @default 20 * @desc 点滅時間です。(初期値: 20) * * @param criticalAnimation * @type animation * @desc クリティカル時に再生するアニメーションです。(数式可) * * @param criticalBlinkOff * @type boolean * @default false * @desc クリティカル時に対象を点滅させません。 * * @param weakAnimation * @type animation * @desc 弱点時に再生するアニメーションです。(数式可) * * @param weakBlinkOff * @type boolean * @default false * @desc 弱点時に対象を点滅させません。 * * @param weakCondition * @type string * @default 150 <= action.calcElementRate(target) * 100 * @desc 弱点演出を行う条件です。(例:有効度150%以上) * * @param resistAnimation1 * @type animation * @desc 耐性時に再生するアニメーション(タイプ1)です。(数式可) * * @param resistBlinkOff1 * @type boolean * @default false * @desc 耐性時に対象の点滅を無効にします。(アニメーションのみの場合) * * @param resistCondition1 * @type string * @default 50 >= action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。(例:有効度50%以下) * * @param resistAnimation2 * @type animation * @desc 耐性時に再生するアニメーション(タイプ2)です。(数式可) * * @param resistBlinkOff2 * @type boolean * @default false * @desc 耐性時に対象の点滅を無効にします。(アニメーションのみの場合) * * @param resistCondition2 * @type string * @default 0 == action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。(例:有効度0%) * * @param effectPrioritity * @type select * @option critical * @option weak * @option both * @default critical * @desc クリティカル/弱点演出の優先度です。(同時発生時の優先順位) * * @param enemyDamageOffsetX * @type string * @default 0 * @desc 敵のダメージ表示位置Xの調整値です。 * * @param enemyDamageOffsetY * @type string * @default -8 * @desc 敵のダメージ表示位置Yの調整値です。 * * @param actorDamageOffsetX * @type string * @default -32 * @desc アクターのダメージ表示位置Xの調整値です。 * * @param actorDamageOffsetY * @type string * @default 0 * @desc アクターのダメージ表示位置Yの調整値です。 * * @param extraStateID * @type number * @default 5 * @desc 追加アニメーションを表示する対象のステートIDです。(例:5) * * @param extraAnimationID * @type number * @default 10 * @desc 対象が上記ステートのときに再生する追加アニメーションのIDです。(例:10) */ /*:ja * @target MV MZ * @plugindesc v1.04 ダメージ処理の演出を変更し、特定のステートの場合に追加アニメーションを重ねて表示します。 * @author 砂川赳 * @url http://newrpg.seesaa.net/article/475586753.html * * @help ダメージ処理の演出を変更します。 * * ■できること * ・敵味方の点滅演出の有効・無効化 * ・クリティカル、弱点、耐性時にアニメーションで演出 * ・ダメージポップアップの表示位置変更 * ・対象が特定のステートの場合に追加アニメーションを表示 * * ※各アニメーションはMV/MZ両対応 * * ■利用規約 * 特に制約はありません。改変、再配布自由、商用可、権利表示も任意です。 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。 * * @param enemyBlink * @text 敵の点滅 * @type boolean * @default true * @desc ダメージ時に敵を点滅させます。(初期値: true) * * @param actorBlink * @text アクターの点滅 * @type boolean * @default false * @desc ダメージ時にアクターを点滅させます。(初期値: false) * * @param blinkDuration * @text 点滅時間 * @type number * @default 20 * @desc 点滅時間です。(初期値: 20) * * @param criticalAnimation * @text クリティカル時のアニメ * @type animation * @desc クリティカル時に再生するアニメーションです。(数式可) * * @param criticalBlinkOff * @text クリティカル時の点滅オフ * @type boolean * @default false * @desc クリティカル時に対象を点滅させません。 * * @param weakAnimation * @text 弱点時のアニメ * @type animation * @desc 弱点時に再生するアニメーションです。(数式可) * * @param weakBlinkOff * @text 弱点時の点滅オフ * @type boolean * @default false * @desc 弱点時に対象を点滅させません。 * * @param weakCondition * @text 弱点演出条件 * @type string * @default 150 <= action.calcElementRate(target) * 100 * @desc 弱点演出を行う条件です。(例:有効度150%以上) * * @param resistAnimation1 * @text 耐性時アニメ1 * @type animation * @desc 耐性時に再生するアニメーション(タイプ1)です。(数式可) * * @param resistBlinkOff1 * @text 耐性時点滅オフ1 * @type boolean * @default false * @desc 耐性時に対象の点滅を無効にします。(初期値: false) * * @param resistCondition1 * @text 耐性演出条件1 * @type string * @default 50 >= action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。(例:有効度50%以下) * * @param resistAnimation2 * @text 耐性時アニメ2 * @type animation * @desc 耐性時に再生するアニメーション(タイプ2)です。(数式可) * * @param resistBlinkOff2 * @text 耐性時点滅オフ2 * @type boolean * @default false * @desc 耐性時に対象の点滅を無効にします。(初期値: false) * * @param resistCondition2 * @text 耐性演出条件2 * @type string * @default 0 == action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。(例:有効度0%) * * @param effectPrioritity * @text クリティカル/弱点優先度 * @type select * @option critical * @option weak * @option both * @default critical * @desc クリティカル/弱点演出の優先度です。(同時発生時の優先順位) * * @param enemyDamageOffsetX * @text 敵ダメージ表示X調整 * @type string * @default 0 * @desc 敵のダメージ表示位置Xの調整値です。 * * @param enemyDamageOffsetY * @text 敵ダメージ表示Y調整 * @type string * @default -8 * @desc 敵のダメージ表示位置Yの調整値です。 * * @param actorDamageOffsetX * @text アクターダメージ表示X調整 * @type string * @default -32 * @desc アクターのダメージ表示位置Xの調整値です。 * * @param actorDamageOffsetY * @text アクターダメージ表示Y調整 * @type string * @default 0 * @desc アクターのダメージ表示位置Yの調整値です。 * * @param extraStateID * @text 追加ステートID * @type number * @default 5 * @desc 追加アニメーションを表示する対象のステートIDです。(例:5) * * @param extraAnimationID * @text 追加アニメーションID * @type number * @default 10 * @desc 対象が上記ステートの場合に再生する追加アニメーションのIDです。(例:10) */ (function() { "use strict"; function toBoolean(str) { if (str === true) return true; return (str === "true"); } function toNumber(str, def) { return isNaN(str) ? def : +(str || def); } function setDefault(str, def) { return (str !== undefined && str.length > 0) ? str : def; } const parameters = PluginManager.parameters("NRP_DamageEffect"); // 点滅設定 const pEnemyBlink = toBoolean(parameters["enemyBlink"]); const pActorBlink = toBoolean(parameters["actorBlink"]); const pBlinkDuration = toNumber(parameters["blinkDuration"]); // クリティカル設定 const pCriticalAnimation = parameters["criticalAnimation"]; const pCriticalBlinkOff = toBoolean(parameters["criticalBlinkOff"]); // 弱点設定 const pWeakAnimation = parameters["weakAnimation"]; const pWeakBlinkOff = toBoolean(parameters["weakBlinkOff"]); const pWeakCondition = parameters["weakCondition"]; // 耐性1設定 const pResistAnimation1 = parameters["resistAnimation1"]; const pResistBlinkOff1 = toBoolean(parameters["resistBlinkOff1"]); const pResistCondition1 = parameters["resistCondition1"]; // 耐性2設定 const pResistAnimation2 = parameters["resistAnimation2"]; const pResistBlinkOff2 = toBoolean(parameters["resistBlinkOff2"]); const pResistCondition2 = parameters["resistCondition2"]; // クリティカル/弱点共通 const pEffectPrioritity = setDefault(parameters["effectPrioritity"], "critical"); // ダメージ表示位置設定 const pEnemyDamageOffsetX = setDefault(parameters["enemyDamageOffsetX"]); const pEnemyDamageOffsetY = setDefault(parameters["enemyDamageOffsetY"]); const pActorDamageOffsetX = setDefault(parameters["actorDamageOffsetX"]); const pActorDamageOffsetY = setDefault(parameters["actorDamageOffsetY"]); // 追加アニメーション設定 const pExtraStateID = Number(parameters["extraStateID"] || 5); const pExtraAnimationID = Number(parameters["extraAnimationID"] || 10); // 重複防止用フラグ var noBlink = false; var noDamageSound = false; /*********************************************************** * ■敵のダメージ演出 ***********************************************************/ var _Game_Enemy_performDamage = Game_Enemy.prototype.performDamage; Game_Enemy.prototype.performDamage = function() { if (!pEnemyBlink) { noBlink = true; } if (isEffectTarget(this)) { noDamageSound = true; } _Game_Enemy_performDamage.apply(this, arguments); noBlink = false; noDamageSound = false; }; var _SoundManager_playEnemyDamage = SoundManager.playEnemyDamage; SoundManager.playEnemyDamage = function() { if (noDamageSound) return; _SoundManager_playEnemyDamage.apply(this, arguments); }; var _Sprite_Enemy_startBlink = Sprite_Enemy.prototype.startBlink; Sprite_Enemy.prototype.startBlink = function() { if (pBlinkDuration) { this._effectDuration = pBlinkDuration; return; } _Sprite_Enemy_startBlink.apply(this, arguments); }; /*********************************************************** * ■アクターのダメージ演出 ***********************************************************/ var _Sprite_Actor_initMembers = Sprite_Actor.prototype.initMembers; Sprite_Actor.prototype.initMembers = function() { _Sprite_Actor_initMembers.apply(this, arguments); this._effectType = null; this._effectDuration = 0; }; var _Sprite_Actor_update = Sprite_Actor.prototype.update; Sprite_Actor.prototype.update = function() { _Sprite_Actor_update.apply(this, arguments); if (this._actor) { this.updateEffect(); } }; var _Game_Actor_performDamage = Game_Actor.prototype.performDamage; Game_Actor.prototype.performDamage = function() { if (isEffectTarget(this)) { noDamageSound = true; } _Game_Actor_performDamage.apply(this, arguments); noDamageSound = false; if (pActorBlink) { this.requestEffect('blink'); } }; var _SoundManager_playActorDamage = SoundManager.playActorDamage; SoundManager.playActorDamage = function() { if (noDamageSound) return; _SoundManager_playActorDamage.apply(this, arguments); }; Sprite_Actor.prototype.startBlink = function() { if (pBlinkDuration) { this._effectDuration = pBlinkDuration; return; } this._effectDuration = 20; }; Sprite_Actor.prototype.setupEffect = function() { if (this._actor.isEffectRequested()) { this.startEffect(this._actor.effectType()); this._actor.clearEffect(); } }; Sprite_Actor.prototype.startEffect = function(effectType) { this._effectType = effectType; switch (this._effectType) { case 'blink': this.startBlink(); break; } }; Sprite_Actor.prototype.updateEffect = function() { this.setupEffect(); if (this._effectDuration > 0) { this._effectDuration--; switch (this._effectType) { case 'blink': this.updateBlink(); break; } if (this._effectDuration === 0) { this._effectType = null; } } }; Sprite_Actor.prototype.isEffecting = function() { return this._effectType !== null; }; Sprite_Actor.prototype.updateBlink = function() { this.opacity = (this._effectDuration % 10 < 5) ? 255 : 0; }; /*********************************************************** * ■共通:エフェクトリクエスト(点滅) ***********************************************************/ var _Game_Battler_requestEffect = Game_Battler.prototype.requestEffect; Game_Battler.prototype.requestEffect = function(effectType) { if (effectType === "blink") { if (noBlink) { return; } else if (isCriticalEffect(this) && pCriticalBlinkOff) { return; } else if (isWeakEffect(this) && pWeakBlinkOff) { return; } else if (isResistEffect1(this) && pResistBlinkOff1) { return; } else if (isResistEffect2(this) && pResistBlinkOff2) { return; } } _Game_Battler_requestEffect.apply(this, arguments); }; /*********************************************************** * ■クリティカル/弱点/耐性演出 ***********************************************************/ var _Window_BattleLog_displayCritical = Window_BattleLog.prototype.displayCritical; Window_BattleLog.prototype.displayCritical = function(target) { const isCriticalFlg = isCriticalEffect(target); const isWeakFlg = isWeakEffect(target); const isResistFlg1 = isResistEffect1(target); const isResistFlg2 = isResistEffect2(target); // クリティカルと弱点(または耐性)が同時発生した場合 if (isCriticalFlg && (isWeakFlg || isResistFlg1 || isResistFlg2)) { if (pEffectPrioritity === "critical") { callAnimation(target, eval(pCriticalAnimation), this); // 追加:対象が指定ステートを保持している場合、追加アニメーションを表示 if (target.isStateAffected(pExtraStateID)) { callAnimation(target, pExtraAnimationID, this); } _Window_BattleLog_displayCritical.apply(this, arguments); return; } else if (pEffectPrioritity === "weak") { if (isWeakFlg) { callAnimation(target, eval(pWeakAnimation), this); } else if (isResistFlg2) { callAnimation(target, eval(pResistAnimation2), this); } else if (isResistFlg1) { callAnimation(target, eval(pResistAnimation1), this); } _Window_BattleLog_displayCritical.apply(this, arguments); return; } } if (isCriticalFlg) { callAnimation(target, eval(pCriticalAnimation), this); // 追加:対象が指定ステートの場合、追加アニメーションを表示 if (target.isStateAffected(pExtraStateID)) { callAnimation(target, pExtraAnimationID, this); } } if (isWeakFlg) { callAnimation(target, eval(pWeakAnimation), this); } else if (isResistFlg2) { callAnimation(target, eval(pResistAnimation2), this); } else if (isResistFlg1) { callAnimation(target, eval(pResistAnimation1), this); } _Window_BattleLog_displayCritical.apply(this, arguments); }; function isEffectTarget(target) { return isCriticalEffect(target) || isWeakEffect(target) || isResistEffect1(target) || isResistEffect2(target); } function isCriticalEffect(target) { const action = BattleManager._action; return (target.result().critical && pCriticalAnimation); } function isWeakEffect(target) { const action = BattleManager._action; if (target.result().missed || target.result().evaded || !pWeakAnimation) { return false; } else if (target.result().hpAffected && target.result().hpDamage <= 0) { return false; } return eval(pWeakCondition); } function isResistEffect1(target) { const action = BattleManager._action; if (target.result().missed || target.result().evaded || !pResistAnimation1) { return false; } return eval(pResistCondition1); } function isResistEffect2(target) { const action = BattleManager._action; if (target.result().missed || target.result().evaded || !pResistAnimation2) { return false; } return eval(pResistCondition2); } function callAnimation(target, animationId, win) { if (!animationId) return; if (Utils.RPGMAKER_NAME === "MV") { target.startAnimation(animationId, target.isActor(), 0); } else { let animation = $dataAnimations[animationId]; if (!isMVAnimation(animation) && isEmptyAnimation(animation) && typeof $dataMvAnimations !== 'undefined') { animation = $dataMvAnimations[animationId]; } createAnimationSprite([target], animation, false, 0); } } function isEmptyAnimation(animation) { return animation && !animation.effectName && animation.flashTimings.length === 0 && animation.soundTimings.length === 0; } function isMVAnimation(animation) { return animation && !!animation.frames; } function createAnimationSprite(targets, animation, mirror, delay) { var spriteSet = BattleManager._spriteset; const mv = spriteSet.isMVAnimation(animation); const sprite = new (mv ? Sprite_AnimationMV : Sprite_Animation)(); const targetSprites = spriteSet.makeTargetSprites(targets); const baseDelay = spriteSet.animationBaseDelay(); const previous = delay > baseDelay ? spriteSet.lastAnimationSprite() : null; if (spriteSet.animationShouldMirror(targets[0])) { mirror = !mirror; } sprite.targetObjects = targets; sprite.setup(targetSprites, animation, mirror, delay, previous); spriteSet._effectsContainer.addChild(sprite); spriteSet._animationSprites.push(sprite); sprite._noWait = true; } if (Utils.RPGMAKER_NAME !== "MV") { const _Spriteset_Base_isAnimationPlaying = Spriteset_Base.prototype.isAnimationPlaying; Spriteset_Base.prototype.isAnimationPlaying = function() { if (this._animationSprites.length > 0 && this._animationSprites.every(sprite => sprite._noWait)) { return false; } return _Spriteset_Base_isAnimationPlaying.apply(this, arguments); }; } /*********************************************************** * ■ダメージ表示位置の調整 ***********************************************************/ if (pEnemyDamageOffsetX !== undefined) { Sprite_Enemy.prototype.damageOffsetX = function() { const offset = eval(pEnemyDamageOffsetX); return offset ? Number(offset) : 0; }; } if (pEnemyDamageOffsetY !== undefined) { Sprite_Enemy.prototype.damageOffsetY = function() { const offset = eval(pEnemyDamageOffsetY); return offset ? Number(offset) : 0; }; } if (pActorDamageOffsetX !== undefined) { Sprite_Actor.prototype.damageOffsetX = function() { const offset = eval(pActorDamageOffsetX); return offset ? Number(offset) : 0; }; } if (pActorDamageOffsetY !== undefined) { Sprite_Actor.prototype.damageOffsetY = function() { const offset = eval(pActorDamageOffsetY); return offset ? Number(offset) : 0; }; } })();