Code:
/*============================================================================
* ## 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. http://pastebin.com/6TGXWV1w
* Mentioned Patreon Supporters:
* https://www.patreon.com/posts/71738797
*----------------------------------------------------------------------------
* # 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);
/*============================================================================*/