//============================================================================= // NRP_DamageEffect.js //============================================================================= /*: * @target MV MZ * @plugindesc v1.031 Change the effect of damage handling. * @author Takeshi Sunagawa (http://newrpg.seesaa.net/) * @url http://newrpg.seesaa.net/article/475586753.html * * @help Change the effect of damage handling. * * [What you can do] * 1. enable/disable enemy & actor blinking effects. * 2. Play an animation during critical or weak. * 3. change the position of the damage popup. * * Effective from ver1.02, a staging for resistance has been added. * Initially, "Resist1" is assumed to be halved * and "Resist2" is assumed to be disabled. * * For more information, please see below. * http://newrpg.seesaa.net/article/475586753.html * * [Terms] * There are no restrictions. * Modification, redistribution freedom, commercial availability, * and rights indication are also optional. * The author is not responsible, * but we will respond to defects as far as possible. * * @param * * @param enemyBlink * @parent * @type boolean * @default true * @desc Blink the enemy on damage. * The default value is true. * * @param actorBlink * @parent * @type boolean * @default false * @desc Blink the actor on damage. * The default value is false. * * @param blinkDuration * @parent * @type number * @default 20 * @desc Blinking time. The default value is 20. * * @param * * @param criticalAnimation * @parent * @type animation * @desc When critical, this animation plays back to the target. * Formula is allowed (Text). (e.g.:target.isEnemy() ? 1 : 2) * * @param criticalBlinkOff * @parent * @type boolean * @defalt false * @desc When critical, the target will not blink. * If you want to leave the effect to animation only. * * @param * * @param weakAnimation * @parent * @type animation * @desc When weak, this animation plays back to the target. * Formula is allowed (Text). (e.g.:target.isEnemy() ? 1 : 2) * * @param weakBlinkOff * @parent * @type boolean * @defalt false * @desc When weak, the target will not blink. * If you want to leave the effect to animation only. * * @param weakCondition * @parent * @type string * @default 150 <= action.calcElementRate(target) * 100 * @desc The condition for staging weaknesses. * The initial value must be 150% effective or higher. * * @param * * @param resistAnimation1 * @parent * @type animation * @desc When resist, this animation plays back to the target. * Formula is allowed (Text). (e.g.:target.isEnemy() ? 1 : 2) * * @param resistBlinkOff1 * @parent * @type boolean * @defalt false * @desc When resist, the target will not blink. * If you want to leave the effect to animation only. * * @param resistCondition1 * @parent * @type string * @default 50 >= action.calcElementRate(target) * 100 * @desc The condition for staging resistance. * The default value is less than 50% validity. * * @param * * @param resistAnimation2 * @parent * @type animation * @desc When resist, this animation plays back to the target. * Formula is allowed (Text). (e.g.:target.isEnemy() ? 1 : 2) * * @param resistBlinkOff2 * @parent * @type boolean * @defalt false * @desc When resist, the target will not blink. * If you want to leave the effect to animation only. * * @param resistCondition2 * @parent * @type string * @default 0 == action.calcElementRate(target) * 100 * @desc The condition for staging resistance. * The initial value is conditional on 0% validity. * * @param * * @param effectPrioritity * @parent * @type select * @option Critical Priority @value critical * @option Weak Priority @value weak * @option Both @value both * @default critical * @desc Priority for critical/weakness effects. * Which is the priority if it occurs at the same time? * * @param * * @param enemyDamageOffsetX * @parent * @type string * @desc Adjustment to the X for displaying enemy damage popups. * You can use a formula. The default value is 0. * * @param enemyDamageOffsetY * @parent * @type string * @desc Adjustment to the Y for displaying enemy damage popups. * You can use a formula. The default value is -8. * * @param actorDamageOffsetX * @parent * @type string * @desc Adjustment to the X for displaying actor damage popups. * You can use a formula. The default value is -32. * * @param actorDamageOffsetY * @parent * @type string * @desc Adjustment to the Y for displaying actor damage popups. * You can use a formula. The default value is 0. */ /*:ja * @target MV MZ * @plugindesc v1.031 ダメージ処理の演出を変更します。 * @author 砂川赳 (http://newrpg.seesaa.net/) * @url http://newrpg.seesaa.net/article/475586753.html * * @help ダメージ処理の演出を変更します。 * * ■できること * ・敵味方の点滅演出の有効・無効化 * ・クリティカルや弱点時にアニメーションで演出 * ・ダメージポップアップの表示位置を変更 * * ver1.02より、耐性時の演出を追加しました。 * 初期状態では耐性演出1は半減、 * 耐性演出2は無効を想定しています。 * * 詳細は以下をご覧ください。 * http://newrpg.seesaa.net/article/475586753.html * * ■利用規約 * 特に制約はありません。 * 改変、再配布自由、商用可、権利表示も任意です。 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。 * * @param * @text <点滅演出> * * @param enemyBlink * @text 敵を点滅 * @parent * @type boolean * @default true * @desc ダメージ時に敵を点滅させます。 * 初期値はtrueです。 * * @param actorBlink * @text アクターを点滅 * @parent * @type boolean * @default false * @desc ダメージ時にアクターを点滅させます。 * 初期値はfalseです。 * * @param blinkDuration * @text 点滅時間 * @parent * @type number * @default 20 * @desc 点滅時間です。初期値は20です。 * * @param * @text <クリティカル演出> * * @param criticalAnimation * @text クリティカル時のアニメ * @parent * @type animation * @desc クリティカル時、対象に再生するアニメーションです。 * 数式可(テキスト)。例:target.isEnemy() ? 1 : 2 * * @param criticalBlinkOff * @text クリティカル時の点滅オフ * @parent * @type boolean * @defalt false * @desc クリティカル時、対象を点滅させません。 * アニメーションのみに演出を任せたい場合。 * * @param * @text <弱点演出> * * @param weakAnimation * @text 弱点時のアニメ * @parent * @type animation * @desc 弱点時、対象に再生するアニメーションです。 * 数式可(テキスト)。例:target.isEnemy() ? 1 : 2 * * @param weakBlinkOff * @text 弱点時の点滅オフ * @parent * @type boolean * @defalt false * @desc 弱点時、対象を点滅させません。 * アニメーションのみに演出を任せたい場合。 * * @param weakCondition * @text 弱点演出を行う条件 * @parent * @type string * @default 150 <= action.calcElementRate(target) * 100 * @desc 弱点演出を行う条件です。 * 初期値は有効度150%以上が条件です。 * * @param * @text <耐性演出1> * * @param resistAnimation1 * @text 耐性時のアニメ1 * @parent * @type animation * @desc 耐性時、対象に再生するアニメーションです。 * 数式可(テキスト)。例:target.isEnemy() ? 1 : 2 * * @param resistBlinkOff1 * @text 耐性時の点滅オフ1 * @parent * @type boolean * @defalt false * @desc 耐性時、対象を点滅させません。 * アニメーションのみに演出を任せたい場合。 * * @param resistCondition1 * @text 耐性演出を行う条件1 * @parent * @type string * @default 50 >= action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。 * 初期値は有効度50%以下が条件です。 * * @param * @text <耐性演出2> * * @param resistAnimation2 * @text 耐性時のアニメ2 * @parent * @type animation * @desc 耐性時、対象に再生するアニメーションです。 * 数式可(テキスト)。例:target.isEnemy() ? 1 : 2 * * @param resistBlinkOff2 * @text 耐性時の点滅オフ2 * @parent * @type boolean * @defalt false * @desc 耐性時、対象を点滅させません。 * アニメーションのみに演出を任せたい場合。 * * @param resistCondition2 * @text 耐性演出を行う条件2 * @parent * @type string * @default 0 == action.calcElementRate(target) * 100 * @desc 耐性演出を行う条件です。 * 初期値は有効度0%が条件です。 * * @param * @text <クリティカル/弱点共通> * * @param effectPrioritity * @text クリティカル弱点優先度 * @parent * @type select * @option クリティカル優先 @value critical * @option 弱点優先 @value weak * @option 両方表示 @value both * @default critical * @desc クリティカル/弱点演出の優先度です。 * 同時に発生した場合にどちらを優先するか。 * * @param * @text <ダメージ表示位置> * * @param enemyDamageOffsetX * @text 敵のダメージX調整 * @parent * @type string * @desc 敵のダメージ数値を表示するX座標の調整分です。 * 数式使用可。初期値は0です。 * * @param enemyDamageOffsetY * @text 敵のダメージY調整 * @parent * @type string * @desc 敵のダメージ数値を表示するY座標の調整分です。 * 数式使用可。初期値は-8です。 * * @param actorDamageOffsetX * @text アクターのダメージX調整 * @parent * @type string * @desc アクターのダメージ数値を表示するX座標の調整分です。 * 数式使用可。初期値は-32です。 * * @param actorDamageOffsetY * @text アクターのダメージY調整 * @parent * @type string * @desc アクターのダメージ数値を表示するY座標の調整分です。 * 数式使用可。初期値は0です。 */ (function() { "use strict"; function toBoolean(str) { if (str == true) { return true; } return (str == "true") ? true : false; } 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"], true); const pActorBlink = toBoolean(parameters["actorBlink"], false); const pBlinkDuration = toNumber(parameters["blinkDuration"]); // クリティカル const pCriticalAnimation = parameters["criticalAnimation"]; const pCriticalBlinkOff = toBoolean(parameters["criticalBlinkOff"], false); // 弱点 const pWeakAnimation = parameters["weakAnimation"]; const pWeakBlinkOff = toBoolean(parameters["weakBlinkOff"], false); const pWeakCondition = parameters["weakCondition"]; // 耐性1 const pResistAnimation1 = parameters["resistAnimation1"]; const pResistBlinkOff1 = toBoolean(parameters["resistBlinkOff1"], false); const pResistCondition1 = parameters["resistCondition1"]; // 耐性2 const pResistAnimation2 = parameters["resistAnimation2"]; const pResistBlinkOff2 = toBoolean(parameters["resistBlinkOff2"], false); 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"]); // 競合を避けるためのフラグ var noBlink = false; var noDamageSound = false; /*********************************************************** * ■敵のダメージ演出 ***********************************************************/ /** * ●敵のダメージ演出 */ var _Game_Enemy_performDamage = Game_Enemy.prototype.performDamage; Game_Enemy.prototype.performDamage = function() { if (!pEnemyBlink) { noBlink = true; } // クリティカル or 弱点 or 耐性の演出対象 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() { // クリティカル or 弱点 or 耐性の演出対象 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; } // this.revertToNormal(); }; /** * ●エフェクト更新 */ 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; // 耐性1かつ点滅無効なら処理しない } else if (isResistEffect1(this) && pResistBlinkOff1) { return; // 耐性2かつ点滅無効なら処理しない } else if (isResistEffect2(this) && pResistBlinkOff2) { return; } } _Game_Battler_requestEffect.apply(this, arguments); }; /** * ●属性計算 */ const _Game_Action_calcElementRate = Game_Action.prototype.calcElementRate; Game_Action.prototype.calcElementRate = function(target) { // ダメージタイプが『なし』ならば計算しない。 if (this.item().damage.type == 0) { return 1; } return _Game_Action_calcElementRate.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); // 耐性判定1 const isResistFlg2 = isResistEffect2(target); // 耐性判定2 // クリティカルと弱点(耐性)が同時発生した場合 if (isCriticalFlg && (isWeakFlg || isResistFlg1 || isResistFlg2)) { // クリティカル優先 if (pEffectPrioritity == "critical") { callAnimation(target, eval(pCriticalAnimation), this); // 処理終了 _Window_BattleLog_displayCritical.apply(this, arguments); return; // 弱点~耐性優先 } else if (pEffectPrioritity == "weak") { // 弱点 if (isWeakFlg) { callAnimation(target, eval(pWeakAnimation), this); // 耐性2(耐性1よりも優先) } else if (isResistFlg2) { callAnimation(target, eval(pResistAnimation2), this); // 耐性1 } else if (isResistFlg1) { callAnimation(target, eval(pResistAnimation1), this); } // 処理終了 _Window_BattleLog_displayCritical.apply(this, arguments); return; } } // それ以外はクリティカルと弱点を別々に処理 if (isCriticalFlg) { callAnimation(target, eval(pCriticalAnimation), this); } // 弱点 if (isWeakFlg) { callAnimation(target, eval(pWeakAnimation), this); // 耐性2(耐性1よりも優先) } else if (isResistFlg2) { callAnimation(target, eval(pResistAnimation2), this); // 耐性1 } else if (isResistFlg1) { callAnimation(target, eval(pResistAnimation1), this); } _Window_BattleLog_displayCritical.apply(this, arguments); }; /** * ●演出対象とするかどうか? */ function isEffectTarget(target) { // クリティカル or 弱点 or 耐性の演出対象 if (isCriticalEffect(target) || isWeakEffect(target) || isResistEffect1(target) || isResistEffect2(target)) { return true; } return false; } /** * ●クリティカル演出を行うかどうか? */ function isCriticalEffect(target) { // eval参照用 const action = BattleManager._action; // クリティカルかつアニメーションが設定されている if (target.result().critical && pCriticalAnimation) { return true; } return false; } /** * ●弱点演出を行うかどうか? */ function isWeakEffect(target) { // eval参照用 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); } /** * ●耐性演出1を行うかどうか? */ function isResistEffect1(target) { // eval参照用 const action = BattleManager._action; // ミス、回避、弱点アニメーションの設定がない場合は無効 if (target.result().missed || target.result().evaded || !pResistAnimation1) { return false; } return eval(pResistCondition1); } /** * ●耐性演出2を行うかどうか? */ function isResistEffect2(target) { // eval参照用 const action = BattleManager._action; // ミス、回避、弱点アニメーションの設定がない場合は無効 if (target.result().missed || target.result().evaded || !pResistAnimation2) { return false; } return eval(pResistCondition2); } /** * ●アニメーション呼び出しを行う。 * MV, MZの両方に対応 */ function callAnimation(target, animationId, win) { if (!animationId) { return; } // MVの場合 if (Utils.RPGMAKER_NAME == "MV") { target.startAnimation(animationId, target.isActor(), 0); // MZの場合 } else { //--------------------------------------- // MZ ver1.4.0より$dataAnimations内に // MVデータが含まれるようになったので考慮 //--------------------------------------- let animation = $dataAnimations[animationId]; // MZのMV用アニメーションではない。 // かつ、MZ用アニメーションが空で // $dataMvAnimationsが有効ならMV用アニメーションを取得 if (!isMVAnimation(animation) && isEmptyAnimation(animation) && typeof $dataMvAnimations !== 'undefined') { animation = $dataMvAnimations[animationId]; } createAnimationSprite([target], animation, false, 0); } } /** * ●MZアニメーションの情報が空かどうかの判定 * ※AnimationMv.jsから移植 */ function isEmptyAnimation(animation) { return animation && !animation.effectName && animation.flashTimings.length === 0 && animation.soundTimings.length === 0; } /** * ●MVアニメーションかどうかの判定 */ function isMVAnimation(animation) { return animation && !!animation.frames; }; /** * ●MZ用のアニメーション呼び出し */ 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; }; // MZの場合 if (Utils.RPGMAKER_NAME != "MV") { /** * ●アニメーションの実行中判定 * ※実際にはウェイト判定に使う。 */ const _Spriteset_Base_isAnimationPlaying = Spriteset_Base.prototype.isAnimationPlaying; Spriteset_Base.prototype.isAnimationPlaying = function() { // 全てのアニメーションがnoWaitならば待たない。 // これによって、演出時のウェイトなくす。 if (this._animationSprites.length > 0 && this._animationSprites.every(sprite => sprite._noWait)) { return false; } return _Spriteset_Base_isAnimationPlaying.apply(this, arguments); }; } /*********************************************************** * ■ダメージ表示位置 ***********************************************************/ /** * ●敵のダメージ表示位置X */ if (pEnemyDamageOffsetX != undefined) { Sprite_Enemy.prototype.damageOffsetX = function() { const offset = eval(pEnemyDamageOffsetX); return offset ? Number(offset) : 0; }; } /** * ●敵のダメージ表示位置Y */ if (pEnemyDamageOffsetY != undefined) { Sprite_Enemy.prototype.damageOffsetY = function() { const offset = eval(pEnemyDamageOffsetY); return offset ? Number(offset) : 0; }; } /** * ●アクターのダメージ表示位置X */ if (pActorDamageOffsetX != undefined) { Sprite_Actor.prototype.damageOffsetX = function() { const offset = eval(pActorDamageOffsetX); return offset ? Number(offset) : 0; }; } /** * ●アクターのダメージ表示位置Y */ if (pActorDamageOffsetY != undefined) { Sprite_Actor.prototype.damageOffsetY = function() { const offset = eval(pActorDamageOffsetY); return offset ? Number(offset) : 0; }; } })();