/*============================================================================ * ## Plugin Info *---------------------------------------------------------------------------- * # Plugin Name * DoubleX RMMV Substitute Edit *---------------------------------------------------------------------------- * # Terms Of Use * You shall keep this plugin's Plugin Info part's contents intact * You shalln't claim that this plugin's written by anyone other than * DoubleX or his aliases * None of the above applies to DoubleX or his aliases *---------------------------------------------------------------------------- * # Prerequisites * Abilities: * 1. Little Javascript coding proficiency to fully utilize this plugin *---------------------------------------------------------------------------- * # Links * This plugin: * 1. [url]http://pastebin.com/6TGXWV1w[/url] * Mentioned Patreon Supporters: * [url]https://www.patreon.com/posts/71738797[/url] *---------------------------------------------------------------------------- * # Author * DoubleX *---------------------------------------------------------------------------- * # Changelog * v1.00b(GMT 1500 21-12-2015): * 1. Fixed typos and calling function via call instead of directly bug * v1.00a(GMT 1500 19-12-2015): * 1. 1st version of this plugin finished *============================================================================*/ /*: * @plugindesc Lets you sets conditions determining the battler to substitute * @author DoubleX * * @param substituteMissed * @desc Sets if substitutions will take place if the skill/item would miss * This feature's not implemented yet but will possibly be implemented * @default false * * @param substituteEvaded * @desc Sets if substitutions will take place if the original target would * evade the skill/item * This feature's not implemented yet but will possibly be implemented * @default false * * @param substituteCountered * @desc Sets if substitutions will take place if the original target would * counterattack/reflect the skill/item * @default false * * @param substituteCounter * @desc Sets if substitutions will take place if the skill/item's a * counterattack/reflection of that of another action * Might cause infinite counter loop with substituteBattlerCounter * @default false * * @param substituteBattlerMiss * @desc Sets if the skill/item can miss the substitute battler * This feature's not implemented yet but will possibly be implemented * @default true * * @param substituteBattlerEvade * @desc Sets if the substitute battler can evade the skill/item * This feature's not implemented yet but will possibly be implemented * @default true * * @param substituteBattlerCounter * @desc Sets if the substitute battler can counterattack/reflect the * skill/item * Might cause infinite counter loop with substituteCounter * @default true * * @param substituteBattlerFilters * @desc Sets the list of filters determining which battler to substitute * Only movable battlers having the substitute flag will be considered * The battlers passing the ith filter will proceed to the (i + 1)th one * If only 1 battler passes the ith filter, all the remaining (i + j)th * ones won't be used * If no battler pass the ith filter, all battlers passing the (i - 1)th * one will proceed to the (i + 1)th one * Available filters: * hpMp0 - The battler having 0 hp/mp * immortal - The battler being immune to death * maxCntMrf - The battler having the maximum cnt/mrf * maxEvaMev - The battler having the maximum eva/mev * maxPdrMdr - The battler having the maximum pdr/mdr * maxHpMp - The battler having the maximum hp/mp * maxGrd - The battler having the maximum grd * maxCev - The battler having the maximum cev * All unavailable filters in the list will be ignored * The battler having the smallest party/troop member index will be the * substitute battler if more than 1 battlers pass all filters in the * list * @default hpMp0 immortal maxCntMrf maxEvaMev maxPdrMdr maxHpMp maxGrd maxCev * * @help * The plugin file name must be the same as DoubleX_RMMV.Substitute_Edit_File, * which must be edited by editing the plugin js file directly * The default value of DoubleX_RMMV.Substitute_Edit_File is * DoubleX RMMV Substitute Edit v100b *============================================================================ * ## Plugin Call Info *---------------------------------------------------------------------------- * # Configuration manipulations * 1. $gameSystem.substituteEdit.param * - Returns the value of param listed in the plugin manager * 2. $gameSystem.substituteEdit.param = val * - Sets the value of param listed in the plugin manager as val * - All $gameSystem.substituteEdit.param changes will be saved *============================================================================ */ "use strict"; var DoubleX_RMMV = DoubleX_RMMV || {}; DoubleX_RMMV["Substitute Edit"] = "v1.00b"; // The plugin file name must be the same as DoubleX_RMMV.Substitute_Edit_File DoubleX_RMMV.Substitute_Edit_File = "DoubleX RMMV Substitute Edit v100b"; /*============================================================================ * ## Plugin Implementations * You need not edit this part as it's about how this plugin works *---------------------------------------------------------------------------- * # Plugin Support Info: * 1. Prerequisites * - Some Javascript coding proficiency to fully comprehend this * plugin * 2. Function documentation * - The 1st part describes why this function's rewritten/extended for * rewritten/extended functions or what the function does for new * functions * - The 2nd part describes what the arguments of the function are * - The 3rd part informs which version rewritten, extended or created * this function * - The 4th part informs whether the function's rewritten or new * - The 5th part informs whether the function's a real or potential * hotspot * - The 6th part describes how this function works for new functions * only, and describes the parts added, removed or rewritten for * rewritten or extended functions only * Example: * /*---------------------------------------------------------------------- * * Why rewrite/extended/What this function does * *----------------------------------------------------------------------*/ /* // arguments: What these arguments are * functionName = function(arguments) { // Version X+; Hotspot * // Added/Removed/Rewritten to do something/How this function works * functionContents * // * } // functionName *----------------------------------------------------------------------------*/ DoubleX_RMMV.Substitute_Edit = {}; (function(SE) { SE.BattleManager = {}; var BM = SE.BattleManager; /*------------------------------------------------------------------------ * New public instance variable *------------------------------------------------------------------------*/ // Read by Game_Unit to get the currently executing action Object.defineProperty(BattleManager, "action", { get: function() { return this._action; }, configurable: true }); BattleManager.invokeAction = function(subject, target) { this._logWindow.push('pushBaseLine'); BM.invokeAction.call(this, subject, target); // Rewritten subject.setLastTarget(target); this._logWindow.push('popBaseLine'); this.refreshStatus(); }; // BattleManager.invokeAction BattleManager.invokeNormalAction = function(subject, target) { BM.invokeNormalAction.call(this, subject, target); // Rewritten this._logWindow.displayActionResults(subject, realTarget); }; // BattleManager.invokeNormalAction BM.invokeCounterAttack = BattleManager.invokeCounterAttack; BattleManager.invokeCounterAttack = function(subject, target) { // Added if ($gameSystem.substituteEdit.substituteCounter) { return BM.invokeCounterSubstitute.call(this, subject, target); } // BM.invokeCounterAttack.apply(this, arguments); }; // BattleManager.invokeCounterAttack BM.invokeMagicReflection = BattleManager.invokeMagicReflection; BattleManager.invokeMagicReflection = function(subject, target) { if ($gameSystem.substituteEdit.substituteCounter) { this._logWindow.displayReflection(target); BM.invokeNormalAction.call(this, target, subject); this._logWindow.displayActionResults(subject, subject); return; } BM.invokeMagicReflection.apply(this, arguments); }; // BattleManager.invokeMagicReflection BM.invokeAction = function(subject, target) { var se = $gameSystem.substituteEdit; var substitute = BM.substituteBattler.call(this, target); if (se.substituteCountered && substitute !== target) { return this.invokeNormalAction(subject, target); } else if (Math.random() < this._action.itemCnt(target)) { return this.invokeCounterAttack(subject, target); } else if (Math.random() < this._action.itemMrf(target)) { return this.invokeMagicReflection(subject, target); } this.invokeNormalAction(subject, target); }; // BM.invokeAction BM.substituteBattler = function(target) { if (!this.checkSubstitute(target)) { return target; } return target.friendsUnit().substituteBattler(); }; // BM.substituteBattler BM.invokeNormalAction = function(subject, target) { var realTarget; if (!$gameSystem.substituteEdit.substituteBattlerCounter) { return; } realTarget = this.applySubstitute(target); if (realTarget === target) { return; } if (Math.random() < this._action.itemCnt(realTarget)) { return this.invokeCounterAttack(subject, realTarget); } else if (Math.random() < this._action.itemMrf(realTarget)) { return this.invokeMagicReflection(subject, realTarget); } this._action.apply(realTarget); }; // BM.invokeNormalAction BM.invokeCounterSubstitute = function(subject, target) { var lastAct = this._action; this._action = new Game_Action(target); this._action.setAttack(); this._logWindow.displayCounter(target); BM.invokeNormalAction.call(this, target, subject); this._logWindow.displayActionResults(subject, subject); this._action = lastAct; }; // BM.invokeCounterSubstitute SE.Game_System = {}; var GS = SE.Game_System; /*------------------------------------------------------------------------ * New public instance variable *------------------------------------------------------------------------*/ // The storage of all configuration values Object.defineProperty(Game_System.prototype, "substituteEdit", { get: function() { return this._substituteEdit; }, configurable: true }); GS.initialize = Game_System.prototype.initialize; Game_System.prototype.initialize = function() { GS.initialize.apply(this, arguments); GS.initSubstituteEditParams.call(this); // Added }; // Game_System.prototype.initialize GS.initSubstituteEditParams = function() { var params, filters; this._substituteEdit = {}; params = PluginManager.parameters(DoubleX_RMMV.Substitute_Edit_File); Object.keys(params).forEach(function(param) { this._substituteEdit[param] = params[param] === "true"; }, this); filters = params.substituteBattlerFilters.split(/ +/); this._substituteEdit.substituteBattlerFilters = filters; }; // GS.initSubstituteEditParams SE.Game_Action = {}; var GA = SE.Game_Action; /*------------------------------------------------------------------------ * Helper function easing checkings in filtering substitute battlers *------------------------------------------------------------------------*/ GA.effectType = function() { return this.isHpEffect() ? "hp" : this.isMpEffect() ? "mp" : null; }; // GA.effectType /*------------------------------------------------------------------------ * Helper function easing checkings in filtering substitute battlers *------------------------------------------------------------------------*/ GA.hitType = function() { return this.isPhysical() ? "pdr" : this.isMagical() ? "mdr" : null; }; // GA.hitType SE.Game_Unit = {}; var GU = SE.Game_Unit; Game_Unit.prototype.substituteBattler = function() { // Rewritten to use all filters in the filter list sequentially as well var mems = this.members(); mems = mems.filter(function(mem) { return mem.isSubstitute(); }); if (mems.length === 0) { return null; } if (mems.length === 1) { return mems[0]; } return GU.substituteBattler(mems); // }; // Game_Unit.prototype.substituteBattler // mems: All members that can substitute GU.substituteBattler = function(mems) { var tempMems, eT = GA.effectType.call(BattleManager.action); var hT = GA.hitType.call(BattleManager.action); var filters = $gameSystem.substituteEdit.substituteBattlerFilters; for (var index = 0, length = filters.length; index < length; index++) { tempMems = GU.substituteBattlers(mems, filters[index], eT, hT); if (tempMems.length === 1) { return tempMems[0]; } if (tempMems.length > 1) { mems = tempMems; } } return mems[0]; }; // GU.substituteBattler /* mems: All members that can substitute * filter: The added filter applied to all members that can substitute * effectType: The hp/mp effect type of the currently executing action * hitType: The physical/magical hit type of the currently executing action */ GU.substituteBattlers = function(mems, filter, effectType, hitType) { // Calls the filter function corresponding to the passed filter switch (filter) { case "hpMp0": return GU.hpMp0Battlers(mems, effectType); case "immortal": return GU.immortalBattlers(mems); case "maxCntMrf": return GU.maxCntMrfBattlers(mems, hitType); case "maxEvaMev": return GU.maxEvaMevBattlers(mems, hitType); case "maxPdrMdr": return hitType ? GU.maxParamBattlers(mems, hitType) : mems; case "maxHpMp": return GU.maxHpMpBattlers(mems, effectType); case "maxGrd": return GU.maxParamBattlers(mems, "grd"); case "maxCev": return GU.maxParamBattlers(mems, "cev"); default: console.log("Unavailable substitute battler filter " + filter); return mems; } // }; // GU.substituteBattlers /* mems: All members that can substitute * effectType: The hp/mp effect type of the currently executing action */ GU.hpMp0Battlers = function(mems, effectType) { if (!effectType) { return mems; } return mems.filter(function(mem) { return mem[effectType] === 0; }); }; // GU.hpMp0Battlers // mems: All members that can substitute GU.immortalBattlers = function(mems) { return mems.filter(function(mem) { return mem.isStateResist(mem.deathStateId()); }); }; // GU.immortalBattlers /* mems: All members that can substitute * hitType: The physical/magical hit type of the currently executing action */ GU.maxCntMrfBattlers = function(mems, hitType) { var counter = hitType === "pdr" ? "cnt" : "mdr" ? "mrf" : null; return counter ? GU.maxParamBattlers(mems, counter) : mems; }; // GU.maxCntMrfBattlers /* mems: All members that can substitute * hitType: The physical/magical hit type of the currently executing action */ GU.maxEvaMevBattlers = function(mems, hitType) { var evade = hitType === "pdr" ? "eva" : "mdr" ? "mev" : null; return evade ? GU.maxParamBattlers(mems, evade) : mems; }; // GU.maxEvaMevBattlers /* mems: All members that can substitute * effectType: The hp/mp effect type of the currently executing action */ GU.maxHpMpBattlers = function(mems, effectType) { return effectType ? GU.maxParamBattlers(mems, effectType) : mems; }; // GU.maxHpMpBattlers /* mems: All members that can substitute * param: The param/ExParam/SpParam used to filter the substitute battler */ GU.maxParamBattlers = function(mems, param) { var maxParam = mems.slice(0).sort(function(a, b) { return b[param] - a[param]; })[0][param]; return mems.filter(function(mem) { return mem[param] === maxParam; }); }; // GU.maxParamBattlers })(DoubleX_RMMV.Substitute_Edit); /*============================================================================*/