/*============================================================================ * ## Plugin Info *---------------------------------------------------------------------------- * # Plugin Name * DoubleX RMMV Linked Battlers *---------------------------------------------------------------------------- * # 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. Some Javascript coding proficiency to fully utilize this plugin *---------------------------------------------------------------------------- * # Links * This plugin: * 1. [url]http://pastebin.com/wemL2xFW[/url] * Mentioned Patreon Supporters: * [url]https://www.patreon.com/posts/71738797[/url] *---------------------------------------------------------------------------- * # Author * DoubleX *---------------------------------------------------------------------------- * # Changelog * v1.00d(GMT 1500 29-1-2016): * 1. Fixed undefined g in Proto[func[0]] bug * 2. Fixed passing getter instead of its name to linkedBattlersStateId * 3. Fixed calling getter via this[getter] instead of this.getter * 4. Fixed state.linkedBattlers instead of state.meta.linkedBattlers bug * 5. Fixed adding 2 Arrays instead of concatenating them bug * 6. Fixed undefined battler isStateAdded bug * 7. Fixed linked battlers' stats being possible to be non-integer bug * 8. Only the target will collapse when some others die at the same time * v1.00c(GMT 1400 31-12-2015): * 1. Fixed writing getter contents directly instead of using String bug * v1.00b(GMT 1100 28-12-2015): * 1. Fixed unintentionally declaring global variable in strict mode bug * 2. Fixed using new Function and class instead of eval and prototype * v1.00a(GMT 1400 23-12-2015): * 1. 1st version of this plugin finished *============================================================================*/ /*: * @plugindesc Lets users set some states to let their owners share some stats * @author DoubleX * * @help * You're supposed to edit the plugin js file directly to set notetag values *============================================================================ * ## Notetag Info *---------------------------------------------------------------------------- * # State Notetags: * 1. <linked battlers: LBCX, LBSX, LBWX> * - Sets all owners of this state meeting LBCX to share stats * included in LBSX with weight LBWX applied to each of them when * any included stat of any included battler changes * - Only the 1st applicable notetag of the state with the highest * priority will be applied to the stat change of the linked battler * - If a linked battler can't take all of that battler's share of the * original stat change due to hitting the min/max stat value, thost * not being taken by that battler will be shared by the rest of the * linked battlers also * - The battler originally having a stat to be changed is the last * linked battler taking the change not shared by any other ones * - LBCX can be set in Linked Battler Condition Functions * - LBSX can be set in Linked Battler Stat Functions * - LBWX can be set in Linked Battler Weight Functions *============================================================================ * ## Plugin Call Info *---------------------------------------------------------------------------- * # Configuration manipulations * 1. DoubleX_RMMV.Linked_Battlers.prop * - Returns the property prop under DoubleX_RMMV.Linked_Battlers * 2. DoubleX_RMMV.Linked_Battlers.prop = function * - Sets the property prop under DoubleX_RMMV.Linked_Battlers as * function which will be bound to the battler upon use * - No DoubleX_RMMV.Linked_Battlers.prop change will be saved * # State manipulations * All meta.linkedBattlers changes can be saved if * DoubleX RMMV Dynamic Data is used * 1. meta.linkedBattlers * - Returns an Array of all LBCX-LBSX-LBWX triples, each in the form * of [LBCX, LBSX, LBWX] * 2. meta.linkedBattlers = [[LBCX, LBSX, LBWX], [LBCX, LBSX, LBWX], ...] * - Resets the Array of all LBCX-LBSX-LBWX triples, each in the form * of [LBCX, LBSX, LBWX], stored sequentially in that Array * 3. meta.linkedBattlers[i] = [LBCX, LBSX, LBWX] * - Sets the (i + 1)th LBCX-LBSX-LBWX triple as LBCX-LBSX-LBWX *============================================================================ */ "use strict"; var DoubleX_RMMV = DoubleX_RMMV || {}; DoubleX_RMMV["Linked Battlers"] = "v1.00d"; /*============================================================================ * ## Plugin Configurations * You only need to edit this part as it's about what this plugin does *----------------------------------------------------------------------------*/ DoubleX_RMMV.Linked_Battlers = { /*------------------------------------------------------------------------ * Linked Battler Condition Functions * - Setups LBCX used by <linked battlers: LBCX, LBSX, LBWX> *------------------------------------------------------------------------*/ /* LBCX are used in functions included in LINKED_STATS * LBCX are functions that will be bound to battler calling them upon use * LBCX names can only use alphanumeric characters * Each linked battler besides the caller can be referenced by battler * The caller will always pass LBCX even when it's supposed to fail * The below LBCX are examples added to help you set your LBCX * You can freely use, rewrite and/or delete these examples */ // Sets the linked battler condition to include all linked battlers LBC1: function(battler) { return true; }, /* Sets the linked battler condition to include all and no linked battlers * if switch with id x is on and off respectively */ LBC2: function(battler) { return $gameSwitches.value(x); }, // Adds new LBCX here /*------------------------------------------------------------------------ * Linked Battler Stat Functions * - Setups LBSX used by <linked battlers: LBCX, LBSX, LBWX> *------------------------------------------------------------------------*/ /* LBSX are used in functions included in LINKED_STATS * LBSX are functions that will be bound to battlers upon use * LBSX names can only use alphanumeric characters * It must return an Array, which should include all strings of getter * functions of each stat to be included * The below LBSX are examples added to help you set your LBSX * You can freely use, rewrite and/or delete these examples */ // Sets the linked battler stat to include hp, mp and tp LBS1: function() { return ["hp", "mp", "tp"]; }, // Sets the linked battler stat to include nothing LBS2: function() { return []; }, // Adds new LBSX here /*------------------------------------------------------------------------ * Linked Battler Weight Functions * - Setups LBWX used by <linked battlers: LBCX, LBSX, LBWX> *------------------------------------------------------------------------*/ /* LBWX are used in functions included in LINKED_STATS * LBWX are functions that will be bound to battlers upon use * LBWX names can only use alphanumeric characters * It must return a Number * No stat change will take place for any linked battler if the sum of all * weights of all linked battlers is 0 * Each linked battler besides the caller can be referenced by battler * The below LBWX are examples added to help you set your LBWX * You can freely use, rewrite and/or delete these examples */ // Sets the linked battler weight to be the same for all linked battlers LBW1: function(battler) { return 1; }, /* Sets the linked battler weight to be multiplied by x if the linked * battler is the one having a stat to be changed */ LBW2: function(battler) { return battler === this ? x : 1; }, // Adds new LBWX here /* Sets the battler functions to be used by linked battlers * Its property names must be the battler stat getter function names * Its values must be Arrays, each containing the battler stat setter * function name, the index of the argument as the original new stat value * in the stat setter function argument list, and each linked battler's * min/max stat value * All battler functions as min/max stat value must be referenced by this * All the included battler stat getter functions will be extended */ LINKED_STATS: { /* General form: * FunctionClass: { * getter: ["setter", statArgIndex, "statMin", "statMax"] * } */ Game_BattlerBase: { /* General form: * getter: ["setter", statArgIndex, "statMin", "statMax"] */ hp: ["setHp", 0, "0", "this.mhp"], mp: ["setMp", 0, "0", "this.mmp"], tp: ["setTp", 0, "0", "this.maxTp()"] // Adds new functions here } // Adds new classes here } }; // DoubleX_RMMV.Linked_Battlers /*============================================================================ * ## Plugin Implementations * You need not edit this part as it's about how this plugin works *---------------------------------------------------------------------------- * # Plugin Support Info: * 1. Prerequisites * - Decent 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 *----------------------------------------------------------------------------*/ (function(LB) { LB.DataManager = {}; var DM = LB.DataManager; DM.isDatabaseLoaded = DataManager.isDatabaseLoaded; DataManager.isDatabaseLoaded = function() { // Rewritten return DM.isDatabaseLoaded.apply(this, arguments) && DM.loadAllNotes(); // }; // DataManager.isDatabaseLoaded DM.loadAllNotes = function() { $dataStates.forEach(function(data) { if (data) { DM.loadStateNotes(data); } }); return true; }; // DM.loadAllNotes // data: The data to have its notetags read DM.loadStateNotes = function(data) { var regExp = /< *linked +battlers *: *(\w+) *, *(\w+) *, *(\w+) *>/i; data.meta.linkedBattlers = []; var linkedBattlers = data.meta.linkedBattlers; // Stores all LBCX-LBSX-LBWX triples in 1 single Array sequentially data.note.split(/[\r\n]+/).forEach(function(line) { if (!line.match(regExp)) { return; } linkedBattlers.push([RegExp.$1, RegExp.$2, RegExp.$3]); }); // }; // DM.loadStateNotes LB.Game_BattlerBase = {}; var GBB = LB.Game_BattlerBase, gf = "getLinkedBattlers"; GBB[gf] = function(stateId, cond) { var aliveMems = $gameParty.aliveMembers(); return aliveMems.concat($gameTroop.aliveMembers()).filter(function(mem) { return mem.isStateAffected(stateId) && LB[cond].call(this, mem); }, this); }; // GBB[gf] GBB.linkedBattlersStateId = function(stat) { if (!this._states) { return null; } var linkedBattlers, states = this.states(); // Returns the (1st applicable LBCX-LBSX-LBWX triple and state id) pair for (var index = 0, length = states.length; index < length; index++) { linkedBattlers = states[index].meta.linkedBattlers; for (var i = 0, l = linkedBattlers.length; i < l; i++) { if (LB[linkedBattlers[i][1]].call(this).indexOf(stat) >= 0) { return [linkedBattlers[i], states[index].id]; } } } // return null; }; // GBB.linkedBattlersStateId var Proto, Klass, func; for (var k in LB.LINKED_STATS) { if (!LB.LINKED_STATS.hasOwnProperty(k)) { continue; } LB[k] = LB[k] || {}; // Ensures container GBB won't be rewritten Proto = eval(k + ".prototype"); // Actual class prototype Klass = LB.LINKED_STATS[k]; // Class name as string for (var g in Klass) { if (!Klass.hasOwnProperty(g)) { continue; } func = Klass[g]; // ["setter", statArgIndex, "statMin", "statMax"] /*---------------------------------------------------------------- * Extends all stat setter functions to have shared stat change *----------------------------------------------------------------*/ LB[k][func[0]] = Proto[func[0]]; Proto[func[0]] = new Function ([ "var LB = DoubleX_RMMV.Linked_Battlers;", "var lBSI = LB.Game_BattlerBase.linkedBattlersStateId;", "this._linkedBattler = lBSI.call(this, '" + g + "');", "if (this._linkedBattler) {", " return LB." + k + "." + gf + g + ".apply(this, arguments);", "}", "LB." + k + "." + func[0] + ".apply(this, arguments);", ].join("\n")); // Proto[func[0]] /*---------------------------------------------------------------- * Redistributes the stat change to all found linked battlers *----------------------------------------------------------------*/ LB[k][gf + g] = new Function ([ "var LB = DoubleX_RMMV.Linked_Battlers;", "var GBB = LB.Game_BattlerBase;", "var lB = this._linkedBattler[0];", "var stateId = this._linkedBattler[1];", "var mems = GBB." + gf + ".call(this, stateId, lB[0]);", "var index = mems.indexOf(this);", "if (index >= 0) { mems.splice(index, 1); }", "mems.push(this);", "var weights = mems.map(function(mem) {", " return LB[lB[2]].call(this, mem);", "}, this);", "var weightSum = weights.reduce(function(a, b) {", " return a + b;", "}, 0);", "if (weightSum === 0) { return; }", "var statDiff = arguments[" + func[1] + "] - this." + g + ";", "var statChange, newStat, minStat, maxStat;", "for (var i = 0, l = mems.length; i < l; i++) {", " statChange = statDiff * weights[i] / weightSum;", " statChange = Math.trunc(statChange);", " newStat = mems[i]." + g + " + statChange;", " minStat = LB." + k + ".min" + g + ".call(mems[i]);", " maxStat = LB." + k + ".max" + g + ".call(mems[i]);", " if (newStat < minStat) {", " statChange = mems[i]." + g + " - minStat;", " arguments[" + func[1] + "] = minStat;", " } else if (newStat > maxStat) {", " statChange = maxStat - mems[i]." + g + ";", " arguments[" + func[1] + "] = maxStat;", " } else {", " arguments[" + func[1] + "] = newStat;", " }", " LB." + k + "." + func[0] + ".apply(mems[i], arguments);", " statDiff -= statChange;", " weightSum -= weights[i];", "}", ].join("\n")); // LB[k][gf + g] // Returns the minimum stat value LB[k]["min" + g] = new Function("return " + func[2] + ";"); // Returns the maximum stat value LB[k]["max" + g] = new Function("return " + func[3] + ";"); } } })(DoubleX_RMMV.Linked_Battlers); /*============================================================================*/