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