Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
7185 lines (6418 sloc)
286 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*============================================================================ | |
| * ## Plugin Info | |
| *---------------------------------------------------------------------------- | |
| * # Plugin Name | |
| * DoubleX RMMZ Enhanced Codebase | |
| *---------------------------------------------------------------------------- | |
| * # Introduction | |
| * 1. This plugin's supposed to be fully compatible with those not written | |
| * with this plugin in mind, so plugin developers don't have to write | |
| * compatibility fixes involving this plugin | |
| * 2. This plugin added some new APIs and refactored some codes to further | |
| * facilitate more effective and efficient plugin development by making | |
| * the default RMMZ codebase quality improvements even more drastic | |
| * Note that such refactoring will only be done incrementally, meaning | |
| * that these codebase quality improvements won't be all present in the | |
| * 1st version of this plugin, but only when they cause real issues in | |
| * plugin development, in which those improvements will be added to be | |
| * newer versions of this plugin | |
| * 3. This plugin also fixed some bugs and further improved performance in | |
| * the default RMMZ codebase | |
| * 4. THIS PLUGIN'S INTENDED TO GIVE AN EXTRA OPTION TO PLUGIN DEVELOPERS | |
| * RATHER THAN REPLACING THE DEFAULT RMMZ CODEBASE | |
| *---------------------------------------------------------------------------- | |
| * # Prerequisites | |
| * Abilities(Plugin Users): | |
| * 1. Nothing special | |
| * Abilities(Plugin Developers): | |
| * 1. Basic knowledge on what the default RMMZ codebase does in general | |
| * 2. Some RMMZ plugin development proficiency to fully utilize this | |
| * plugin in intended ways | |
| * (Basic knowledge on what RMMZ plugin development does in general | |
| * with several easy, simple and small plugins written without | |
| * nontrivial bugs up to 1000 LoC scale but still being inexperienced) | |
| *---------------------------------------------------------------------------- | |
| * # Terms Of Use | |
| * 1. Commercial use's always allowed and crediting me's always optional. | |
| * 2. You shall keep this plugin's Plugin Info part's contents intact. | |
| * 3. You shalln't claim that this plugin's written by anyone other than | |
| * DoubleX or my aliases. I always reserve the right to deny you from | |
| * using any of my plugins anymore if you've violated this. | |
| * 4. If you repost this plugin directly(rather than just linking back), | |
| * you shall inform me of these direct repostings. I always reserve | |
| * the right to request you to edit those direct repostings. | |
| * 5. CC BY 4.0, except those conflicting with any of the above, applies | |
| * to this plugin, unless you've my permissions not needing follow so. | |
| * 6. I always reserve the right to deny you from using this plugin | |
| * anymore if you've violated any of the above. | |
| *---------------------------------------------------------------------------- | |
| * # Links | |
| * This Plugin: | |
| * 1. https://github.com/Double-X/DoubleX-RMMZ/blob/master/DoubleX%20RMMZ%20Enhanced%20Codebase.js | |
| * Posts: | |
| * 1. | |
| * 2. | |
| * 3. | |
| * 4. | |
| * 5. | |
| * 6. | |
| * 7. | |
| * 8. | |
| * 9. | |
| * 10. | |
| *---------------------------------------------------------------------------- | |
| * # Instructions | |
| * 1. THIS PLUGIN MUST BE PLACED ABOVE ALL THE OTHER PLUGINS | |
| * 2. The version number of this plugin's consists of 2 parts, with 1 | |
| * being the targeted default RMMZ codebase versions, so this plugin | |
| * must be outdated if those version numbers are indeed different | |
| * 3. (Plugin developers only)The version numbers of this plugin are | |
| * stored in DoubleX_RMMZ.Enhanced_Codebase.VERSIONS, which should be | |
| * { codebase: "1.4.3", plugin: "v0.00a" } | |
| * If it's falsy, it means this plugin's not loaded at the moment of | |
| * querying its version numbers | |
| * 4. (Plugin developers only)Please use the following search tag to | |
| * check how this plugin extends and rewrites functions: | |
| * - Enhanced_Codebase_Extend_Rewrite_Funcs | |
| * Note that the original function will still be stored in the plugin | |
| * container even if it's supposed to be rewritten rather than | |
| * extended | |
| * Please use the following search tag to check how this plugin adds | |
| * accessors, getters and setters: | |
| * - Enhanced_Codebase_Add_Accessors | |
| *---------------------------------------------------------------------------- | |
| * # Contributors | |
| * Authors: | |
| * 1. DoubleX | |
| * Plugin Development Collaborators: | |
| * - None So Far | |
| * Bug Reporters: | |
| * - None So Far | |
| * Compatibility Issue Raisers: | |
| * - None So Far | |
| * Feature Requesters: | |
| * - None So Far | |
| *---------------------------------------------------------------------------- | |
| * # Todo | |
| * 1. Adds Array.prototype.filterFlat(with improved performance) | |
| * 2. Adds Array.prototype.filterFlatMap(with improved performance) | |
| * 3. Adds Array.prototype.filterMapReduce(with improved performance) | |
| * 4. Adds Array.prototype.filterMapReduceRight(with improved | |
| * performance) | |
| * 5. Adds Array.prototype.filterReduce(with improved performance) | |
| * 6. Adds Array.prototype.filterReduceRight(with improved performance) | |
| * 7. Adds Array.prototype.flatFilter(with improved performance) | |
| * 8. Adds Array.prototype.flatFilterReduce(with improved performance) | |
| * 9. Adds Array.prototype.flatFilterReduceRight(with improved | |
| * performance) | |
| * 10. Adds Array.prototype.flatMapEvery(with improved performance) | |
| * 11. Adds Array.prototype.flatMapFilter(with improved performance) | |
| * 12. Adds Array.prototype.flatMapFilterReduce(with improved | |
| * performance) | |
| * 13. Adds Array.prototype.flatMapFilterReduceRight(with improved | |
| * performance) | |
| * 14. Adds Array.prototype.flatMapFind(with improved performance) | |
| * 15. Adds Array.prototype.flatMapReduce(with improved performance) | |
| * 16. Adds Array.prototype.flatMapReduceRight(with improved performance) | |
| * 17. Adds Array.prototype.flatMapSome(with improved performance) | |
| * 18. Adds Array.prototype.mapEvery(with improved performance) | |
| * 19. Adds Array.prototype.mapFilterReduce(with improved performance) | |
| * 20. Adds Array.prototype.mapFilterReduceRight(with improved | |
| * performance) | |
| * 21. Adds Array.prototype.mapFind(with improved performance) | |
| * 22. Adds Array.prototype.mapReduceRight(with improved performance) | |
| * 23. Adds Array.prototype.mapSome(with improved performance) | |
| *============================================================================*/ | |
| /*: | |
| * @url https://www.patreon.com/doublex | |
| * @target MZ | |
| * @plugindesc Versions: { codebase: "1.4.3", plugin: "v0.00a" } | |
| * Fixes bugs, improves codebase quality, boosts performance and gives new APIs | |
| * @author DoubleX | |
| * | |
| * @param rngPartNum | |
| * @desc Sets the number of parts altering Math.random randomness | |
| * It makes Math.random gives more evenly distributed numbers | |
| * @default 10 | |
| * | |
| * @help | |
| *============================================================================ | |
| * ## Plugin Users Info | |
| *---------------------------------------------------------------------------- | |
| * # Additional plugin parameter explanations | |
| * 1. rngPartNum | |
| * Math.random will be run under each of equal-sized partitions | |
| * The number of those partitions is rngPartNum | |
| * No partition will be run under twice before they've all been run | |
| * under | |
| * rngPartNum shouldn't be too large nor too small to maximize the | |
| * chance for the RNG generated by Math.random() to be more evenly | |
| * distributed(For instance, 10 is a good value for rngPartNum) | |
| * Larger rngPartNum means more time and memory needed to run it | |
| * E.g.: | |
| * - With rngPartNum being 10, the random numbers will be divided into | |
| * the below 10 partitions: | |
| * i. - [0, 0.1) | |
| * ii. - [0.1, 0.2) | |
| * iii. - [0.2, 0.3) | |
| * iv. - [0.3, 0.4) | |
| * v. - [0.4, 0.5) | |
| * vi. - [0.5, 0.6) | |
| * vii. - [0.6, 0.7) | |
| * viii. - [0.7, 0.8) | |
| * ix. - [0.8, 0.9) | |
| * x. - [0.9, 1) | |
| * Then every 10 consecutive Math.random() call will always results | |
| * in random numbers in different partitions, until all partitions | |
| * are used, then all those partitions will be reset and can be used | |
| * again | |
| * For instance, the consecutive call results of Math.random with | |
| * rngPartNum being 10, can be something like this: | |
| * i. - 0.5583369022811258 // 6 - [0.5, 0.6) | |
| * ii. - 0.8856774551202906 // 9 - [0.8, 0.9) | |
| * iii. - 0.7053351634934172 // 8 - [0.7, 0.8) | |
| * iv. - 0.2910141721648054 // 3 - [0.2, 0.3) | |
| * v. - 0.46443921703774416 // 5 - [0.4, 0.5) | |
| * vi. - 0.34247765359444715 // 4 - [0.3, 0.4) | |
| * vii. - 0.9611230852360236 // 10 - [0.9, 1) | |
| * viii. 0.170055669517572 // 2 - [0.1, 0.2) | |
| * ix. - 0.6280946076323228 // 7 - [0.6, 0.7) | |
| * x. - 0.09900382018076581 // 1 - [0, 0.1) | |
| * (Now all the 10 partitions are used after the 1st 10 consecutive | |
| * Math.random() call and thus reset to be able to be "used" again) | |
| * xi. - 0.49970969353564276 // 5 - [0.4, 0.5) | |
| * xii. - 0.19670031315146652 // 2 - [0.1, 0.2) | |
| * xiii. - 0.6183234115814623 // 7 - [0.6, 0.7) | |
| * xiv. - 0.9592661473226407 // 10 - [0.9, 1) | |
| * xv. - 0.837747307203645 // 9 - [0.8, 0.9) | |
| * xvi. - 0.06670947818157003 // 1 - [0, 0.1) | |
| * xvii. - 0.20614586616388186 // 3 - [0.2, 0.3) | |
| * xviii. - 0.38808043042462215 // 4 - [0.3, 0.4) | |
| * xix. - 0.7973840400497697 // 8 - [0.7, 0.8) | |
| * xx. - 0.5467456358572309 // 6 - [0.5, 0.6) | |
| * # Fixed bugs | |
| * 1. The RMMZ hardcodes the rendering loop fps to be the monitor refresh | |
| * rate, and can be problematic when targeting players with low end | |
| * mobiles | |
| * - This plugin lets you force the rendering loop fps by this script | |
| * call: | |
| * Graphics.renderFps = newRenderFps | |
| * Where newRenderFps is the new clamped rendering loop fps | |
| * - This can be useful when targeting low end mobiles by clamping the | |
| * rendering loop fps to 30 | |
| * - Setting this as 0 will remove the clamping | |
| * - Do note that the rendering loop fps can never go beyond the | |
| * monitor refresh rate | |
| * Search tag: Graphics_Render_FPS | |
| * 2. The RMMZ hardcodes the game loop fps to be 60, and can be | |
| * problematic when targeting players with low end mobiles | |
| * - This plugin lets you change the game loop fps by this script | |
| * call: | |
| * Graphics.gameFps = newGameFps | |
| * Where newGameFps is the game loop fps | |
| * - This can be useful as a performance stress test by raising the | |
| * game loop fps to be 120, or when targeting low end mobiles by | |
| * capping the game loop fps to 30 | |
| * - Do note that the game loop fps has an upper bound, which depends | |
| * on the hardware capability of the running machine(so you'll have | |
| * to test it out yourselves), so don't be too insane with it(like | |
| * setting it to 2400, and you'll most likely have troubles) | |
| * Search tag: Graphics_Game_FPS | |
| * 3. The faulty damage formula will just silently return 0 damage | |
| * instead of informing you what faults are in which damage formula | |
| * - This plugin lets you know them by this script call: | |
| * Game_Action.IS_SHOW_DAMAGE_FORMULA_ERRS = true | |
| * Which is useful when testing the damage formulae | |
| * - Alternatively, if you don't want your players to know anything | |
| * about the damage formula, you can use this script call: | |
| * Game_Action.IS_SHOW_DAMAGE_FORMULA_ERRS = false | |
| * Which is useful when the game's about to be published | |
| * 4. Any damage formula having side effects will have those side effects | |
| * leaked out in the battle when some autobattle actors having those | |
| * skills/items input actions | |
| * - This plugin temporarily removes the side effect parts of all | |
| * damage formulae of skills/items of autobattle actors when they | |
| * input actions, but those side effects will still be there when | |
| * the inputted actions are actually executed | |
| * - It's done by replacing the damage formula string with the regular | |
| * expression stored in | |
| * Game_Action.NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX, and its default | |
| * value is new RegExp(".*[};] *", "gim"), meaning that anything | |
| * before the last } or ; will be temporarily removed from the | |
| * damage formula | |
| * - If that default regular expression doesn't suit your needs, you | |
| * can change Game_Action.NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX to be | |
| * a suitable counterpart | |
| * - Regardless of how the regular expression's written, you should | |
| * standardize your damage formula so the side effect parts can | |
| * always be reliably removed with an easy, simple and small regular | |
| * expression | |
| * - (Advanced)Alternatively, you can edit | |
| * Game_Action.prototype.damageFormulaWithoutSideEffects to use | |
| * different regular expressions to santizie different damage | |
| * formulae, or even just return a separate side-effect free | |
| * counterpart as string literals or notetag values for some | |
| * skills/items yourselves, like: | |
| * Game_Action.prototype.damageFormulaWithoutSideEffects = function() { | |
| * const { id, meta, damage: { formula } } = this.item(); | |
| * switch (id) { | |
| * case 1: return meta.damageFormulaWithoutSideEffectsNotetag; | |
| * case 2: return "damageFormulaWithoutSideEffects"; | |
| * case 3: return formula.replace(regex1, ""); | |
| * case 4: return formula.replace(regex2, ""); | |
| * default 1: return formula.replace(Game_Action.NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX, ""); | |
| * } | |
| * }; | |
| * Do note that this plugin doesn't provide such notetags for you, | |
| * so you'll have to use the default RMMZ notetags, which is of this | |
| * format: <notetagName:notetagValue> | |
| * 5. The active TPBS will have an extremely rare chance to crash the | |
| * game when trying to select the inputting actor, the inputting | |
| * actions, or its targets | |
| * - Please refer to this link for details: | |
| * https://forums.rpgmakerweb.com/index.php?threads/bug-extremely-rare-but-fatal-active-tpbs-bug-crashing-the-game.126144/ | |
| *============================================================================ | |
| * ## Plugin Developers Info | |
| *---------------------------------------------------------------------------- | |
| * # New public APIs | |
| * Object | |
| * - Instance method | |
| * 1. traceObjProp(cond, label) | |
| * - Traces all object properties satisfying function cond linked to | |
| * this object | |
| * - Labels all traced object properties with function label | |
| * - cond and label are functions written in | |
| * Object Property Trace Condition Function and | |
| * Object Property Trace Label Function | |
| * of plugin configurations respectively | |
| * - Instance variable | |
| * 1. objPropLog[cond] | |
| * - Returns the log of all traced object properties satisfying | |
| * function cond linked to this object | |
| * - cond is a function written in | |
| * Object Property Trace Condition Function of plugin configurations | |
| * Array | |
| * - Instance methods | |
| * 1. fastMap(mapCallback, mapThis_) | |
| * The same as map but is tested to be noticeably faster | |
| * 2. fastMerge(arr) | |
| * The same as concat except that fastMerge alters the original array | |
| * instead of returning a new one | |
| * 3. filterMap(filterCallback, mapCallback, filterThis_, mapThis_) | |
| * The same as chaining filter with map except that the new array | |
| * returned by filter will be mapped in place(.filter().map()) | |
| * 4. mapFilter(mapCallback, filterCallback, mapThis_, filterThis_) | |
| * The same as chaining map with filter except that the new array | |
| * returned by map will be filtered in place(.map().filter()) | |
| * 5. mapReduce(mapCallback, reduceCallback, initVal_, mapThis_, reduceThis_) | |
| * The same as chaining map with reduce but is tested to be | |
| * noticeably faster(.map().reduce()) | |
| * 6. eraseElem(elem) | |
| * Erases the passed element(if any) from this original array | |
| * 7. split(splitCallback, splitThis) | |
| * Returns an array of array splited by the removed elements | |
| * returning truthy results in splitCallback | |
| * 8. splitInPlace(splitCallback, splitThis) | |
| * Returns an array of array splited by the removed elements | |
| * returning truthy results in splitCallback | |
| * This method changes the original array | |
| * 9. isProperSubsetOf(arr) | |
| * Returns if this array's a proper subset of the specified array | |
| * 10. isProperSupersetOf(arr) | |
| * Returns if this array's a proper superset of the specified array | |
| * 11. isSupersetOf(arr) | |
| * Returns if this array's a superset of the specified array | |
| * 12. isSubsetOf(arr) | |
| * Returns if this array's a subset of the specified array | |
| * 13. isEmpty() | |
| * Returns if this array's empty | |
| * 14. symmetricDifference(arr) | |
| * Returns the symmetric difference of this and the specified array | |
| * 15. symmetricDifferenceInplace(arr) | |
| * Returns the symmetric difference of this and the specified array | |
| * This method changes the original array | |
| * 16. union(arr) | |
| * Returns the union of this and the specified array | |
| * 17. unionInPlace(arr) | |
| * Returns the union of this and the specified array | |
| * This method changes the original array | |
| * 18. difference(arr) | |
| * Returns the difference of this and the specified array | |
| * 19. differenceInPlace(arr) | |
| * Returns the difference of this and the specified array | |
| * This method changes the original array | |
| * 20. intersection(arr) | |
| * Returns the intersection of this and the specified array | |
| * 21. intersectionInPlace(arr) | |
| * Returns the intersection of this and the specified array | |
| * This method changes the original array | |
| * 22. excludes(elem, fromI) | |
| * Returns if this array doesn't include the specified element | |
| * 23. clear() | |
| * Empties the whole array | |
| * Graphics | |
| * - Static Accessor | |
| * 1. renderFps | |
| * Returns the current render fps | |
| * 2. renderFps = newRenderFps | |
| * Sets the current render fps to be newRenderFps | |
| * 3. gameFps | |
| * Returns the current game fps | |
| * 4. gameFps = newGameFps | |
| * Sets the current game fps to be newGameFps | |
| * Input | |
| * - Static Function | |
| * 1. isJustReleased(keyName) | |
| * Returns if the specified key's just released right on this frame | |
| * Game_Action | |
| * - Static Variable | |
| * 1. IS_SHOW_DAMAGE_FORMULA_ERRS | |
| * Controls whether the damage formula error will be reported on the | |
| * console to let users know whether they've some faulty damage | |
| * formulae | |
| * 2. IS_CACHE_DAMAGE_FORMULA | |
| * Controls whether the skill/item damage formula will be always | |
| * reevaluated each time or cached into a function to turn repeated | |
| * eval calls into repeated function calls | |
| * 3. NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX | |
| * Stores the regular expressions to temporarily remove the parts of | |
| * the damage formula leaking side effects when evaluating the damage | |
| * among all actions of autobattle actors to fix the side effect | |
| * leaking bug when those actor input actions | |
| * Game_BattlerBase | |
| * - Instance Method | |
| * 1. onUnrestrict | |
| * Triggers events to happen when a battler becomes no longer | |
| * restricted | |
| * Game_Battler | |
| * - Instance Method | |
| * 1. tpbCastTime | |
| * Returns the proportion of the skill/item casting progress | |
| * 2. tpbIdleTime | |
| * Returns the proportion of the battler idling progress | |
| * 3. isTpbActing | |
| * Returns whether the battler's executing tpb actions | |
| * 4. isTpbCharging | |
| * Returns whether the battler's charging the tpb bar | |
| * 5. isTpbCasting | |
| * Returns whether the battler's casting tpb actions | |
| * 6. onTpbReady | |
| * Triggers events to happen when the battler just finished casting | |
| * tpb actions | |
| * 7. isEndTpbCharging | |
| * Returns whether the tpb battler's just ended charging the tpb bar | |
| * 8. isEndTpbCasting | |
| * Returns whether the tpb battler's just ended casting actions | |
| * 9. isTpbIdle | |
| * Returns whether the battler tpb bar's idle(not doing anything) | |
| * Game_Interpreter | |
| * - Static Variable | |
| * 1. IS_CACHE_SCRIPT | |
| * Controls whether the scripts in events will be always reevaluated | |
| * each time or cached into a function to turn repeated eval calls | |
| * into repeated function calls | |
| *============================================================================ | |
| */ | |
| // jshint esversion: 6 | |
| var DoubleX_RMMZ = DoubleX_RMMZ || {}; // var must be used or game will crash | |
| (() => { | |
| "use strict"; | |
| const src = document.currentScript.src; | |
| const name = src.split("/").slice(-1)[0].split(".")[0].replace(/%20/g, " "); | |
| console.info(src, name); | |
| // Separates the version numbers with the rest to make the former more clear | |
| DoubleX_RMMZ.Enhanced_Codebase = { | |
| CFG: {}, | |
| PLUGIN_NAME: name, | |
| VERSIONS: { codebase: "1.4.3", plugin: "v0.00a" } | |
| }; // DoubleX_RMMZ.Enhanced_Codebase | |
| // | |
| })(); | |
| (MZ_EC => { | |
| "use strict"; | |
| const pluginCodebaseVer = MZ_EC.VERSIONS.codebase; | |
| if (Utils.checkRMVersion(pluginCodebaseVer)) return; | |
| console.warn(`Your codebase version is ${Utils.RPGMAKER_VERSION} but must be | |
| at least ${pluginCodebaseVer} to use ${MZ_EC.PLUGIN_NAME}`); | |
| })(DoubleX_RMMZ.Enhanced_Codebase); | |
| /*============================================================================ | |
| * ## Plugin Configurations | |
| * You only need to edit this part as it's about what this plugin does | |
| *----------------------------------------------------------------------------*/ | |
| (CFG => { | |
| "use strict"; | |
| CFG.objPropTrace = { | |
| /*-------------------------------------------------------------------- | |
| * Object Property Trace Condition Function | |
| * - Setups cond used by traceObjProp(cond, label) | |
| *--------------------------------------------------------------------*/ | |
| /* cond must be a function taking the object property as only argument | |
| Below examples are added to help you setup your own cond functions */ | |
| /** | |
| * Pure function | |
| * @since v0.00a @version v0.00a | |
| * @param {*} obj - The property of the object being traced | |
| * @returns {boolean} Whether the property of the object's to be traced | |
| */ | |
| condObj: function(obj) { | |
| // Checks if the currently traced object's indeed a non-Array object | |
| return !Array.isArray(obj) && typeof obj === "object"; | |
| // | |
| }, // substitute cond with "condObj" to use this function | |
| /** | |
| * Pure function | |
| * @since v0.00a @version v0.00a | |
| * @param {*} obj - The property of the object being traced | |
| * @returns {boolean} Whether the property of the object's to be traced | |
| */ | |
| condArr: function(obj) { | |
| // Checks if the currently traced object's an array | |
| return Array.isArray(obj); | |
| // | |
| }, // substitute cond with "condArr" to use this function | |
| // Add your own cond functions here | |
| /*-------------------------------------------------------------------- | |
| * Object Property Trace Label Function | |
| * - Setups label used by traceObjProp(cond, label) | |
| *--------------------------------------------------------------------*/ | |
| /* label must be a function taking the object property as only argument | |
| All label functions must return a string | |
| No label will be applied to an object directly | |
| Below examples are added to help you setup your label functions */ | |
| /** | |
| * Pure function | |
| * @since v0.00a @version v0.00a | |
| * @param {*} obj - The property of the object being traced | |
| * @returns {string} The label of the traced object property | |
| */ | |
| labelObj: function(obj) { | |
| // Always returns whole traced object property string representation | |
| if (typeof obj === "object") return JSON.stringify(obj); | |
| return obj.toString(); | |
| // This doesn't work if the property to be labelled is an object | |
| }, // substitute label with "labelObj" to use this function | |
| /** | |
| * Pure function | |
| * @since v0.00a @version v0.00a | |
| * @param {*} obj - The property of the object being traced | |
| * @returns {string} The label of the traced object property | |
| */ | |
| labelType: function(obj) { | |
| // Always returns type(including Array) of traced object property | |
| return Array.isArray(obj) ? "array" : typeof obj; | |
| // This doesn't work if the property to be labelled is an object | |
| } // substitute label with "labelType" to use this function | |
| // Add your own label functions here | |
| }; // CFG.objPropTrace | |
| })(DoubleX_RMMZ.Enhanced_Codebase.CFG); | |
| /*============================================================================ | |
| * ## Plugin Implementations | |
| * You need not edit this part as it's about how this plugin works | |
| *---------------------------------------------------------------------------- | |
| * # Plugin Support Info: | |
| * 1. Prerequisites | |
| * - Solid understanding on how the default RMMZ codebase works on its | |
| * own in details | |
| * - Decent RMMZ plugin development proficiency to fully comprehend | |
| * this plugin | |
| * (Solid understanding on how RMMZ plugin development works on its | |
| * own in details with dozens of tolerable quality plugins written | |
| * without nontrivial bugs with some up to 3000 LoC scale and being | |
| * experienced) | |
| * 2. Parameter/Return value of type * means it might be of any type | |
| * 3. Function signature with (**) means it might take any number of | |
| * parameters of any type | |
| * 4. Supposedly nullable variables are marked with the _ suffix in their | |
| * names(but they can be sure to be non null in some cases) | |
| * 5. Functions supposedly returning nullable values are marked with the | |
| * _ suffix in their names(but their return values can be sure to be | |
| * non null in some cases) | |
| *----------------------------------------------------------------------------*/ | |
| /*============================================================================*/ | |
| (MZ_EC => { | |
| "use strict"; | |
| MZ_EC.setKlassContainer = (klassName, origKlass, plugin) => { | |
| const container = plugin[klassName] = { orig: {}, new: {} }; | |
| return { | |
| NEW: container.new, | |
| ORIG: container.orig, | |
| addAccessor: CORE._addAccessor.bind(undefined, origKlass), | |
| addGetter: CORE._addGetter.bind(undefined, origKlass), | |
| addSetter: CORE._addSetter.bind(undefined, origKlass), | |
| rewriteAccessor: CORE._rewriteAccessor.bind(undefined, origKlass), | |
| rewriteGetter: CORE._rewriteGetter.bind(undefined, origKlass), | |
| rewriteSetter: CORE._rewriteSetter.bind(undefined, origKlass), | |
| extendFunc: MZ_EC.extendFunc.bind(undefined, origKlass, container), | |
| rewriteFunc: MZ_EC.rewriteFunc.bind(undefined, origKlass, container) | |
| }; | |
| }; // MZ_EC.makeKlassContainer | |
| // Search tag: Enhanced_Codebase_Extend_Rewrite_Funcs | |
| MZ_EC.extendFunc = (origKlass, pluginContainer, funcName, func) => { | |
| pluginContainer.orig[funcName] = origKlass[funcName]; | |
| pluginContainer.new[funcName] = origKlass[funcName] = func; | |
| }; // MZ_EC.extendFunc | |
| // | |
| // It has the same implementations but different meanings on the callers | |
| MZ_EC.rewriteFunc = MZ_EC.extendFunc; | |
| // | |
| MZ_EC.IS_VALID_VAL = val => val !== null && val !== undefined; | |
| MZ_EC.TO_PASCAL_CASE = camelCase => { | |
| return camelCase[0].toUpperCase() + camelCase.slice(0); | |
| }; // MZ_EC.TO_PASCAL_CASE | |
| const CORE = MZ_EC.CORE = {}; | |
| // Search tag: Enhanced_Codebase_Add_Accessors | |
| CORE._addAccessor = (origKlass, accessorName, getFunc, setFunc) => { | |
| Object.defineProperty(origKlass, accessorName, { | |
| get: getFunc, | |
| set: setFunc, | |
| configurable: true | |
| }); | |
| }; // CORE._addAccessor | |
| // | |
| CORE._addGetter = (origKlass, getterName, getFunc) => { | |
| Object.defineProperty(origKlass, getterName, { | |
| get: getFunc, | |
| configurable: true | |
| }); | |
| }; // CORE._addGetter | |
| CORE._addSetter = (origKlass, setterName, setFunc) => { | |
| Object.defineProperty(origKlass, setterName, { | |
| set: setFunc, | |
| configurable: true | |
| }); | |
| }; // CORE._addSetter | |
| // They've the same implementations but different meanings on the callers | |
| CORE._rewriteAccessor = CORE._addAccessor; | |
| CORE._rewriteGetter = CORE._addGetter; | |
| CORE._rewriteSetter = CORE._addSetter; | |
| // | |
| // They must be placed here or the notetag pairs of other plugins won't work | |
| MZ_EC.BOOL_SUFFIXES = ["val", "switch", "script"]; | |
| MZ_EC.VAL_SUFFIXES = ["val", "var", "script"]; | |
| MZ_EC.EVENT_SUFFIXES = ["event", "script"]; | |
| [MZ_EC.BOOL_ENTRY, MZ_EC.BOOL_ARRAY_ENTRY] = ["bool", "boolArray"]; | |
| [MZ_EC.NUM_ENTRY, MZ_EC.NUM_ARRAY_ENTRY] = ["num", "numArray"]; | |
| [MZ_EC.STRING_ENTRY, MZ_EC.STRING_ARRAY_ENTRY] = ["string", "stringArray"]; | |
| // | |
| CORE._BOOL_VAL = entry => entry === "true" || entry !== "false"; | |
| CORE._ARRAY_VAL_SEPARATOR = "|", CORE._BOOL_ARRAY_VAL = entry => { | |
| return entry.split(CORE._ARRAY_VAL_SEPARATOR).fastMap(CORE._BOOL_VAL); | |
| }; // CORE._BOOL_ARRAY_VAL | |
| CORE._NUM_ARRAY_VAL = entry => { | |
| return entry.split(CORE._ARRAY_VAL_SEPARATOR).fastMap(Number); | |
| }; // CORE._NUM_ARRAY_VAL | |
| CORE._STRING_VAL = entry => entry; | |
| CORE._STRING_ARRAY_VAL = entry => entry.split(CORE._ARRAY_VAL_SEPARATOR); | |
| CORE._RETURNED_ENTRY_VAL = (notePairs, notetagType, entry, count) => { | |
| // There's not enough context to throw errors meaningfully | |
| if (!notePairs.has(notetagType)) return CORE._STRING_VAL; | |
| switch (notePairs.get(notetagType).get(`entry${count}`)) { | |
| // There's not enough context to throw errors meaningfully | |
| case MZ_EC.BOOL_ENTRY: return CORE._BOOL_VAL.bind(undefined, entry); | |
| case MZ_EC.BOOL_ARRAY_ENTRY: { | |
| return CORE._BOOL_ARRAY_VAL.bind(undefined, entry); | |
| } case MZ_EC.NUM_ENTRY: return Number.bind(undefined, entry); | |
| case MZ_EC.NUM_ARRAY_ENTRY: { | |
| return CORE._NUM_ARRAY_VAL.bind(undefined, entry); | |
| } case MZ_EC.STRING_ENTRY: { | |
| return CORE._STRING_VAL.bind(undefined, entry); | |
| } case MZ_EC.STRING_ARRAY_ENTRY: { | |
| return CORE._STRING_ARRAY_VAL.bind(undefined, entry); | |
| } default: return CORE._STRING_VAL.bind(undefined, entry); | |
| // | |
| } | |
| }; // CORE._RETURNED_ENTRY_VAL | |
| CORE._RETURNED_ENTRY_SWITCH = entry => { | |
| const switchId = +entry; | |
| return () => $gameSwitches.value(switchId); | |
| }; // CORE._RETURNED_ENTRY_SWITCH | |
| CORE._RETURNED_ENTRY_VAR = entry => { | |
| const varId = +entry; | |
| return () => $gameVariables.value(varId); | |
| }; // CORE._RETURNED_ENTRY_VAR | |
| // The script function will be reloaded upon setting the variables anyway | |
| CORE._RETURNED_ENTRY_SCRIPT = () => () => {}; | |
| // | |
| CORE._ENTRY_EVENT = entry => { | |
| const eventId = +entry; | |
| return () => { | |
| /** @todo Verifies whether running common events instantly's safe */ | |
| $gameTemp.reserveCommonEvent(eventId); | |
| const interpreter = new Game_Interpreter(); | |
| interpreter.clear(); | |
| interpreter.setupReservedCommonEvent(); | |
| interpreter.update(); | |
| // | |
| }; | |
| }; // CORE._ENTRY_EVENT | |
| CORE._SUFFIX_ENTRY_FUNC = function(notePairs, notetagType, suffix, entry, count) { | |
| switch (suffix) { | |
| case "val": return CORE._RETURNED_ENTRY_VAL( | |
| notePairs, notetagType, entry, count); | |
| case "switch": return CORE._RETURNED_ENTRY_SWITCH(entry); | |
| case "var": return CORE._RETURNED_ENTRY_VAR(entry); | |
| case "script": return CORE._RETURNED_ENTRY_SCRIPT(); | |
| case "event": return CORE._ENTRY_EVENT(entry); | |
| // There's not enough context to throw errors meaningfully | |
| default: return CORE._STRING_VAL; | |
| // | |
| } | |
| }; // CORE._SUFFIX_ENTRY_FUNC | |
| CORE._IS_VALID_SUFFIX = (notePairs, notetagType, suffix, count) => { | |
| const notetagTypePairs = notePairs.get(notetagType); | |
| const suffixName = `suffix${count}`; | |
| if (!notetagTypePairs.has(suffixName)) return false; | |
| return notetagTypePairs.get(suffixName).includes(suffix); | |
| }; // CORE._IS_VALID_SUFFIX | |
| CORE._SHOW_INVALID_NOTE_SUFFIX = (datumType, id, count, suffix, line) => { | |
| console.warn(`A ${datumType} data with id ${id} | |
| has the invalid ${count}th suffix ${suffix} | |
| in notetag ${line}`); | |
| }; // CORE._SHOW_INVALID_NOTE_SUFFIX | |
| CORE._NOTETAG_PAIRS = (container, notePairs, line, notetagType, suffixes, entries) => { | |
| // So those excessive suffixes/entries will be discarded right here | |
| const pairs = new Map(), l = Math.min(suffixes.length, entries.length); | |
| // | |
| let i = 0; | |
| // It's tolerable and more performant than any declarative counterpart | |
| while (i < l) { // while is at least slightly faster than for in general | |
| const suffix = suffixes[i], entry = entries[i], count = i + 1; | |
| if (CORE._IS_VALID_SUFFIX(notePairs, notetagType, suffix, count)) { | |
| // suffixes and entries are still stored to handle dynamic data | |
| pairs.set(`suffix${count}`, suffix); | |
| pairs.set(`entry${count}`, entry); | |
| // | |
| pairs.set(`func${count}`, CORE._SUFFIX_ENTRY_FUNC( | |
| notePairs, notetagType, suffix, entry, count)); | |
| } else CORE._SHOW_INVALID_NOTE_SUFFIX( | |
| container.datumType, container.id, count, suffix, line); | |
| i++; | |
| } | |
| return pairs; | |
| // | |
| }; // CORE._NOTETAG_PAIRS | |
| CORE._ON_LOAD_NOTETAG_PAIRS = (container, notePairs, line, notetagType, suffixes, entries) => { | |
| const pairs = CORE._NOTETAG_PAIRS( | |
| container, notePairs, line, notetagType, suffixes, entries); | |
| // push is much faster than concat and pairs isn't an array | |
| container.notetags.push({ notetagType, pairs }); | |
| // | |
| }; // CORE._ON_LOAD_NOTETAG_PAIRS | |
| CORE._REG_EXP_SUFFIX_SEPARATOR = " +", CORE._REG_EXP_SUFFIX_SEPARATOR_OBJ = | |
| new RegExp(CORE._REG_EXP_SUFFIX_SEPARATOR); | |
| CORE._REG_EXP_ENTRY_SEPARATOR = " *, +"; | |
| CORE._REG_EXP_ENTRY_SEPARATOR_OBJ = | |
| new RegExp(CORE._REG_EXP_ENTRY_SEPARATOR); | |
| CORE._SHOW_INVALID_NOTE_TYPE = (datumType, id, noteType, line) => { | |
| console.warn(`A ${datumType} data with id ${id} | |
| has the invalid type ${noteType} in notetag ${line}`); | |
| }; // CORE._SHOW_INVALID_NOTE_TYPE | |
| CORE._ON_LOAD_DATUM_NOTETAG = (container, fullRegex, notePairs, line) => { | |
| if (!line.match(fullRegex)) return; | |
| const notetagType = RegExp.$1; | |
| if (!notePairs.has(notetagType)) return CORE._SHOW_INVALID_NOTE_TYPE( | |
| container.datumType, container.id, notetagType, line); | |
| // Otherwise split would corrupt RegExp.$2 and RegExp.$3 | |
| const rawSuffixes = RegExp.$2, rawEntries = RegExp.$3; | |
| const suffixes = rawSuffixes.split(CORE._REG_EXP_SUFFIX_SEPARATOR_OBJ); | |
| const entries = rawEntries.split(CORE._REG_EXP_ENTRY_SEPARATOR_OBJ); | |
| // | |
| CORE._ON_LOAD_NOTETAG_PAIRS( | |
| container, notePairs, line, notetagType, suffixes, entries); | |
| // | |
| }; // CORE._ON_LOAD_DATUM_NOTETAG | |
| CORE._REG_EXP_SPLIT_NOTES = /[\r\n]+/; | |
| CORE._ON_LOAD_DATUM_NOTETAGS = (datumType, datum, containerName, fullRegex, notePairs) => { | |
| const { meta } = datum; | |
| meta.enhancedCodebase = meta.enhancedCodebase || {}; | |
| // Storing datumType is to streamline the notetag datum type reading | |
| const container = meta.enhancedCodebase[containerName] = { | |
| id: datum.id, | |
| datumType, | |
| notetags: [] | |
| }, lines = datum.note.split(CORE._REG_EXP_SPLIT_NOTES); | |
| // | |
| lines.forEach(line => { | |
| CORE._ON_LOAD_DATUM_NOTETAG(container, fullRegex, notePairs, line); | |
| }); | |
| }; // CORE._ON_LOAD_DATUM_NOTETAGS | |
| CORE._REG_EXP_PREFIX = "\\s*(?:doublex\\s+rmmz\\s+)?"; | |
| CORE._REG_EXP_SUFFIXES = "\\s+(\\w+)\\s+(\\w+(?:" + | |
| CORE._REG_EXP_SUFFIX_SEPARATOR + "\\w+)*)\\s*"; | |
| // So alphanumeric characters as well as numbers with decimals are captured | |
| CORE.REG_EXP_ENTRY_VAL = "[\\/A-Za-z\\d_\\.\\+\\-\\*%=]+"; | |
| // The / is captured as well to support filepath strings | |
| CORE._REG_EXP_ENTRIES = " *(" + CORE.REG_EXP_ENTRY_VAL + "(?:" + | |
| CORE._REG_EXP_ENTRY_SEPARATOR + CORE.REG_EXP_ENTRY_VAL + ")*)\\s*"; | |
| CORE._FULL_REG_EXP = baseRegex => { | |
| return new RegExp("<" + CORE._REG_EXP_PREFIX + baseRegex + | |
| CORE._REG_EXP_SUFFIXES + ":" + CORE._REG_EXP_ENTRIES + ">", | |
| "gim"); | |
| }; // CORE._FULL_REG_EXP | |
| MZ_EC.onLoadDataNotetags = (obj, datumType, baseRegex, notePairs, containerName = baseRegex) => { | |
| const fullRegex = CORE._FULL_REG_EXP(baseRegex); | |
| console.info("MZ_EC.onLoadDataNotetags fullRegex", fullRegex); | |
| obj.forEach(datum_ => { | |
| if (datum_) CORE._ON_LOAD_DATUM_NOTETAGS( | |
| datumType, datum_, containerName, fullRegex, notePairs); | |
| }); | |
| }; // MZ_EC.onLoadDataNotetags | |
| CORE._IS_RELOAD_DATA_NOTETAG_PAIRS = (pairs, count, varId) => { | |
| if (pairs.get(`suffix${count}`) !== "script") return false; | |
| return +pairs.get(`entry${count}`) === varId; | |
| }; // CORE._IS_RELOAD_DATA_NOTETAG_PAIRS | |
| CORE._RELOAD_DATA_NOTETAG_PAIRS = (varId, val, pairs) => { | |
| let count = 1; | |
| while (pairs.has(`func${count}`)) { | |
| if (CORE._IS_RELOAD_DATA_NOTETAG_PAIRS(pairs, count, varId)) { | |
| pairs.set(`func${count}`, new Function("argObj", val)); | |
| // It's a cheap idempotent operation so it's ok to call it here | |
| MZ_EC.clearAllBattlerNotetagCaches(); | |
| // | |
| } | |
| count++; | |
| } | |
| }; // MZ_EC._RELOAD_DATA_NOTETAG_PAIRS | |
| MZ_EC.updateDataNotetags = (obj, containerName, varId, val) => { | |
| obj.forEach(datum_ => { | |
| if (!datum_) return; | |
| const { enhancedCodebase } = datum_.meta; | |
| enhancedCodebase[containerName].notetags.forEach(({ pairs }) => { | |
| CORE._RELOAD_DATA_NOTETAG_PAIRS(varId, val, pairs); | |
| }); | |
| }); | |
| }; // MZ_EC.updateDataNotetags | |
| CORE._battlerNotetagCache = new Map(); | |
| CORE._BATTLER_CACHE_KEY = battler => { | |
| if (battler.isActor()) return `{"id":${battler.actorId()}}`; | |
| if (battler.isEnemy()) return `{"i":${battler.index()}}`; | |
| return ""; | |
| }; // CORE._BATTLER_CACHE_KEY | |
| CORE._ARRAY_CACHE_KEY = JSON.stringify; | |
| CORE._ACTOR_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? [battler.actor()] : []; | |
| }; // CORE._ACTOR_NOTETAG_DATA | |
| CORE._CLASS_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? [battler.currentClass()] : []; | |
| }; // CORE._CLASS_NOTETAG_DATA | |
| CORE._ACT_DATA_SKILL = ({ skillId }) => $dataSkills[skillId]; | |
| CORE._SKILLS_NOTETAG_DATA = battler => { | |
| if (battler.isActor()) return battler.skills(); | |
| if (!battler.isEnemy()) return []; | |
| return battler.enemy().actions.fastMap(CORE._ACT_DATA_SKILL); | |
| }; // CORE._SKILLS_NOTETAG_DATA | |
| CORE._USABLE_SKILLS_NOTETAG_DATA = battler => { | |
| if (battler.isActor()) return battler.usableSkills(); | |
| if (!battler.isEnemy()) return []; | |
| const EC_GE = MZ_EC.Game_Enemy.new; | |
| return EC_GE._validActs.call(battler).fastMap(CORE._ACT_DATA_SKILL); | |
| }; // CORE._USABLE_SKILLS_NOTETAG_DATA | |
| CORE._ITEMS_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? $gameParty.items() : []; | |
| }; // CORE._ITEMS_NOTETAG_DATA | |
| CORE._USABLE_ITEMS_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? $gameParty.items().fastMap(item => { | |
| return battler.canUse(item); | |
| }) : []; | |
| }; // CORE._USABLE_ITEMS_NOTETAG_DATA | |
| CORE._LATEST_SKILL_ITEM_NOTETAG_DATA = battler => { | |
| if (battler.latestSkillItems) return battler.latestSkillItems; | |
| const curAct = battler.currentAction(); | |
| return curAct && curAct.item() ? [curAct.item()] : []; | |
| }; // CORE._LATEST_SKILL_ITEM_NOTETAG_DATA | |
| CORE._WEAPONS_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? battler.weapons() : []; | |
| }; // CORE._WEAPONS_NOTETAG_DATA | |
| CORE._ARMORS_NOTETAG_DATA = battler => { | |
| return battler.isActor() ? battler.armors() : []; | |
| }; // CORE._ARMORS_NOTETAG_DATA | |
| CORE._ENEMIES_NOTETAG_DATA = battler => { | |
| return battler.isEnemy() ? [battler.enemy()] : []; | |
| }; // CORE._ENEMIES_NOTETAG_DATA | |
| CORE._STATES_NOTETAG_DATA = battler => battler.states(); | |
| CORE._THIS_STATE_NOTETAG_DATA = battler => { | |
| return battler.thisState ? [battler.thisState] : []; | |
| }; // CORE._THIS_STATE_NOTETAG_DATA | |
| CORE._NOTETAG_DATA = (battler, dataType) => { | |
| switch (dataType) { | |
| case "actor": return CORE._ACTOR_NOTETAG_DATA(battler); | |
| case "class": return CORE._CLASS_NOTETAG_DATA(battler); | |
| case "skills": return CORE._SKILLS_NOTETAG_DATA(battler); | |
| case "usableSkills": { | |
| return CORE._USABLE_SKILLS_NOTETAG_DATA(battler); | |
| } | |
| case "items" : return CORE._ITEMS_NOTETAG_DATA(battler); | |
| case "usableItems" : { | |
| return CORE._USABLE_ITEMS_NOTETAG_DATA(battler); | |
| } | |
| case "latestSkillItem": { | |
| return CORE._LATEST_SKILL_ITEM_NOTETAG_DATA(battler); | |
| } | |
| case "weapons" : return CORE._WEAPONS_NOTETAG_DATA(battler); | |
| case "armors" : return CORE._ARMORS_NOTETAG_DATA(battler); | |
| case "enemy" : return CORE._ENEMIES_NOTETAG_DATA(battler); | |
| case "states" : return CORE._STATES_NOTETAG_DATA(battler); | |
| case "thisState" : return CORE._THIS_STATE_NOTETAG_DATA(battler); | |
| // There's not enough context to throw errors meaningfully | |
| default: return []; | |
| // | |
| } | |
| }; // CORE._NOTETAG_DATA | |
| CORE._IS_VALID_DATUM = datum => datum; | |
| CORE._DATA_NOTETAGS = (battler, dataType, containerName) => { | |
| const notetagData = CORE._NOTETAG_DATA(battler, dataType); | |
| const validNotetagData = notetagData.filter(CORE._IS_VALID_DATUM); | |
| return validNotetagData.reduce((notes, { meta }) => { | |
| const { enhancedCodebase } = meta; | |
| return notes.fastMerge(enhancedCodebase[containerName].notetags); | |
| }, []); | |
| }; // CORE._DATA_NOTETAGS | |
| CORE._NEW_LIST_CONTAINER = notetagList => new Map(Object.entries({ | |
| list: notetagList | |
| })); // CORE._NEW_LIST_CONTAINER | |
| CORE._NEW_NOTETAG_LIST_CONTAINER = (containerName, notetagList) => { | |
| return new Map(Object.entries({ | |
| [containerName]: CORE._NEW_LIST_CONTAINER(notetagList) | |
| })); | |
| }; // CORE._NEW_NOTETAG_LIST_CONTAINER | |
| CORE._NEW_BATTLER_NOTETAG_LIST_CACHE = (priorityKey, containerName, notetagList) => { | |
| return new Map(Object.entries({ | |
| [priorityKey]: CORE._NEW_NOTETAG_LIST_CONTAINER( | |
| containerName, notetagList) | |
| })); | |
| }; // CORE._NEW_BATTLER_NOTETAG_LIST_CACHE | |
| CORE._CACHE_BATTLER_NOTETAG_LIST = (battler, priorities, containerName, notetagList) => { | |
| const battlerKey = CORE._BATTLER_CACHE_KEY(battler); | |
| if (!battlerKey) return; | |
| const priorityKey = CORE._ARRAY_CACHE_KEY(priorities); | |
| if (!CORE._battlerNotetagCache.has(battlerKey)) { | |
| const newBattlerNotetagCache = CORE._NEW_BATTLER_NOTETAG_LIST_CACHE( | |
| priorityKey, containerName, notetagList); | |
| return CORE._battlerNotetagCache.set( | |
| battlerKey, newBattlerNotetagCache); | |
| } | |
| const battlerNotetagCache = CORE._battlerNotetagCache.get(battlerKey); | |
| if (!battlerNotetagCache.has(priorityKey)) { | |
| return battlerNotetagCache.set(priorityKey, CORE. | |
| _NEW_NOTETAG_LIST_CONTAINER(containerName, notetagList)); | |
| } | |
| const battlerNotetagContainerCache = | |
| battlerNotetagCache.get(priorityKey); | |
| const list = CORE._NEW_LIST_CONTAINER(notetagList); | |
| battlerNotetagContainerCache.set(containerName, list); | |
| }; // CORE._CACHE_BATTLER_NOTETAG_LIST | |
| CORE._NOTETAG_WITH_TYPES = (notetags, notetagTypes_) => { | |
| // Not cloning the cached list can end up mutating the cache unknowingly | |
| return notetagTypes_ ? notetags.filter(({ notetagType }) => { | |
| return notetagTypes_.includes(notetagType); | |
| }) : notetags.clone(); | |
| // | |
| }; // CORE._NOTETAG_WITH_TYPES | |
| CORE._NEW_NOTETAG_LIST = (battler, priorities, containerName, notetagTypes_) => { | |
| // Cache the whole notetag list regardless of notetagTypes_ | |
| const notetagList = priorities.reduce((notetags, dataType) => { | |
| return notetags.fastMerge( | |
| CORE._DATA_NOTETAGS(battler, dataType, containerName)); | |
| }, []); | |
| CORE._CACHE_BATTLER_NOTETAG_LIST( | |
| battler, priorities, containerName, notetagList); | |
| // | |
| // Only returns the needed parts of the whole cached notetag list | |
| return CORE._NOTETAG_WITH_TYPES(notetagList, notetagTypes_); | |
| // | |
| }; // CORE._NEW_NOTETAG_LIST | |
| CORE._BATTLER_NOTETAG_CACHE_LIST_CONTAINER = (battlerNotetagContainerCache, containerName, notetagTypes_) => { | |
| if (!battlerNotetagContainerCache.has(containerName)) return undefined; | |
| const container = battlerNotetagContainerCache.get(containerName); | |
| // | |
| // Only returns the needed parts of the whole cached notetag list | |
| return CORE._NOTETAG_WITH_TYPES(container.get("list"), notetagTypes_); | |
| // | |
| }; // CORE._BATTLER_NOTETAG_CACHE_LIST_CONTAINER | |
| CORE._CACHED_BATTLER_NOTETAG_LIST = (battler, priorities, containerName, notetagTypes_) => { | |
| const battlerKey = CORE._BATTLER_CACHE_KEY(battler); | |
| if (!CORE._battlerNotetagCache.has(battlerKey)) return undefined; | |
| const battlerNotetagCache = CORE._battlerNotetagCache.get(battlerKey); | |
| const priorityKey = CORE._ARRAY_CACHE_KEY(priorities); | |
| if (!battlerNotetagCache.has(priorityKey)) return undefined; | |
| const battlerNotetagContainerCache = | |
| battlerNotetagCache.get(priorityKey); | |
| return CORE._BATTLER_NOTETAG_CACHE_LIST_CONTAINER( | |
| battlerNotetagContainerCache, containerName, notetagTypes_); | |
| }; // CORE._CACHED_BATTLER_NOTETAG_LIST | |
| MZ_EC.notetags = (battler, priorities, containerName, notetagTypes_) => { | |
| const cachedNotetagList_ = CORE._CACHED_BATTLER_NOTETAG_LIST( | |
| battler, priorities, containerName, notetagTypes_); | |
| if (MZ_EC.IS_VALID_VAL(cachedNotetagList_)) return cachedNotetagList_; | |
| return CORE._NEW_NOTETAG_LIST( | |
| battler, priorities, containerName, notetagTypes_); | |
| }; // MZ_EC.notetags | |
| CORE._accumCondOpValNotetagVal = function(accumVal, { pairs }) { | |
| // condFunc | |
| if (!pairs.has("func1")) return accumVal; | |
| if (!pairs.get("func1").call(this)) return accumVal; | |
| // | |
| // opFunc and valFunc | |
| if (!pairs.has("func2") || !pairs.has("func3")) return accumVal; | |
| const val = pairs.get("func3").call(this); | |
| switch(pairs.get("func2").call(this)) { | |
| case "+": return accumVal + val; | |
| case "-": return accumVal - val; | |
| case "*": return accumVal * val; | |
| case "/": return accumVal / val; | |
| case "%": return accumVal % val; | |
| case "=": return val; | |
| // There's not enough context to throw errors meaningfully | |
| default: return accumVal; | |
| // | |
| } | |
| // | |
| }; // CORE._accumCondOpValNotetagVal | |
| CORE._NEW_INIT_VAL_CONTAINER = (initVal, notetagVal) => { | |
| return new Map(Object.entries({ [initVal]: notetagVal })); | |
| }; // CORE._NEW_INIT_VAL_CONTAINER | |
| CORE._NEW_NOTETAG_TYPE_VAL_CONTAINER = (notetagTypeKey, initVal, notetagVal) => { | |
| return new Map(Object.entries({ | |
| [notetagTypeKey]: CORE._NEW_INIT_VAL_CONTAINER(initVal, notetagVal) | |
| })); | |
| }; // CORE._NEW_NOTETAG_TYPE_VAL_CONTAINER | |
| CORE._CACHE_BATTLER_NOTETAG_VAL = (battler, priorities, containerName, notetagTypes_, initVal, notetagVal) => { | |
| const battlerKey = CORE._BATTLER_CACHE_KEY(battler); | |
| if (!battlerKey) return; | |
| const priorityKey = CORE._ARRAY_CACHE_KEY(priorities); | |
| const notetagTypeKey = CORE._ARRAY_CACHE_KEY(notetagTypes_); | |
| // CORE._CACHE_BATTLER_NOTETAG_LIST must be run before running this | |
| const battlerNotetagCache = CORE._battlerNotetagCache.get(battlerKey); | |
| const battlerNotetagValCache = | |
| battlerNotetagCache.get(priorityKey).get(containerName); | |
| // | |
| if (!battlerNotetagValCache.has("val")) { | |
| const notetagTypeCache = CORE._NEW_NOTETAG_TYPE_VAL_CONTAINER( | |
| notetagTypeKey, initVal, notetagVal); | |
| return battlerNotetagValCache.set("val", notetagTypeCache); | |
| } | |
| const battlerNotetagTypeCache = battlerNotetagValCache.get("val"); | |
| if (!battlerNotetagTypeCache.has(notetagTypeKey)) { | |
| const initValCache = | |
| CORE._NEW_INIT_VAL_CONTAINER(initVal, notetagVal); | |
| return battlerNotetagTypeCache.set(notetagTypeKey, initValCache); | |
| } | |
| battlerNotetagTypeCache.get(notetagTypeKey).set(initVal, notetagVal); | |
| }; // CORE._CACHE_BATTLER_NOTETAG_VAL | |
| CORE._NEW_COND_OP_VAL_NOTETAG_VAL = (battler, priorities, containerName, notetagTypes_, initVal) => { | |
| const notetags = MZ_EC.notetags( | |
| battler, priorities, containerName, notetagTypes_); | |
| const notetagVal = notetags.reduce( | |
| CORE._accumCondOpValNotetagVal, initVal, battler); | |
| CORE._CACHE_BATTLER_NOTETAG_VAL(battler, priorities, containerName, | |
| notetagTypes_, initVal, notetagVal); | |
| return notetagVal; | |
| }; // CORE._NEW_COND_OP_VAL_NOTETAG_VAL | |
| CORE._BATTLER_NOTETAG_CACHE_VAL_CONTAINER = (battlerNotetagContainerCache, containerName, notetagTypes_, initVal) => { | |
| if (!battlerNotetagContainerCache.has(containerName)) return undefined; | |
| const container = battlerNotetagContainerCache.get(containerName); | |
| const notetagTypes = container.get("val"); | |
| if (notetagTypes_) { | |
| const notetagTypeKey = CORE._ARRAY_CACHE_KEY(notetagTypes_); | |
| if (!notetagTypes.has(notetagTypeKey)) return undefined; | |
| return notetagTypes.get(notetagTypeKey).get(initVal); | |
| } | |
| return notetagTypes.get("allNotetags").get(initVal); | |
| }; // CORE._BATTLER_NOTETAG_CACHE_VAL_CONTAINER | |
| CORE._CACHED_BATTLER_NOTETAG_VAL = (battler, priorities, containerName, notetagTypes_, initVal) => { | |
| const battlerKey = CORE._BATTLER_CACHE_KEY(battler); | |
| if (!CORE._battlerNotetagCache.has(battlerKey)) return undefined; | |
| const battlerNotetagCache = CORE._battlerNotetagCache.get(battlerKey); | |
| const priorityKey = CORE._ARRAY_CACHE_KEY(priorities); | |
| if (!battlerNotetagCache.has(priorityKey)) return undefined; | |
| const battlerNotetagContainerCache = | |
| battlerNotetagCache.get(priorityKey); | |
| return CORE._BATTLER_NOTETAG_CACHE_VAL_CONTAINER( | |
| battlerNotetagContainerCache, containerName, notetagTypes_, initVal); | |
| }; // CORE._CACHED_BATTLER_NOTETAG_VAL | |
| MZ_EC.condOpValNotetagVal = (battler, priorities, containerName, notetagTypes_, initVal) => { | |
| const cachedNotetagVal_ = CORE._CACHED_BATTLER_NOTETAG_VAL( | |
| battler, priorities, containerName, notetagTypes_, initVal); | |
| if (MZ_EC.IS_VALID_VAL(cachedNotetagVal_)) return cachedNotetagVal_; | |
| return CORE._NEW_COND_OP_VAL_NOTETAG_VAL( | |
| battler, priorities, containerName, notetagTypes_, initVal); | |
| }; // MZ_EC.condOpValNotetagVal | |
| CORE._accumCondOpNotetagVal = function(accumVal, { pairs }) { | |
| // condFunc and opFunc | |
| if (!pairs.has("func1") || !pairs.has("func2")) return accumVal; | |
| // | |
| const cond = pairs.get("func1").call(this); | |
| // The opFunc shouldn't be used at the beginning of the cond op chain | |
| if (!MZ_EC.IS_VALID_VAL(accumVal)) return cond; | |
| // | |
| switch(pairs.get("func2").call(this).toUpperCase()) { | |
| case "AND": return accumVal && cond; | |
| case "OR": return accumVal || cond; | |
| case "NAND": return !accumVal || !cond; | |
| case "NOR": return !accumVal && !cond; | |
| case "XOR": return accumVal !== cond; | |
| case "XNOR": return accumVal === cond; | |
| case "SET": return cond; | |
| // There's not enough context to throw errors meaningfully | |
| default: return accumVal; | |
| // | |
| } | |
| }; // CORE._accumCondOpNotetagVal | |
| CORE._NEW_COND_OP_NOTETAG_VAL = (battler, priorities, containerName, notetagTypes_, initVal) => { | |
| const notetags = MZ_EC.notetags( | |
| battler, priorities, containerName, notetagTypes_); | |
| const notetagVal = notetags.reduce( | |
| CORE._accumCondOpNotetagVal, initVal, battler); | |
| CORE._CACHE_BATTLER_NOTETAG_VAL(battler, priorities, containerName, | |
| notetagTypes_, initVal, notetagVal); | |
| return notetagVal; | |
| }; // CORE._NEW_COND_OP_NOTETAG_VAL | |
| MZ_EC.condOpNotetagVal = (battler, priorities, containerName, notetagTypes_, initVal = undefined) => { | |
| const cachedNotetagVal_ = CORE._CACHED_BATTLER_NOTETAG_VAL( | |
| battler, priorities, containerName, notetagTypes_, initVal); | |
| if (MZ_EC.IS_VALID_VAL(cachedNotetagVal_)) return cachedNotetagVal_; | |
| return CORE._NEW_COND_OP_NOTETAG_VAL( | |
| battler, priorities, containerName, notetagTypes_, initVal); | |
| }; // MZ_EC.condOpNotetagVal | |
| MZ_EC.runCondEventNotetags = (battler, priorities, containerName, notetagTypes_) => { | |
| const notetags = MZ_EC.notetags( | |
| battler, priorities, containerName, notetagTypes_); | |
| notetags.forEach(({ pairs }) => { | |
| if (!pairs.has("func1") || !pairs.has("func2")) return; | |
| if (!pairs.get("func1").call(battler)) return; | |
| pairs.get("func2").call(battler); | |
| }); | |
| }; // MZ_EC.runCondEventNotetags | |
| MZ_EC.clearAllBattlerNotetagCaches = () => { | |
| CORE._battlerNotetagCache.clear(); | |
| }; // MZ_EC.clearAllBattlerNotetagCaches | |
| MZ_EC.clearBattlerNotetagCache = (battler, containerName_) => { | |
| const battlerKey = CORE._BATTLER_CACHE_KEY(battler); | |
| if (!CORE._battlerNotetagCache.has(battlerKey)) return; | |
| if (!containerName_) { | |
| return CORE._battlerNotetagCache.delete(battlerKey); | |
| } | |
| CORE._battlerNotetagCache.get(battlerKey).forEach((container) => { | |
| container.delete(containerName_); | |
| }); | |
| }; // MZ_EC.clearBattlerNotetagCache | |
| // This unused function's here just to show that this idea doesn't work | |
| MZ_EC.runSparseNotetagResults = function(notetagName, paramFunc, containerName, dataName, newData, notetagTypeFunc) { | |
| const suffix = "NotetagDataTypePriorities"; | |
| const types = $gameSystem[paramFunc](`${notetagName}${suffix}`); | |
| MZ_EC.clearBattlerNotetagCache(this, containerName); | |
| const oldData = this[dataName]; | |
| this[dataName] = newData; | |
| MZ_EC[notetagTypeFunc](this, types, containerName, [notetagName]); | |
| this[dataName] = oldData; | |
| MZ_EC.clearBattlerNotetagCache(this, containerName); | |
| }; // MZ_EC.runNotetagResults | |
| // | |
| })(DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| (MZ_EC => { | |
| "use strict"; | |
| MZ_EC.setupFuncParams = (pluginName, paramFuncArgs) => { | |
| const FP = pluginName.FUNC_PARAMS = {}; | |
| FP.PARAM_FUNCS = new Map(); | |
| FP._PARAM_FUNC_ARGS = new Map(Object.entries(paramFuncArgs)); | |
| FP.storeFuncParam = (param, val) => { | |
| if (!FP._PARAM_FUNC_ARGS.has(param)) return; | |
| const args = FP._PARAM_FUNC_ARGS.get(param); | |
| // Using fastMerge would mutate the parameter function argument list | |
| FP.PARAM_FUNCS.set(param, new Function(...args.concat(val))); | |
| // | |
| }; // FP.storeFuncParam | |
| }; // MZ_EC.setupFuncParams | |
| })(DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Core | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edit class: Object | |
| * - Adds some new array APIs | |
| *----------------------------------------------------------------------------*/ | |
| (function($, OPT) { | |
| "use strict"; | |
| /*------------------------------------------------------------------------ | |
| * New public variable | |
| *------------------------------------------------------------------------*/ | |
| // {{*}} objPropLog: The container as the object properties trace log | |
| const _DEFINE_PROP = (obj, prop, val) => { | |
| // Using Object.defineProperty is to make the property non-enumerable | |
| if (!obj[prop]) Object.defineProperty(obj, prop, { | |
| configurable: true, | |
| value: val, | |
| writable: true | |
| }); | |
| // | |
| }; // _DEFINE_PROP | |
| /** | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @enum @param {string} cond - The name of the trace condition function | |
| * @enum @param {string} label - The name of the trace label function | |
| */ | |
| _DEFINE_PROP($, "traceObjProp", function(cond, label) { | |
| _DEFINE_PROP(this, "objPropLog", {}); | |
| _DEFINE_PROP(this, "_objPropTrace", {}); | |
| // Stop tracing the object property if the path would be cyclic | |
| if (this._objPropTrace[cond]) return; | |
| // | |
| const traceCond = this._objPropTrace[cond] = {}; | |
| // Labels and uses all nonempty subtrees to form object property tree | |
| Object.entries(this).forEach(([prop, obj]) => { | |
| // Recursively traverse the property tree via Depth First Search | |
| const isNonObj = Array.isArray(obj) || typeof obj !== "object"; | |
| if (OPT[cond](obj)) { | |
| traceCond[obj] = [prop]; | |
| this.objPropLog[cond] = this.objPropLog[cond] || "{"; | |
| if (isNonObj) { | |
| this.objPropLog[cond] += ` ${prop}: ${OPT[label](obj)} `; | |
| } | |
| } | |
| if (isNonObj || obj === null) return; | |
| obj.traceObjProp(cond, label); | |
| if (Object.keys(traceCond).isEmpty()) return; | |
| traceCond[obj] = traceCond[obj] || []; | |
| traceCond[obj].push(obj._objPropTrace[cond]); | |
| if (!obj.objPropLog[cond]) return; | |
| this.objPropLog[cond] = this.objPropLog[cond] || "{"; | |
| this.objPropLog[cond] += ` ${prop}: ${obj.objPropLog[cond]} `; | |
| // | |
| }); | |
| // | |
| if (this.objPropLog[cond]) this.objPropLog[cond] += "}"; | |
| }); // traceObjProp | |
| // | |
| })(Object.prototype, DoubleX_RMMZ.Enhanced_Codebase.CFG.objPropTrace); | |
| /*---------------------------------------------------------------------------- | |
| * # Edit class: Array | |
| * - Adds some new array APIs | |
| *----------------------------------------------------------------------------*/ | |
| (function($) { | |
| "use strict"; | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> *} mapCallback - The callback in the Array | |
| * map method | |
| * @param {*?} mapThis_ - The context of mapCallback | |
| * @returns {[*]} - The fully mapped array from this | |
| */ | |
| $.fastMap = function(mapCallback, mapThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| if (typeof mapCallback !== "function") { | |
| throw new TypeError(`${mapCallback} is not a function`); | |
| } | |
| const newArray = []; | |
| // forEach is tested to be the fastest among sandboxes including NW.js | |
| this.forEach((elem, i) => { | |
| // It's ok to call undefined context with previously bound callbacks | |
| newArray.push(mapCallback.call(mapThis_, elem, i, this)); | |
| // | |
| }); | |
| // | |
| return newArray; | |
| }; // $.fastMap | |
| /** | |
| * concat array that can be changed in place will lead to needless throwaway | |
| * This method alters the original array(this) as it merges another in place | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to be merged | |
| * @returns {This} The original array merged with another array in place | |
| */ | |
| $.fastMerge = function(arr) { | |
| this.push(...arr); | |
| return this; | |
| }; // $.fastMerge | |
| /** | |
| * Chaining filter with map will lead to a new redundantly throwaway Array | |
| * This method doesn't support the thisArg argument in mapCallback | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> boolean} filterCallback - The callback in | |
| * the Array filter | |
| * method | |
| * @param {(<T>, index) -> <U>} mapCallback - The callback in the Array map | |
| * method | |
| * @param {*?} filterThis_ - The context of filterCallback | |
| * @param {*?} mapThis_ - The context of mapCallback | |
| * @returns {[<U>]} - The fully filtered then mapped array from this | |
| */ | |
| $.filterMap = function(filterCallback, mapCallback, filterThis_, mapThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| if (typeof filterCallback !== "function") { | |
| throw new TypeError(`${filterCallback} is not a function`); | |
| } else if (typeof mapCallback !== "function") { | |
| throw new TypeError(`${mapCallback} is not a function`); | |
| } | |
| const newArray = []; | |
| // forEach is tested to be the fastest among sandboxes including NW.js | |
| this.forEach((elem, i) => { | |
| // It's ok to call undefined context with previously bound callbacks | |
| if (!filterCallback.call(filterThis_, elem, i, this)) return; | |
| newArray.push(mapCallback.call(mapThis_, elem, i)); | |
| // | |
| }); | |
| // | |
| return newArray; | |
| }; // $.filterMap | |
| /** | |
| * Chaining map with filter will lead to a new redundantly throwaway Array | |
| * This method doesn't support the thisArg argument in filterCallback | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> <U>} mapCallback - The callback in the | |
| * Array map method | |
| * @param {(<U>, index) -> boolean} filterCallback - The callback in the | |
| * Array filter method | |
| * @param {*?} mapThis_ - The context of mapCallback | |
| * @param {*?} filterThis_ - The context of filterCallback | |
| * @returns {[<U>]} - The fully mapped then filtered array from this | |
| */ | |
| $.mapFilter = function(mapCallback, filterCallback, mapThis_, filterThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| if (typeof mapCallback !== "function") { | |
| throw new TypeError(`${mapCallback} is not a function`); | |
| } else if (typeof filterCallback !== "function") { | |
| throw new TypeError(`${filterCallback} is not a function`); | |
| } | |
| const newArray = []; | |
| // forEach is tested to be the fastest among sandboxes including NW.js | |
| this.forEach((elem, i) => { | |
| // It's ok to call undefined context with previously bound callbacks | |
| const mappedElem = mapCallback.call(mapThis_, elem, i, this); | |
| if (!filterCallback.call(filterThis_, mappedElem, i)) return; | |
| // | |
| newArray.push(mappedElem); | |
| }); | |
| // | |
| return newArray; | |
| }; // $.mapFilter | |
| /** | |
| * Chaining map with reduce will lead to a new redundantly throwaway Array | |
| * This method doesn't support the thisArg argument in reduceCallback | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> <U>} mapCallback - The callback in the | |
| * Array map method | |
| * @param {(<V>, <U>, index) -> <V>} reduceCallback - The callback in the | |
| * Array reduce method | |
| * @param {<V>?} initVal_ - The initial value of reduceCallback | |
| * @param {*?} mapThis_ - The context of mapCallback | |
| * @param {*?} reduceThis_ - The context of reduceCallback | |
| * @returns {<V>} - The fully mapped then reduced result from this | |
| */ | |
| $.mapReduce = function(mapCallback, reduceCallback, initVal_, mapThis_, reduceThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| const l = this.length, hasInitVal = initVal_ !== undefined; | |
| if (typeof mapCallback !== "function") { | |
| throw new TypeError(`${mapCallback} is not a function`); | |
| } else if (typeof reduceCallback !== "function") { | |
| throw new TypeError(`${reduceCallback} is not a function`); | |
| } else if (l <= 0 && !hasInitVal) { | |
| throw new TypeError("Reduce of empty array with no initial value"); | |
| } | |
| if (hasInitVal) { | |
| let val = initVal_; | |
| // forEach is tested to be fastest among sandboxes including NW.js | |
| this.forEach((elem, i) => { | |
| // It's ok to call undefined context with already bound callback | |
| const mappedElem = mapCallback.call(mapThis_, elem, i, this); | |
| val = reduceCallback.call(reduceThis_, val, mappedElem, i); | |
| // | |
| }); | |
| // | |
| return val; | |
| } | |
| /** @todo Uses forEach without checking if (i === 0) to be faster */ | |
| let val = this[0], i = 1; | |
| while (i < l) { | |
| // It's ok to call undefined context with already bound callback | |
| const mappedElem = mapCallback.call(mapThis_, this[i], i, this); | |
| val = reduceCallback.call(reduceThis_, val, mappedElem, i); | |
| // | |
| i++; | |
| } | |
| // | |
| return val; | |
| }; // $.mapReduce | |
| /** | |
| * This method erases the passed element(if any) from this original array | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {*} elem - Element(if any) to be erased from this original array | |
| * @returns {This} This original array with passed element(if any) erased | |
| */ | |
| $.eraseElem = function(elem) { | |
| const i = this.indexOf(elem); | |
| if (i >= 0) this.splice(i, 1); | |
| return this; | |
| }; // $.eraseElem | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> boolean} splitCallback - The callback in | |
| * the Array split | |
| * method | |
| * @param {*?} splitThis_ - The context of splitCallback | |
| * @returns {[[<T>]]} - The fully splitted array from this | |
| */ | |
| $.split = function(splitCallback, splitThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| if (typeof splitCallback !== "function") { | |
| throw new TypeError(`${splitCallback} is not a function`); | |
| } | |
| const newArray = []; | |
| let newGroup = []; | |
| // forEach is tested to be the fastest among sandboxes including NW.js | |
| this.forEach((elem, i) => { | |
| // It's ok to call undefined context with previously bound callbacks | |
| if (splitCallback.call(splitThis_, elem, i, this)) { | |
| newArray.push(newGroup); // It's ok for 1st group to be empty | |
| newGroup = []; | |
| } else newGroup.push(elem); | |
| // | |
| }); | |
| newArray.push(newGroup); // It's ok for the last group to be empty | |
| // | |
| return newArray; | |
| }; // $.split | |
| /** | |
| * This method changes the original array | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {(<T>, index, [<T>]) -> boolean} splitCallback - The callback in | |
| * the Array split | |
| * method | |
| * @param {*?} splitThis_ - The context of splitCallback | |
| * @returns {[[<T>]]} - The fully splitted array as the modified this | |
| */ | |
| $.splitInPlace = function(splitCallback, splitThis_) { | |
| if (this == null) throw new TypeError("this is null or not defined"); | |
| if (typeof splitCallback !== "function") { | |
| throw new TypeError(`${splitCallback} is not a function`); | |
| } | |
| let newGroup = [], oldI = 0, newI = 0; // oldI = newI = 0 doesn't work | |
| while (this.length > newI) { | |
| const elem = this.shift(); | |
| // It's ok to call undefined context with previously bound callbacks | |
| if (splitCallback.call(splitThis_, elem, oldI, this)) { | |
| this.push(newGroup); // It's ok for 1st group to be empty | |
| newGroup = []; | |
| newI++; | |
| } else newGroup.push(elem); | |
| // | |
| oldI++; | |
| } | |
| this.push(newGroup); // It's ok for the last group to be empty | |
| // | |
| return this; | |
| }; // $.splitInPlace | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to be checked against | |
| * @returns {boolean} If this's a proper subset of the specified array | |
| */ | |
| $.isProperSubsetOf = function(arr) { | |
| return this.isSubsetOf(arr) && !arr.isSubsetOf(this); | |
| }; // $.isProperSubsetOf | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to be checked against | |
| * @returns {boolean} If this's a proper superset of the specified array | |
| */ | |
| $.isProperSupersetOf = function(arr) { | |
| return this.isSupersetOf(arr) && !arr.isSupersetOf(this); | |
| }; // $.isProperSupersetOf | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to be checked against | |
| * @returns {boolean} If this's a superset of the specified array | |
| */ | |
| $.isSupersetOf = function(arr) { return arr.isSubsetOf(this); }; | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to be checked against | |
| * @returns {boolean} If this's a subset of the specified array | |
| */ | |
| $.isSubsetOf = function(arr) { return this.difference(arr).isEmpty(); }; | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @returns {boolean} If this array's empty | |
| */ | |
| $.isEmpty = function() { return this.length <= 0; }; | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have symmetric difference with | |
| * @returns {[*]} The symmetric difference of this and the specified array | |
| */ | |
| $.symmetricDifference = function(arr) { | |
| return this.difference(arr).union(arr.difference(this)); | |
| }; // $.symmetricDifference | |
| /** | |
| * This method changes the original array | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have symmetric difference with | |
| * @returns {[*]} The symmetric difference of this and the specified array | |
| */ | |
| $.symmetricDifferenceInPlace = function(arr) { | |
| return this.differenceInPlace(arr).unionInPlace(arr.difference(this)); | |
| }; // $.symmetricDifferenceInPlace | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have union with this array | |
| * @returns {[*]} The union of this and the specified array | |
| */ | |
| $.union = function(arr) { return this.concat(arr.difference(this)); }; | |
| /** | |
| * This method changes the original array | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have union with this array | |
| * @returns {[*]} The union of this and the specified array | |
| */ | |
| $.unionInPlace = function(arr) { | |
| return this.fastMerge(arr.difference(this)); | |
| }; // $.unionInPlace | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have difference with this array | |
| * @returns {[*]} The difference of this and the specified array | |
| */ | |
| $.difference = function(arr) { | |
| return this.filter(elem => arr.excludes(elem)); | |
| }; // $.difference | |
| /** | |
| * This method changes the original array | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have difference with this array | |
| * @returns {[*]} The difference of this and the specified array | |
| */ | |
| $.differenceInPlace = function(arr) { | |
| for (let i = 0; ; i++) { | |
| while (this[i] && arr.includes(this[i])) this.remove(this[i]); | |
| if (!this[i]) return this; | |
| } | |
| }; // $.differenceInPlace | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have intersection with this array | |
| * @returns {[*]} The intersection of this and the specified array | |
| */ | |
| $.intersection = function(arr) { | |
| // The 2nd argument of includes doesn't match with that of filter | |
| return this.filter(elem => arr.includes(elem)); | |
| // | |
| }; // $.intersection | |
| /** | |
| * This method changes the original array | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {[*]} arr - The array to have intersection with this array | |
| * @returns {[*]} The intersection of this and the specified array | |
| */ | |
| $.intersectionInPlace = function(arr) { | |
| for (let i = 0; ; i++) { | |
| while (this[i] && arr.excludes(this[i])) this.remove(this[i]); | |
| if (!this[i]) return this; | |
| } | |
| }; // $.intersectionInPlace | |
| /** | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| * @param {*} elem - The element to be checked against | |
| * @param {index} fromI - The index in this at which to begin searching | |
| * @returns {boolean} If this array doesn't have the specified element | |
| */ | |
| $.excludes = function(elem, fromI) { return !this.includes(elem, fromI); }; | |
| /** | |
| * Potential Hotspot/Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @memberof JsExtensions | |
| */ | |
| $.clear = function() { this.length = 0; }; | |
| })(Array.prototype); | |
| /*---------------------------------------------------------------------------- | |
| * # Edit class: Math | |
| * - Lets you control the randomness of Math.random in RMMZ | |
| *----------------------------------------------------------------------------*/ | |
| (function($, MZ_EC) { | |
| "use strict"; | |
| const { NEW, ORIG, extendFunc } = MZ_EC.setKlassContainer("Math", $, MZ_EC); | |
| extendFunc("random", function() { | |
| // Rewritten to restrict the RNG into an unused partition if any | |
| if (NEW._rngParts.length >= NEW._RNG_PART_NUM) NEW._rngParts.length = 0; | |
| let part, rng; | |
| do { | |
| rng = ORIG.random.apply(this, arguments); | |
| part = Math.floor(rng * NEW._RNG_PART_NUM); | |
| } while (NEW._rngParts.includes(part)); | |
| NEW._rngParts.push(part); | |
| return rng; | |
| // | |
| }); // v0.00a - v0.00a | |
| NEW._RNG_PART_NUM = +PluginManager.parameters(MZ_EC.PLUGIN_NAME).rngPartNum; | |
| NEW._rngParts = []; | |
| })(Math, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Graphics | |
| * - Impproves code quality and adds Graphics renderFps/gameFps accessors | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| addAccessor, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Graphics", $, MZ_EC); | |
| extendFunc("initialize", function() { | |
| const init = ORIG.initialize.apply(this, arguments); | |
| // Added to help plugins alter initialize behaviors in better ways | |
| NEW._initKeyEvents.call(this); | |
| // | |
| return init; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("resize", function(width, height) { | |
| // Added to fix redundant resizes with width and height unchanged | |
| if (this._width === width && this._height === height) return; | |
| // | |
| [this._width, this._height] = [width, height]; | |
| this._app.renderer.resize(width, height); | |
| this._updateAllElements(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("_onKeyDown", function() { | |
| // Edited to help plugins alter key events in better ways | |
| if (NEW._hasNoKeyEvent.call(this, event)) return; | |
| const { keyCode } = event; | |
| for (const [keyCodeFunc, eventFunc] of NEW._keyEvents) { | |
| if (keyCodeFunc() !== keyCode) continue; | |
| event.preventDefault(); | |
| return eventFunc(); | |
| } | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("_createPixiApp", function() { | |
| // Edited to help plugins alter create pixi app in better ways | |
| try { NEW._createPixiAppWithoutRescue.call(this); } catch (e) { | |
| NEW._onCreatePixiAppErr.call(this, e); | |
| } | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("_createEffekseerContext", function() { | |
| // Edited to help plugins alter create effekseer context in better ways | |
| if (!NEW._isCreateEffekseerContext.call(this)) return; | |
| NEW._tryCreateEffekseerContext.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| // Search tag: Graphics_Render_FPS | |
| addAccessor("renderFps", function() { | |
| return this._app.ticker.FPS; | |
| }, function(renderFps) { | |
| const { ticker } = this._app; | |
| ticker.maxFPS = ticker.minFPS = renderFps; | |
| }); // v0.00a - v0.00a | |
| // | |
| // Search tag: Graphics_Game_FPS | |
| addAccessor("gameFps", function() { // v0.00a - v0.00a | |
| return PIXI.settings.TARGET_FPMS * 1000.0; | |
| }, function(gameFps) { PIXI.settings.TARGET_FPMS = gameFps / 1000.0; }); | |
| // | |
| NEW._keyEvents = new Map(); | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._initKeyEvents = function() { | |
| NEW._keyEvents.clear(); | |
| const fpsKeyFunc = NEW._switchFPSCounterKey.bind(this); | |
| NEW._keyEvents.set(fpsKeyFunc, this._switchFPSCounter.bind(this)); | |
| const stretchKeyFunc = NEW._switchStretchModeKey.bind(this); | |
| NEW._keyEvents.set(stretchKeyFunc, this._switchStretchMode.bind(this)); | |
| const fullScreenKeyFn = NEW._switchFullScreenKey.bind(this); | |
| NEW._keyEvents.set(fullScreenKeyFn, this._switchFullScreen.bind(this)); | |
| }; // NEW._initKeyEvents | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {number} - The code of the switch FPS counter key | |
| */ | |
| NEW._switchFPSCounterKey = function() { return 113; }; | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {number} - The code of the switch stretch mode key | |
| */ | |
| NEW._switchStretchModeKey = function() { return 114; }; | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {number} - The code of the switch full screen key | |
| */ | |
| NEW._switchFullScreenKey = function() { return 115; }; | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Event} event - The onkeydown event to be checked against | |
| * @returns {boolean} If the event might trigger functions to be called | |
| */ | |
| NEW._hasNoKeyEvent = function(event) { | |
| return event.ctrlKey || event.altKey; | |
| }; // NEW._hasNoKeyEvent | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._createPixiAppWithoutRescue = function() { | |
| this._setupPixi(); | |
| this._app = NEW._pixiApp.call(this); | |
| }; // NEW._createPixiAppWithoutRescue | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {PIXI.Application} The graphics pixi application | |
| */ | |
| NEW._pixiApp = function() { | |
| const app = new PIXI.Application({ | |
| view: this._canvas, | |
| autoStart: false | |
| }); | |
| app.ticker.remove(app.render, app); | |
| app.ticker.add(this._onTick, this); | |
| return app; | |
| }; // NEW._pixiApp | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error occured when trying to create the pixi app | |
| */ | |
| NEW._onCreatePixiAppErr = function(e) { | |
| console.error(e.stack); | |
| this._app = null; | |
| }; // NEW._onCreatePixiAppErr | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} If the effekseer context can be created | |
| */ | |
| NEW._isCreateEffekseerContext = function() { | |
| return this._app && window.effekseer; | |
| }; // NEW._isCreateEffekseerContext | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._tryCreateEffekseerContext = function() { | |
| try { | |
| this._effekseer = NEW._effekseerContextWithoutRescue.call(this); | |
| } catch (e) { NEW._onCreateEffekseerContextErr.call(this, e); } | |
| }; // NEW._tryCreateEffekseerContext | |
| /** | |
| * The this pointer is Graphics | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {EffekseerContext} The graphics effekseer context | |
| */ | |
| NEW._effekseerContextWithoutRescue = function() { | |
| const context = effekseer.createContext(); | |
| if (context) context.init(this._app.renderer.gl); | |
| return context; | |
| }; // NEW._effekseerContextWithoutRescue | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to create the effekseer context | |
| */ | |
| NEW._onCreateEffekseerContextErr = function(e) { | |
| console.error(e.stack); | |
| this._app = null; | |
| }; // NEW._onCreateEffekseerContextErr | |
| /** | |
| * The this pointer is Graphics | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current target rendering loop FPS | |
| */ | |
| NEW._getRenderFps = function() { return this._app.ticker.FPS; }; | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} renderFps - The new target rendering loop FPS | |
| */ | |
| NEW._setRenderFps = function(renderFps) { | |
| const { ticker } = this._app; | |
| ticker.maxFPS = ticker.minFPS = renderFps; | |
| }; // NEW._setRenderFps | |
| /** | |
| * The this pointer is Graphics | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current target game loop FPS | |
| */ | |
| NEW._getGameFps = function() { return PIXI.settings.TARGET_FPMS * 1000.0; }; | |
| /** | |
| * The this pointer is Graphics | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} gameFps - The new target game loop FPS | |
| */ | |
| NEW._setGameFps = function(gameFps) { | |
| PIXI.settings.TARGET_FPMS = gameFps / 1000.0; | |
| }; // NEW._setGameFps | |
| })(Graphics, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Graphics.FPSCounter | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Graphics_FPSCounter", $, MZ_EC); | |
| rewriteFunc("_update", function() { | |
| // Edited to help plugins alter update behaviors in better ways | |
| this._labelDiv.textContent = NEW._labelDivTextContent.call(this); | |
| this._numberDiv.textContent = NEW._numDivTextContent.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {string} The new FPS counter label text content | |
| */ | |
| NEW._labelDivTextContent = function() { | |
| return this._showFps ? "FPS" : "ms"; | |
| }; // NEW._labelDivTextContent | |
| /** | |
| * The this pointer is Graphics.FPSCounter.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {string} The new FPS counter number text content | |
| */ | |
| NEW._numDivTextContent = function() { | |
| return (this._showFps ? this.fps : this.duration).toFixed(0); | |
| }; // NEW._numDivTextContent | |
| })(Graphics.FPSCounter.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Bitmap | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { NEW, rewriteFunc } = MZ_EC.setKlassContainer("Bitmap", $, MZ_EC); | |
| rewriteFunc("blt", function(source, sx, sy, sw, sh, dx, dy, dw, dh) { | |
| // Edited to help plugins alter the blt behaviors in better ways | |
| try { | |
| NEW._bltWithoutRescue.call( | |
| this, source, sx, sy, sw, sh, dx, dy, dw, dh); | |
| } catch (e) { NEW._onBltError.call(this, e); } | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("drawText", function(text, x, y, maxWidth, lineHeight, align) { | |
| const { context } = this, alpha = context.globalAlpha; | |
| maxWidth = maxWidth || 0xffffffff; | |
| // Edited to help plugins alter the text align behaviors in better ways | |
| const tx = NEW._drawnTextX.call(this, align, x, maxWidth); | |
| // | |
| // Edited to help plugins alter the line height behaviors in better ways | |
| const ty = NEW._drawnTextY.call(this, y, lineHeight); | |
| // | |
| context.save(); | |
| [context.font, context.textAlign] = [this._makeFontNameText(), align]; | |
| [context.textBaseline, context.globalAlpha] = ["alphabetic", 1]; | |
| this._drawTextOutline(text, tx, ty, maxWidth); | |
| context.globalAlpha = alpha; | |
| this._drawTextBody(text, tx, ty, maxWidth); | |
| context.restore(); | |
| this._baseTexture.update(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Bitmap.prototype | |
| * Potential Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Bitmap} source - The bitmap to draw. | |
| * @param {number} sx - The x coordinate in the source | |
| * @param {number} sy - The y coordinate in the source | |
| * @param {number} sw - The width of the source image | |
| * @param {number} sh - The height of the source image | |
| * @param {number} dx - The x coordinate in the destination | |
| * @param {number} dy - The y coordinate in the destination | |
| * @param {number} [dw=sw] The width to draw the image in the destination | |
| * @param {number} [dh=sh] The height to draw the image in the destination | |
| */ | |
| NEW._bltWithoutRescue = function(source, sx, sy, sw, sh, dx, dy, dw, dh) { | |
| // Default parameters can't be used as it's possible for them to be 0 | |
| [dw, dh] = [dw || sw, dh || sh]; | |
| // | |
| const image = source._canvas || source._image; | |
| this.context.globalCompositeOperation = "source-over"; | |
| this.context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); | |
| this._baseTexture.update(); | |
| }; // NEW._bltWithoutRescue | |
| /** | |
| * The this pointer is Bitmap.prototype | |
| * Potential Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to perform bit block transfer | |
| */ | |
| NEW._onBltError = function(e) { console.warn(e.stack); }; | |
| /** | |
| * The this pointer is Bitmap.prototype | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} x - The x coordinate for the top of the text | |
| * @param {number} lineHeight - The height of the text line | |
| * @returns {number} The x position of the text to be drawn | |
| */ | |
| NEW._drawnTextX = function(align, x, maxWidth) { | |
| if (align === "center") return x + maxWidth / 2; | |
| return align === "right" ? x + maxWidth : x; | |
| }; // NEW._drawnTextX | |
| /** | |
| * The this pointer is Bitmap.prototype | |
| * Potential Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} y - The y coordinate for the top of the text | |
| * @param {number} lineHeight - The height of the text line | |
| * @returns {number} The y position of the text to be drawn | |
| */ | |
| NEW._drawnTextY = function(y, lineHeight) { | |
| return Math.round(y + lineHeight / 2 + this.fontSize * 0.35); | |
| }; // NEW._drawnTextY | |
| })(Bitmap.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Sprite | |
| * - Impproves performance and code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteAccessor, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Sprite", $, MZ_EC); | |
| rewriteAccessor("width", function() { | |
| return this._frame.width; | |
| }, function(val) { | |
| // Added to stop refreshing the sprite when its width remain unchanged | |
| if (this._frame.width === val) return; | |
| // | |
| this._frame.width = val; | |
| this._refresh(); | |
| }); // v0.00a - v0.00a | |
| rewriteAccessor("height", function() { | |
| return this._frame.height; | |
| }, function(val) { | |
| // Added to stop refreshing the sprite when its height remain unchanged | |
| if (this._frame.height === val) return; | |
| // | |
| this._frame.height = val; | |
| this._refresh(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("_refresh", function() { | |
| // Edited to help plugins alter texture refresh behaviors in better ways | |
| if (this.texture) NEW._refreshWithTexture.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._refreshWithTexture = function() { | |
| const frameX = Math.floor(this._frame.x); | |
| const frameY = Math.floor(this._frame.y); | |
| const frameW = Math.floor(this._frame.width); | |
| const frameH = Math.floor(this._frame.height); | |
| const baseTexture = this._bitmap ? this._bitmap.baseTexture : null; | |
| const baseTextureW = baseTexture ? baseTexture.width : 0; | |
| const baseTextureH = baseTexture ? baseTexture.height : 0; | |
| const realX = frameX.clamp(0, baseTextureW); | |
| const realY = frameY.clamp(0, baseTextureH); | |
| const realW = (frameW - realX + frameX).clamp(0, baseTextureW - realX); | |
| const realH = (frameH - realY + frameY).clamp(0, baseTextureH - realY); | |
| const frame = new Rectangle(realX, realY, realW, realH); | |
| [this.pivot.x, this.pivot.y] = [frameX - realX, frameY - realY]; | |
| if (baseTexture) { | |
| NEW._refreshWithBaseTexture.call(this, baseTexture, frame); | |
| } | |
| this.texture._updateID++; | |
| }; // NEW._refreshWithTexture | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {PIXI.BaseTexture} baseTexture - The sprite bitmap base texture | |
| * @param {Rectangle} frame - The rectangular frame with real dimensions | |
| */ | |
| NEW._refreshWithBaseTexture = function(baseTexture, frame) { | |
| const { texture } = this; | |
| texture.baseTexture = baseTexture; | |
| try { texture.frame = frame; } catch (e) { | |
| NEW._onRefreshWithBaseTextureErr.call(this, e); | |
| } | |
| }; // NEW._refreshWithBaseTexture | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to refresh with base texture | |
| */ | |
| NEW._onRefreshWithBaseTextureErr = function(e) { | |
| console.warn(e.stack); | |
| this.texture.frame = new Rectangle(); | |
| }; // NEW._onRefreshWithBaseTextureErr | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current width of this sprite | |
| */ | |
| NEW._getWidth = function() { return this._frame.width; }; | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new width of this sprite | |
| */ | |
| NEW._setWidth = function(val) { | |
| // Added to stop refreshing the sprite when its width remain unchanged | |
| if (this._frame.width === val) return; | |
| // | |
| this._frame.width = val; | |
| this._refresh(); | |
| }; // NEW._setWidth | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current height of this sprite | |
| */ | |
| NEW._getHeight = function() { return this._frame.height; }; | |
| /** | |
| * The this pointer is Sprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new height of this sprite | |
| */ | |
| NEW._setHeight = function(val) { | |
| // Added to stop refreshing the sprite when its height remain unchanged | |
| if (this._frame.height === val) return; | |
| // | |
| this._frame.height = val; | |
| this._refresh(); | |
| }; // NEW._setHeight | |
| })(Sprite.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Tilemap.Renderer | |
| * - Impproves performance and code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Tilemap_Renderer", $, MZ_EC); | |
| rewriteFunc("_createShader", function() { | |
| // Edited to help plugins alter the create shader glsl in better ways | |
| const vertexSrc = NEW._shaderVertexSrc.call(this); | |
| const fragmentSrc = NEW._shaderFragmentSrc.call(this); | |
| // | |
| return new PIXI.Shader(PIXI.Program.from(vertexSrc, fragmentSrc), { | |
| uSampler0: 0, | |
| uSampler1: 0, | |
| uSampler2: 0, | |
| uProjectionMatrix: new PIXI.Matrix() | |
| }); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Tilemap.Renderer.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {string} The shader vertex glsl source codes | |
| */ | |
| NEW._shaderVertexSrc = function() { | |
| return `attribute float aTextureId; | |
| attribute vec4 aFrame; | |
| attribute vec2 aSource; | |
| attribute vec2 aDest; | |
| uniform mat3 uProjectionMatrix; | |
| varying vec4 vFrame; | |
| varying vec2 vTextureCoord; | |
| varying float vTextureId; | |
| void main(void) { | |
| vec3 position = uProjectionMatrix * vec3(aDest, 1.0); | |
| gl_Position = vec4(position, 1.0); | |
| vFrame = aFrame; | |
| vTextureCoord = aSource; | |
| vTextureId = aTextureId; | |
| }`; | |
| }; // NEW._shaderVertexSrc | |
| /** | |
| * The this pointer is Tilemap.Renderer.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {string} The shader fragment glsl source codes | |
| */ | |
| NEW._shaderFragmentSrc = function() { | |
| return `varying vec4 vFrame; | |
| varying vec2 vTextureCoord; | |
| varying float vTextureId; | |
| uniform sampler2D uSampler0; | |
| uniform sampler2D uSampler1; | |
| uniform sampler2D uSampler2; | |
| void main(void) { | |
| vec2 textureCoord = clamp(vTextureCoord, vFrame.xy, vFrame.zw); | |
| int textureId = int(vTextureId); | |
| vec4 color; | |
| if (textureId < 0) { | |
| color = vec4(0.0, 0.0, 0.0, 0.5); | |
| } else if (textureId == 0) { | |
| color = texture2D(uSampler0, textureCoord / 2048.0); | |
| } else if (textureId == 1) { | |
| color = texture2D(uSampler1, textureCoord / 2048.0); | |
| } else if (textureId == 2) { | |
| color = texture2D(uSampler2, textureCoord / 2048.0); | |
| } | |
| gl_FragColor = color; | |
| }`; | |
| }; // NEW._shaderFragmentSrc | |
| })(Tilemap.Renderer.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: TilingSprite | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("TilingSprite", $, MZ_EC); | |
| rewriteFunc("_refresh", function() { | |
| // Edited to help plugins alter texture refresh behaviors in better ways | |
| if (this.texture) NEW._refreshWithTexture.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is TilingSprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._refreshWithTexture = function() { | |
| if (this.texture.baseTexture) NEW._refreshWithBaseTexture.call(this); | |
| this.texture._updateID++; | |
| }; // NEW._refreshWithTexture | |
| /** | |
| * The this pointer is TilingSprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._refreshWithBaseTexture = function() { | |
| try { | |
| this.texture.frame = NEW._refreshedTextureFrame.call(this); | |
| } catch (e) { NEW._onRefreshWithBaseTextureErr.call(this, e); } | |
| }; // NEW._refreshWithBaseTexture | |
| /** | |
| * The this pointer is TilingSprite.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {Rectangle} The new frame for the refreshed texture | |
| */ | |
| NEW._refreshedTextureFrame = function() { | |
| const frame = this._frame.clone(); | |
| /** @todo Extracts these codes into well-named functions */ | |
| if (frame.width === 0 && frame.height === 0 && this._bitmap) { | |
| frame.width = this._bitmap.width; | |
| frame.height = this._bitmap.height; | |
| } | |
| // | |
| return frame; | |
| }; // NEW._refreshedTextureFrame | |
| /** | |
| * The this pointer is TilingSprite.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error occured when failing to refresh base texture | |
| */ | |
| NEW._onRefreshWithBaseTextureErr = function(e) { | |
| console.warn(e.stack); | |
| this.texture.frame = new Rectangle(); | |
| }; // NEW._onRefreshWithBaseTextureErr | |
| })(TilingSprite.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Window | |
| * - Impproves performance | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteAccessor | |
| } = MZ_EC.setKlassContainer("Window", $, MZ_EC); | |
| rewriteAccessor("width", NEW._getWidth = function() { | |
| return this._width; | |
| }, NEW._setWidth = function(val) { | |
| // Added to fix redundant refresh with width unchanged | |
| if (this._width === val) return; | |
| // | |
| this._width = val; | |
| this._refreshAllParts(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteAccessor("height", NEW._getHeight = function() { | |
| return this._height; | |
| }, NEW._setHeight = function(val) { | |
| // Added to fix redundant refresh with height unchanged | |
| if (this._height === val) return; | |
| // | |
| this._height = val; | |
| this._refreshAllParts(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteAccessor("padding", NEW._getPadding = function() { | |
| return this._padding; | |
| }, NEW._setPadding = function(val) { | |
| // Added to fix redundant refresh with padding unchanged | |
| if (this._padding === val) return; | |
| // | |
| this._padding = val; | |
| this._refreshAllParts(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteAccessor("margin", NEW._getMargin = function() { | |
| return this._margin; | |
| }, NEW._setMargin = function(val) { | |
| // Added to fix redundant refresh with margin unchanged | |
| if (this._margin === val) return; | |
| // | |
| this._margin = val; | |
| this._refreshAllParts(); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Window.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current width of this window | |
| */ | |
| NEW._getWidth = function() { return this._width; }; | |
| /** | |
| * The this pointer is Window.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new width of this window | |
| */ | |
| NEW._setWidth = function(val) { | |
| // Added to fix redundant refresh with width unchanged | |
| if (this._width === val) return; | |
| // | |
| this._width = val; | |
| this._refreshAllParts(); | |
| // | |
| }; // NEW._setWidth | |
| /** | |
| * The this pointer is Window.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current height of this window | |
| */ | |
| NEW._getHeight = function() { return this._height; }; | |
| /** | |
| * The this pointer is Window.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new height of this window | |
| */ | |
| NEW._setHeight = function(val) { | |
| // Added to fix redundant refresh with height unchanged | |
| if (this._height === val) return; | |
| // | |
| this._height = val; | |
| this._refreshAllParts(); | |
| // | |
| }; // NEW._setHeight | |
| /** | |
| * The this pointer is Window.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current padding of this window | |
| */ | |
| NEW._getPadding = function() { return this._padding; }; | |
| /** | |
| * The this pointer is Window.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new padding of this window | |
| */ | |
| NEW._setPadding = function(val) { | |
| // Added to fix redundant refresh with padding unchanged | |
| if (this._padding === val) return; | |
| // | |
| this._padding = val; | |
| this._refreshAllParts(); | |
| // | |
| }; // NEW._setPadding | |
| /** | |
| * The this pointer is Window.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The current margin of this window | |
| */ | |
| NEW._getMargin = function() { return this._margin; }; | |
| /** | |
| * The this pointer is Window.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The new margin of this window | |
| */ | |
| NEW._setMargin = function(val) { | |
| // Added to fix redundant refresh with margin unchanged | |
| if (this._margin === val) return; | |
| // | |
| this._margin = val; | |
| this._refreshAllParts(); | |
| // | |
| }; // NEW._setMargin | |
| })(Window.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: WebAudio | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { NEW, rewriteFunc } = MZ_EC.setKlassContainer("WebAudio", $, MZ_EC); | |
| const { | |
| NEW: NEW_PROTO, | |
| rewriteFunc: rewriteProtoFunc | |
| } = MZ_EC.setKlassContainer("WebAudio_Proto", $.prototype, MZ_EC); | |
| rewriteFunc("_createContext", function() { | |
| // Edited to help plugins alter create context behaviors in better ways | |
| try { | |
| const AudioContext = | |
| window.AudioContext || window.webkitAudioContext; | |
| this._context = new AudioContext(); | |
| } catch (e) { NEW._onCreateContextErr.call(this, e); } | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteProtoFunc("_stopSourceNode", function() { | |
| // Edited to help plugins alter stop source node in better ways | |
| this._sourceNodes.forEach(NEW_PROTO._stopEachSourceNode, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is WebAudio | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to create the audio context | |
| */ | |
| NEW._onCreateContextErr = function(e) { | |
| console.warn(e.stack); | |
| this._context = null; | |
| }; // NEW._onCreateContextErr | |
| /** | |
| * The this pointer is WebAudio.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {AudioBufferSourceNode} sourceNode - The source node to be stopped | |
| */ | |
| NEW_PROTO._stopEachSourceNode = function(sourceNode) { | |
| try { | |
| sourceNode.onended = null; | |
| sourceNode.stop(); | |
| } catch (e) { | |
| NEW_PROTO._onStopSourceNodeErr.call(this, e); | |
| } | |
| }; // NEW_PROTO._stopEachSourceNode | |
| /** | |
| * The this pointer is WebAudio.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to stop the source node | |
| */ | |
| NEW_PROTO._onStopSourceNodeErr = function(e) { console.warn(e.stack); }; | |
| })(WebAudio, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Input | |
| * - Adds some new Input APIs | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Input", $, MZ_EC); | |
| extendFunc("clear", function() { | |
| ORIG.clear.apply(this, arguments); | |
| // Added to help plugins support the isJustReleased static function | |
| NEW._isJustReleased.clear(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("update", function() { | |
| this._pollGamepads(); | |
| // Edited to help plugins alter update behaviors in better ways | |
| NEW._updateLatestButton.call(this); | |
| NEW._updateCurrentStates.call(this); | |
| if (this._virtualButton) NEW._updateVirtualClick.call(this); | |
| // | |
| this._updateDirection(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("_onKeyDown", function(event) { | |
| const { keyCode } = event; | |
| if (this._shouldPreventDefault(keyCode)) event.preventDefault(); | |
| // Edited to help plugins alter clear keys in better ways | |
| if (NEW._shouldClear.call(this, keyCode)) this.clear(); | |
| // | |
| const buttonName = this.keyMapper[keyCode]; | |
| if (buttonName) this._currentState[buttonName] = true; | |
| }); // v0.00a - v0.00a | |
| /** | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| * @returns {boolean} If the key's just released right on this frame | |
| */ | |
| $.isJustReleased = function(keyName) { | |
| if (NEW._isEscCompatibleJustReleased.call(this, keyName)) return true; | |
| return NEW._isJustReleased.has(keyName); | |
| }; // $.isJustReleased | |
| NEW._isJustReleased = new Map(); | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._updateLatestButton = function() { | |
| if (this._currentState[this._latestButton]) { | |
| this._pressedTime++; | |
| } else this._latestButton = null; | |
| }; // NEW._updateLatestButton | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._updateCurrentStates = function() { | |
| for (const keyName in this._currentState) { | |
| const currentState = this._currentState[keyName]; | |
| NEW._updateCurrentState.call(this, currentState, keyName); | |
| } | |
| }; // NEW._updateCurrentStates | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {boolean} keyState - If the key's currently pressed | |
| * @enum @param {string} keyName - The mapped name of the key | |
| */ | |
| NEW._updateCurrentState = function(keyState, keyName) { | |
| NEW._updateLatestState.call(this, keyName); | |
| this._previousState[keyName] = keyState; | |
| }; // NEW._updateCurrentState | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| */ | |
| NEW._updateLatestState = function(keyName) { | |
| if (NEW._isJustPressed.call(this, keyName)) { | |
| NEW._onStartPress.call(this, keyName); | |
| } else if (NEW._isKeyJustReleased.call(this, keyName)) { | |
| NEW._isJustReleased.set(keyName, true); | |
| } else NEW._isJustReleased.delete(keyName); | |
| // | |
| }; // NEW._updateLatestState | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| * @returns {boolean} If the key's just pressed right on this frame | |
| */ | |
| NEW._isJustPressed = function(keyName) { | |
| if (!this._currentState[keyName]) return false; | |
| return !this._previousState[keyName]; | |
| }; // NEW._isJustPressed | |
| /** | |
| * The this pointer is Input | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| */ | |
| NEW._onStartPress = function(keyName) { | |
| [this._latestButton, this._pressedTime] = [keyName, 0]; | |
| this._date = Date.now(); | |
| NEW._isJustReleased.delete(keyName); | |
| }; // NEW._onStartPress | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| * @returns {boolean} If the key's just released right on this frame | |
| */ | |
| NEW._isKeyJustReleased = function(keyName) { | |
| if (this._currentState[keyName]) return false; | |
| return this._previousState[keyName]; | |
| }; // NEW._isKeyJustReleased | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._updateVirtualClick = function() { | |
| this._latestButton = this._virtualButton; | |
| [this._pressedTime, this._virtualButton] = [0, null]; | |
| }; // NEW._updateVirtualClick | |
| /** | |
| * The this pointer is Input | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| * @returns {boolean} If the pressed key should clear all input states | |
| */ | |
| NEW._shouldClear = function(keyCode) { return keyCode === 144; }; | |
| /** | |
| * The this pointer is Input | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {string} keyName - The mapped name of the key | |
| * @returns {boolean} If the specified key should be regarded as pressed | |
| */ | |
| NEW._isEscCompatibleJustReleased = function(keyName) { | |
| if (!this._isEscapeCompatible(keyName)) return false; | |
| return this.isJustReleased("escape"); | |
| }; // NEW._isEscCompatibleJustReleased | |
| })(Input, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Managers | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: DataManager | |
| * - Impproves code quality and helps plugins load notetags in better way | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const klassName = "DataManager", { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc, | |
| } = MZ_EC.setKlassContainer(klassName, $, MZ_EC); | |
| extendFunc("extractSaveContents", function(contents) { | |
| ORIG.extractSaveContents.apply(this, arguments); | |
| // Added to ensure all parameter functions uses the parameters in saves | |
| $gameSystem.loadParamFuncs(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onXhrLoad", function(xhr, name, src, url) { | |
| // Edited to help plugins alter on xhr load behaviors in better ways | |
| if (xhr.status < 400) return NEW._onXhrLoadSuc.call(this, xhr, name); | |
| // | |
| this.onXhrError(name, src, url); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onLoad", function(obj, objName) { | |
| NEW.loadObj.call(this, obj, objName); | |
| // Added to help plugins load notetags with known data container type | |
| NEW.loadDataNotetags.call(this, obj, objName); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {{*}} obj - The raw data from the database to be loaded | |
| * @param {string} objName - The name of the data container having notetags | |
| */ | |
| NEW.loadObj = function(obj, objName) { | |
| if (this.isMapObject(obj)) return NEW.loadMapObj.call(this, obj); | |
| NEW.loadOtherObj.call(this, obj, objName); | |
| }; // NEW.loadObj | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {{*}} obj - The raw data from the database to be loaded | |
| */ | |
| NEW.loadMapObj = function(obj) { | |
| this.extractMetadata(obj); | |
| this.extractArrayMetadata(obj.events); | |
| }; // NEW.loadMapObj | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {{*}} obj - The raw data from the database to be loaded | |
| * @param {string} objName - The name of the data container having notetags | |
| */ | |
| NEW.loadOtherObj = function(obj, objName) { | |
| this.extractArrayMetadata(obj); | |
| }; // NEW.loadOtherObj | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {[Datum]} obj - The data container having notetags to be loaded | |
| * @param {string} objName - The name of the data container having notetags | |
| */ | |
| NEW.loadDataNotetags = function(obj, objName) {}; | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {XMLHttpRequest} xhr - The xhr successfully loading the data | |
| * @param {string} name - The name of the successfully loaded data container | |
| */ | |
| NEW._onXhrLoadSuc = function(xhr, name) { | |
| window[name] = JSON.parse(xhr.responseText); | |
| this.onLoad(window[name], name); | |
| }; // NEW._onXhrLoadSuc | |
| MZ_EC.loadDataManagerNotetags = (pluginName, notePairs, containerNames, regex, containerName = regex) => { | |
| const { | |
| NEW, | |
| ORIG | |
| } = MZ_EC.setKlassContainer(klassName, $, pluginName); | |
| const EC_DM = MZ_EC[klassName].new, DM = pluginName[klassName]; | |
| NEW.NOTETAG_PAIRS = new Map(); | |
| Object.entries(notePairs).forEach(([noteName, pairs]) => { | |
| NEW.NOTETAG_PAIRS.set(noteName, new Map(Object.entries(pairs))); | |
| }); | |
| NEW.NOTETAG_DATA_CONTAINER_NAMES = | |
| new Map(Object.entries(containerNames)); | |
| NEW._REG_EXP_NOTE = regex; | |
| MZ_EC.extendFunc(EC_DM, DM, "loadDataNotetags", function(obj, objName) { | |
| ORIG.loadDataNotetags.apply(this, arguments); | |
| // Added to load all notetags of this plugin | |
| NEW._loadDataNotetags.call(this, obj, objName); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is DataManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[Datum]} obj - Data container having notetags to be loaded | |
| * @param {string} objName - The name of data container having notetags | |
| */ | |
| NEW._loadDataNotetags = function(obj, objName) { | |
| if (!NEW.NOTETAG_DATA_CONTAINER_NAMES.has(objName)) return; | |
| const datumType = NEW.NOTETAG_DATA_CONTAINER_NAMES.get(objName); | |
| MZ_EC.onLoadDataNotetags.call(this, obj, datumType, regex, | |
| NEW.NOTETAG_PAIRS, containerName); | |
| }; // NEW._loadDataNotetags | |
| }; // MZ_EC.loadDataManagerNotetags | |
| })(DataManager, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: StorageManager | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("StorageManager", $, MZ_EC); | |
| rewriteFunc("jsonToZip", function(json) { | |
| return new Promise((resolve, reject) => { | |
| try { | |
| // Edited to help plugins alter json to zip in better ways | |
| const zip = NEW._zipFromJson.call(this, json); | |
| NEW._checkSaveDataSize.call(this, zip); | |
| // | |
| resolve(zip); | |
| } catch (e) { reject(e); } | |
| }); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("zipToJson", function(zip) { | |
| return new Promise((resolve, reject) => { | |
| try { | |
| // Edited to help plugins alter zip to json in better ways | |
| if (zip) return resolve(NEW._jsonFromZip.call(this, zip)); | |
| // | |
| resolve("null"); | |
| } catch (e) { reject(e); } | |
| }); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("saveToLocalFile", function(saveName, zip) { | |
| const filePath = this.filePath(saveName); | |
| const backupFilePath = `${filePath}_`; | |
| return new Promise((resolve, reject) => { | |
| // Edited to help plugins alter save to local file in better ways | |
| NEW._onPrepareSaveToLocalFile.call(this, filePath, backupFilePath); | |
| try { | |
| NEW._onSaveToLocalFileWithoutRescue.call( | |
| this, zip, filePath, backupFilePath); | |
| resolve(); | |
| } catch (e) { | |
| NEW._onTryRollbackFailedLocalFileSave.call( | |
| this, filePath, backupFilePath); | |
| reject(e); | |
| } | |
| // | |
| }); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is StorageManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {json} json - The json string save data to the compressed | |
| * @returns {Uint8Array|Array} The compressed zip from the json string data | |
| */ | |
| NEW._zipFromJson = function(json) { | |
| return pako.deflate(json, { to: "string", level: 1 }); | |
| }; // NEW._zipFromJson | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Uint8Array|Array} zip - Zipped save data to have its size checked | |
| */ | |
| NEW._checkSaveDataSize = function(zip) { | |
| /** @todo Figures out where does 50000 come from */ | |
| if (zip.length >= 50000) console.warn("Save data is too big."); | |
| // | |
| }; // NEW._checkSaveDataSize | |
| /** | |
| * The this pointer is StorageManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Uint8Array|Array} zip - The zipped save data to be decompressed | |
| * @returns {json} The decompressed json string from the compressed zip | |
| */ | |
| NEW._jsonFromZip = function(zip) { | |
| return pako.inflate(zip, { to: "string" }); | |
| }; // NEW._jsonFromZip | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {string} filePath - The real file path of the local save file | |
| * @param {string} backupFilePath - The test file path of the save file | |
| */ | |
| NEW._onPrepareSaveToLocalFile = function(filePath, backupFilePath) { | |
| // It's almost immediately called after saveToLocalFile so it's ok here | |
| this.fsMkdir(this.fileDirectoryPath()); | |
| // | |
| this.fsUnlink(backupFilePath); | |
| this.fsRename(filePath, backupFilePath); | |
| }; // NEW._onPrepareSaveToLocalFile | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Uint8Array|Array} zip - The zipped save data to be saved locally | |
| * @param {string} filePath - The real file path of the local save file | |
| * @param {string} backupFilePath - The test file path of the save file | |
| */ | |
| NEW._onSaveToLocalFileWithoutRescue = function(zip, filePath, backupFilePath) { | |
| this.fsWriteFile(filePath, zip); | |
| this.fsUnlink(backupFilePath); | |
| }; // NEW._onSaveToLocalFileWithoutRescue | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {string} filePath - The real file path of the local save file | |
| * @param {string} backupFilePath - The test file path of the save file | |
| */ | |
| NEW._onTryRollbackFailedLocalFileSave = function(filePath, backupFilePath) { | |
| try { | |
| NEW._onRollbackFailedLocalFileSaveWithouRescue.call( | |
| this, filePath, backupFilePath); | |
| } catch (e2) { NEW._onRollbackFailedLocalFileSaveErr.call(this, e2); } | |
| }; // NEW._onTryRollbackFailedLocalFileSave | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - Error when failing to rollback failed local file save | |
| */ | |
| NEW._onRollbackFailedLocalFileSaveErr = function(e) { | |
| console.warn(e.stack); | |
| }; // NEW._onRollbackFailedLocalFileSaveErr | |
| /** | |
| * The this pointer is StorageManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {string} filePath - The real file path of the local save file | |
| * @param {string} backupFilePath - The test file path of the save file | |
| */ | |
| NEW._onRollbackFailedLocalFileSaveWithouRescue = function(filePath, backupFilePath) { | |
| this.fsUnlink(filePath); | |
| this.fsRename(backupFilePath, filePath); | |
| }; // NEW._onRollbackFailedLocalFileSaveWithouRescue | |
| })(StorageManager, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: SceneManager | |
| * - Impproves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("SceneManager", $, MZ_EC); | |
| extendFunc("initialize", function() { | |
| ORIG.initialize.apply(this, arguments); | |
| // Added to help plugins alter key events in better ways | |
| NEW._initKeyEvents.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onKeyDown", function(event) { | |
| // Edited to help plugins alter key events in better ways | |
| if (NEW._hasNoKeyEvent.call(this, event)) return; | |
| const { keyCode } = event; | |
| for (const [keyCodeFunc, eventFunc] of NEW._keyEvents) { | |
| if (keyCodeFunc() === keyCode) return eventFunc(); | |
| } | |
| // | |
| }); // v0.00a - v0.00a | |
| NEW._keyEvents = new Map(); | |
| /** | |
| * The this pointer is SceneManager | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._initKeyEvents = function() { | |
| NEW._keyEvents.clear(); | |
| const reloadGameKeyFunc = NEW._reloadGameKey.bind(this); | |
| NEW._keyEvents.set(reloadGameKeyFunc, this.reloadGame.bind(this)); | |
| const showDevToolsKeyFunc = NEW._showDevToolsKey.bind(this); | |
| NEW._keyEvents.set(showDevToolsKeyFunc, this.showDevTools.bind(this)); | |
| }; // NEW._initKeyEvents | |
| /** | |
| * The this pointer is SceneManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {number} - The code of the reload game key | |
| */ | |
| NEW._reloadGameKey = function() { return 116; }; | |
| /** | |
| * The this pointer is SceneManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {number} - The code of the show dev tools key | |
| */ | |
| NEW._showDevToolsKey = function() { return 119; }; | |
| /** | |
| * The this pointer is SceneManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Event} event - The onkeydown event to be checked against | |
| * @returns {boolean} If the event might trigger functions to be called | |
| */ | |
| NEW._hasNoKeyEvent = function(event) { | |
| return event.ctrlKey || event.altKey; | |
| }; // NEW._hasNoKeyEvent | |
| })(SceneManager, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: BattleManager | |
| * - Impproves performance and code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("BattleManager", $, MZ_EC); | |
| extendFunc("setup", function() { | |
| // Added to ensures the battler notetag cache won't store stale data | |
| MZ_EC.clearAllBattlerNotetagCaches(); | |
| // | |
| ORIG.setup.apply(this, arguments); | |
| }); // v0.00a - v0.00a | |
| extendFunc("initMembers", function() { | |
| ORIG.initMembers.apply(this, arguments); | |
| // Added to help plugins check if the battle should end | |
| NEW._isBattleEnd = false; | |
| // | |
| // Added to help plugins check if the event main's updated | |
| NEW._isUpdateEventMain = false; | |
| // | |
| }); // v0.00a - v0.00a | |
| extendFunc("updateBattleEnd", function() { | |
| ORIG.updateBattleEnd.apply(this, arguments); | |
| // Added to ensures the battler notetag cache won't store stale data | |
| MZ_EC.clearAllBattlerNotetagCaches(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onEncounter", function() { | |
| // Edited to help plugins alter encounter behaviors in better ways | |
| this._preemptive = NEW._encounterPreemptive.call(this); | |
| this._surprise = NEW._encounterSurprise.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeEscapeRatio", function() { | |
| // Edited to help plugins alter escape ratio behaviors in better ways | |
| this._escapeRatio = NEW._newEscRatio.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateEventMain", function() { | |
| $gameTroop.updateInterpreter(); | |
| $gameParty.requestMotionRefresh(); | |
| // Edited to help plugins check if the event main's updated | |
| if ($gameTroop.isEventRunning() || this.checkBattleEnd()) { | |
| return NEW._isUpdateEventMain = true; | |
| } | |
| $gameTroop.setupBattleEvent(); | |
| return NEW._isUpdateEventMain = | |
| $gameTroop.isEventRunning() || SceneManager.isSceneChanging(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("startBattle", function() { | |
| this._phase = "start"; | |
| $gameSystem.onBattleStart(); | |
| // Edited to help plugins alter start battle behaviors in better ways | |
| $gameParty.onBattleStart(this._preemptive, this._surprise); | |
| $gameTroop.onBattleStart(this._surprise, this._preemptive); | |
| // | |
| this.displayStartMessages(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("changeCurrentActor", function(forward) { | |
| // Edited to help plugins alter change current actor in better ways | |
| this._currentActor = NEW._newCurActor_.call(this, forward); | |
| // | |
| this.startActorInput(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTurn", function(timeActive) { | |
| $gameParty.requestMotionRefresh(); | |
| // Edited to help plugins alter update turn behaviors in better ways | |
| if (NEW._isUpdateTpb.call(this, timeActive)) this.updateTpb(); | |
| // | |
| this._subject = this._subject || this.getNextSubject(); | |
| if (this._subject) return this.processTurn(); | |
| if (!this.isTpb()) this.endTurn(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("endBattlerActions", function(battler) { | |
| // Edited to help plugins alter battler action end state in better ways | |
| battler.setActionState(NEW._battlerActEndState.call(this)); | |
| // | |
| battler.onAllActionsEnd(); | |
| battler.clearTpbChargeTime(); | |
| this.displayBattlerStatus(battler, true); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("invokeAction", function(subject, target) { | |
| this._logWindow.push("pushBaseLine"); | |
| // Edited to help plugins alter invoke action behaviors in better ways | |
| if (NEW._isInvokeCnt.call(this, target)) { | |
| this.invokeCounterAttack(subject, target); | |
| } else if (NEW._isInvokeMrf.call(this, target)) { | |
| this.invokeMagicReflection(subject, target); | |
| } else this.invokeNormalAction(subject, target); | |
| // | |
| subject.setLastTarget(target); | |
| this._logWindow.push("popBaseLine"); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("checkBattleEnd", function() { | |
| // Added _isBattleEnd to help plugins check if the battle should end | |
| if (!this._phase) return NEW._isBattleEnd = false; | |
| if ($gameParty.isEscaped()) { | |
| this.processPartyEscape(); | |
| return NEW._isBattleEnd = true; | |
| } else if ($gameParty.isAllDead()) { | |
| this.processDefeat(); | |
| return NEW._isBattleEnd = true; | |
| } else if (!$gameTroop.isAllDead()) return NEW._isBattleEnd = false; | |
| this.processVictory(); | |
| return NEW._isBattleEnd = true; | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("processEscape", function() { | |
| $gameParty.performEscape(); | |
| SoundManager.playEscape(); | |
| // Edited to help plugins alter process escape behaviors in better ways | |
| const success = NEW._isEscSuc.call(this); | |
| // | |
| success ? this.onEscapeSuccess() : this.onEscapeFailure(); | |
| return success; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onEscapeFailure", function() { | |
| $gameParty.onEscapeFailure(); | |
| this.displayEscapeFailureMessage(); | |
| // Edited to help plugins alter escape ratio increment in better ways | |
| this._escapeRatio = NEW._updatedEscRatio.call(this); | |
| // | |
| if (!this.isTpb()) this.startTurn(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the battle has a preemptive start | |
| */ | |
| NEW._encounterPreemptive = function() { | |
| return Math.random() < this.ratePreemptive(); | |
| }; // NEW._encounterPreemptive | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the battle has a surprise start | |
| */ | |
| NEW._encounterSurprise = function() { | |
| return Math.random() < this.rateSurprise() && !this._preemptive; | |
| }; // NEW._encounterSurprise | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The probability of the party escape attempt to succeed | |
| */ | |
| NEW._newEscRatio = function() { | |
| return 0.5 * $gameParty.agility() / $gameTroop.agility(); | |
| }; // NEW._newEscRatio | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {Game_Actor?} The actor as the selected one to input actions | |
| */ | |
| NEW._newCurActor_ = function(forward) { | |
| const members = $gameParty.battleMembers(); | |
| const iIncrement = forward ? 1 : -1; | |
| let currentI = members.indexOf(this._currentActor); | |
| for (;;) { | |
| currentI += iIncrement; | |
| const actor = members[currentI]; | |
| if (!actor) return null; | |
| if (actor.canInput()) return actor; | |
| } | |
| }; // NEW._newCurActor_ | |
| /** | |
| * The this pointer is BattleManager | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {boolean} timeActive - Whether the TPBS time is actually active | |
| * @returns {boolean} Whether the TPBS frame update should proceed | |
| */ | |
| NEW._isUpdateTpb = function(timeActive) { | |
| return this.isTpb() && timeActive; | |
| }; // NEW._isUpdateTpb | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @returns {pose} The pose of the battler ending executing an action | |
| */ | |
| NEW._battlerActEndState = function() { | |
| return this.isTpb() ? "undecided" : "done"; | |
| }; // NEW._battlerActEndState | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the battle should be aborted | |
| */ | |
| NEW._isInvokeCnt = function(target) { | |
| return Math.random() < this._action.itemCnt(target); | |
| }; // NEW._isInvokeCnt | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the battle should be aborted | |
| */ | |
| NEW._isInvokeMrf = function(target) { | |
| return Math.random() < this._action.itemMrf(target); | |
| }; // NEW._isInvokeMrf | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the party escape attempt should succeed | |
| */ | |
| NEW._isEscSuc = function() { | |
| return this._preemptive || Math.random() < this._escapeRatio; | |
| }; // NEW._isEscSuc | |
| /** | |
| * The this pointer is BattleManager | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The new party escape attempt success probability | |
| */ | |
| NEW._updatedEscRatio = function() { return this._escapeRatio + 0.1; }; | |
| })(BattleManager, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Objects | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_System | |
| * - Uses the configurable Graphics fps instead of the constant 60 | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const klassName = "Game_System", { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer(klassName, $, MZ_EC); | |
| /*------------------------------------------------------------------------ | |
| * New private variable | |
| *------------------------------------------------------------------------*/ | |
| // {{*}} _enhancedCodebase: The container of everything from other plugins | |
| extendFunc("initialize", function() { | |
| ORIG.initialize.call(this); | |
| // Added to help plugins store all parameter values in game saves | |
| NEW.storeParams.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("playtime", function() { | |
| // Edited to help plugins alter the fps in better ways | |
| return Math.floor(Graphics.frameCount / Graphics.gameFps); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| $.loadParamFuncs = function() { | |
| const pluginParamEntries = Object.entries(this._enhancedCodebase); | |
| pluginParamEntries.forEach(([containerName, container]) => { | |
| Object.entries(container).forEach(([param, val]) => { | |
| // It's to update param functions of other plugins | |
| NEW.storeParamVal.call(this, containerName, param, val); | |
| // Even though it does involve redundant container assignments | |
| }); | |
| }); | |
| }; // $.loadParamFuncs | |
| /** | |
| * The this pointer is Game_System.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| NEW.storeParams = function() { | |
| // Map can't be serialized so ordinary objects must be used | |
| this._enhancedCodebase = {}; | |
| // | |
| }; // NEW.storeParams | |
| NEW._TRY_JSON_PARAM = val => { | |
| try { return JSON.parse(val); } catch (err) { return val; } | |
| }; // NEW._TRY_JSON_PARAM | |
| NEW._JSON_PARAM = val => { | |
| if (!val) return val; | |
| if (Array.isArray(val)) return val.fastMap(v => { | |
| return NEW._JSON_PARAM(NEW._TRY_JSON_PARAM(v)); | |
| }); | |
| if (typeof val === "object" || val instanceof Object) { | |
| return Object.entries(val).reduce((obj, [k, v]) => { | |
| obj[k] = NEW._JSON_PARAM(NEW._TRY_JSON_PARAM(v)); | |
| return obj; | |
| }, {}); | |
| } | |
| const jsonVal = NEW._TRY_JSON_PARAM(val); | |
| return jsonVal === val ? val : NEW._JSON_PARAM(jsonVal); | |
| }; // NEW._JSON_PARAM | |
| NEW._PARSED_PARAMS = params => { // v0.05b+ | |
| Object.entries(params).forEach(([param, val]) => { | |
| params[param] = NEW._JSON_PARAM(val); | |
| }); | |
| return params; | |
| }; // NEW._PARSED_PARAMS | |
| NEW._RAW_PARAMS = pluginName => { | |
| // There's no need to cache it as _RAW_PARAMS should only be called once | |
| const params = PluginManager.parameters(pluginName); | |
| // | |
| if (Object.keys(params) <= 0) alert(`Please check if the filename of | |
| ${pluginName} is ${pluginName}`); | |
| // The original plugin parameter container should never be edited | |
| return NEW._PARSED_PARAMS(JsonEx.makeDeepCopy(params)); | |
| // | |
| }; // NEW._RAW_PARAMS | |
| /** | |
| * The this pointer is Game_System.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {string} pluginName - The name of the plugin to store parameters | |
| * @param {string} containerName - The name of the parameter container | |
| */ | |
| NEW.onStoreParams = function(pluginName, containerName) { | |
| // Map can't be serialized so ordinary objects must be used | |
| this._enhancedCodebase[containerName] = {}; | |
| // | |
| Object.entries(NEW._RAW_PARAMS(pluginName)).forEach(([param, val]) => { | |
| NEW.storeParamVal.call(this, containerName, param, val); | |
| }); | |
| }; // NEW.onStoreParams | |
| /** | |
| * The this pointer is Game_System.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {string} containerName - The name of the parameter container | |
| * @enum @param {string} param - The name of parameter to be stored in saves | |
| * @param {*} val - The value of the parameter to be stored in game saves | |
| */ | |
| NEW.storeParamVal = function(containerName, param, val) { | |
| this._enhancedCodebase[containerName][param] = val; | |
| }; // NEW.storeParamVal | |
| /** | |
| * The this pointer is Game_System.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {string} containerName - The name of the parameter container | |
| * @enum @param {string} param - The name of parameter to be stored in saves | |
| * @returns {*} The value of the parameter to be stored in game saves | |
| */ | |
| NEW.storedParamVal = function(containerName, param) { | |
| return this._enhancedCodebase[containerName][param]; | |
| }; // NEW.storedParamVal | |
| MZ_EC.setupGameSystemParamsIOs = (pluginName, containerName) => { | |
| const { ORIG } = MZ_EC.setKlassContainer(klassName, $, pluginName); | |
| const EC_GS = MZ_EC[klassName].new, GS = pluginName[klassName]; | |
| const PLUGIN_NAME = pluginName.PLUGIN_NAME; | |
| MZ_EC.extendFunc(EC_GS, GS, "storeParams", function() { | |
| ORIG.storeParams.apply(this, arguments); | |
| // Added to store all parameters of this plugin | |
| EC_GS.onStoreParams.call(this, PLUGIN_NAME, containerName); | |
| // | |
| }); // v0.00a - v0.00a | |
| const UPPER_CASE_NAME = name => { | |
| return `${name[0].toUpperCase()}${name.slice(1)}`; | |
| }; // UPPER_CASE_NAME | |
| const CMD_NAME = `set${UPPER_CASE_NAME(containerName)}Param`; | |
| /** | |
| * Script Call/Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {string} param - Name of parameter to be stored in saves | |
| * @param {*} val - The value of the parameter to be stored in saves | |
| */ | |
| $[CMD_NAME] = function(param, val) { | |
| EC_GS.storeParamVal.call(this, containerName, param, val); | |
| }; // $$[CMD_NAME] | |
| /** | |
| * Script Call/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {string} param - Name of parameter to be stored in saves | |
| * @returns {*} The value of the parameter to be stored in game saves | |
| */ | |
| $[`${containerName}Param`] = function(param) { | |
| return EC_GS.storedParamVal.call(this, containerName, param); | |
| }; // $[`${containerName}Param`] | |
| PluginManager.registerCommand(PLUGIN_NAME, CMD_NAME, ({ param, val }) => { | |
| $gameSystem[CMD_NAME](param, JSON.parse(val)); | |
| }); | |
| }; // MZ_EC.setupGameSystemParamsIOs | |
| MZ_EC.setupGameSystemTPBSParamsIOs = (pluginName, containerName) => { | |
| const { ORIG } = MZ_EC.setKlassContainer(klassName, $, pluginName); | |
| const EC_GS = MZ_EC[klassName].new, GS = pluginName[klassName]; | |
| const PLUGIN_NAME = pluginName.PLUGIN_NAME; | |
| MZ_EC.extendFunc(EC_GS, GS, "storeParams", function() { | |
| ORIG.storeParams.apply(this, arguments); | |
| // Added to store all parameters of this plugin | |
| EC_GS.onStoreParams.call(this, PLUGIN_NAME, containerName); | |
| // | |
| }); // v0.00a - v0.00a | |
| const CMD_NAME = `setTPBS${containerName.slice(4)}Param`; | |
| /** | |
| * Script Call/Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {string} param - Name of parameter to be stored in saves | |
| * @param {*} val - The value of the parameter to be stored in saves | |
| */ | |
| $[CMD_NAME] = function(param, val) { | |
| EC_GS.storeParamVal.call(this, containerName, param, val); | |
| }; // $$[CMD_NAME] | |
| /** | |
| * Script Call/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {string} param - Name of parameter to be stored in saves | |
| * @returns {*} The value of the parameter to be stored in game saves | |
| */ | |
| $[`${containerName}Param`] = function(param) { | |
| return EC_GS.storedParamVal.call(this, containerName, param); | |
| }; // $[`${containerName}Param`] | |
| PluginManager.registerCommand(PLUGIN_NAME, CMD_NAME, ({ param, val }) => { | |
| $gameSystem[CMD_NAME](param, JSON.parse(val)); | |
| }); | |
| }; // MZ_EC.setupGameSystemParamsIOs | |
| })(Game_System.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Switches | |
| * - Helps plugins keep the notetag contents in sync with switch changes | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| extendFunc | |
| } = MZ_EC.setKlassContainer("Game_Switches", $, MZ_EC); | |
| NEW._REFRESH_BATTLER = battler => battler.refresh(); | |
| extendFunc("onChange", function() { | |
| ORIG.onChange.apply(this, arguments); | |
| // Added to invalidates all caches of all battlers | |
| MZ_EC.clearAllBattlerNotetagCaches(); | |
| // | |
| }); // v0.00a - v0.00a | |
| })(Game_Switches.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Variables | |
| * - Helps plugins keep the notetag contents in sync with variable change | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const klassName = "Game_Variables", { | |
| NEW, | |
| ORIG, | |
| extendFunc | |
| } = MZ_EC.setKlassContainer(klassName, $, MZ_EC); | |
| extendFunc("setValue", function(variableId, value) { | |
| ORIG.setValue.apply(this, arguments); | |
| // Added to help plugins store all parameter values in game saves | |
| NEW.updateDataNotetags.call(this, variableId, value); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Variables.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {id} varId - The id of the variable to have its values set | |
| * @param {*} val - The new value of the variable to have its values set | |
| */ | |
| NEW.updateDataNotetags = function(varId, val) { | |
| MZ_EC.clearAllBattlerNotetagCaches(); | |
| }; // NEW.updateDataNotetags | |
| MZ_EC.updateGameVarsDataNotetags = (pluginName, containerName) => { | |
| const DM = pluginName.DataManager.new; | |
| const { NEW, ORIG } = MZ_EC.setKlassContainer(klassName, $, pluginName); | |
| const EC_GV = MZ_EC[klassName].new, GV = pluginName[klassName]; | |
| MZ_EC.extendFunc(EC_GV, GV, "updateDataNotetags", function(varId, val) { | |
| ORIG.updateDataNotetags.apply(this, arguments); | |
| // Added to reload all notetag of this plugin to keep script updated | |
| NEW._updateDataNotetags.call(this, varId, val); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Variables.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} varId - The id of the variable to have its values set | |
| * @param {*} val - The new value of the variable to have its values set | |
| */ | |
| NEW._updateDataNotetags = function(varId, val) { | |
| DM.NOTETAG_DATA_CONTAINER_NAMES.forEach((objType, objName) => { | |
| const obj = window[objName]; | |
| MZ_EC.updateDataNotetags(obj, containerName, varId, val); | |
| }); | |
| }; // NEW._updateDataNotetags | |
| }; // MZ_EC.updateGameVarsDataNotetags | |
| })(Game_Variables.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Timer | |
| * - Uses the configurable Graphics fps instead of the constant 60 | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Timer", $, MZ_EC); | |
| rewriteFunc("update", function(sceneActive) { | |
| // Edited to help plugins alter the update behaviors in better ways | |
| if (!NEW._isActive.call(this, sceneActive)) return; | |
| NEW._updateWhenActive.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("seconds", function() { | |
| // Edited to help plugins alter the fps in better ways | |
| return Math.floor(this._frames / Graphics.gameFps); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Timer.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the timer's still active | |
| */ | |
| NEW._isActive = function(sceneActive) { | |
| return sceneActive && this._working && this._frames > 0; | |
| }; // NEW._isActive | |
| /** | |
| * The this pointer is Game_Timer.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._updateWhenActive = function() { | |
| this._frames--; | |
| if (this._frames === 0) this.onExpire(); | |
| }; // NEW._updateWhenActive | |
| })(Game_Timer.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Action | |
| * - Improves performance and code quality and fixes bugs for actions | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const proto = $.prototype; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Action", proto, MZ_EC); | |
| rewriteFunc("decideRandomTarget", function() { | |
| // Edited to help plugins alter decide random target in better ways | |
| const target = NEW._randomTarget.call(this); | |
| // | |
| target ? this._targetIndex = target.index() : this.clear(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeTargets", function() { | |
| // Edited to help plugins alter make targets in better ways | |
| return this.repeatTargets(NEW._madeRawTargets.call(this)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("confusionTarget", function() { | |
| switch (this.subject().confusionLevel()) { | |
| // Edited to help plugins to alter confusion target in better ways | |
| case 1: return NEW._randomOpponentTarget.call(this); | |
| case 2: return NEW._confusionAnyTarget.call(this); | |
| default: return NEW._randomFriendTarget.call(this); | |
| // | |
| } | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("targetsForDead", function(unit) { | |
| // Edited to help plugins alter targets for dead behaviors in better way | |
| if (this.isForOne()) return NEW._targetForOneDead.call(this, unit); | |
| // | |
| return unit.deadMembers(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("targetsForAlive", function(unit) { | |
| // Edited to help plugins alter targets for alive in better ways | |
| if (this.isForOne()) return NEW._targetForOneAlive.call(this, unit); | |
| // | |
| return unit.aliveMembers(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("targetsForDeadAndAlive", function(unit) { | |
| // Edited to help plugins alter targets for dead and alive in better way | |
| if (this.isForOne()) { | |
| return NEW._targetForOneDeadAndAlive.call(this, unit); | |
| } else return unit.members(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("evaluate", function() { | |
| // Edited to help plugins alter evaluate behaviors in better ways | |
| const value = NEW._evalBaseVal.call(this) * this.numRepeats(); | |
| // | |
| return value > 0 ? value + Math.random() : value; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("evaluateWithTarget", function(target) { | |
| /** @todo Figures out whther returning undefined's intentional here */ | |
| if (!this.isHpEffect()) return; | |
| // | |
| // Edited to help plugins fix autobattle leak damage formula side effect | |
| const value = NEW._evalDamageWithoutCri.call(this, target); | |
| // | |
| if (this.isForOpponent()) return value / Math.max(target.hp, 1); | |
| return Math.min(-value, target.mhp - target.hp) / target.mhp; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("apply", function(target) { | |
| const result = target.result(); | |
| this.subject().clearResult(); | |
| result.clear(); | |
| result.used = this.testApply(target); | |
| // Edited to help plugins alter apply behaviors in better ways | |
| result.missed = NEW._isMissed.call(this, target); | |
| result.evaded = NEW._isEvaded.call(this, target); | |
| // | |
| [result.physical, result.drain] = [this.isPhysical(), this.isDrain()]; | |
| // Edited to help plugins alter apply behaviors in better ways | |
| if (result.isHit()) NEW._applyHit.call(this, target); | |
| // | |
| this.updateLastTarget(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeDamageValue", function(target, critical) { | |
| const baseValue = this.evalDamageFormula(target); | |
| // Edited to try up codes essentially being the identical knowledge | |
| return NEW._execDamageVal.call(this, target, critical, baseValue); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("evalDamageFormula", function(target) { | |
| // Edited to help plugins alter eval damage formula in better ways | |
| try { | |
| return NEW._evalDamageFormulaWithoutRescue.call(this, target); | |
| } catch (e) { | |
| NEW._onEvalDamageFormulaErr.call(this, e); | |
| return 0; | |
| } | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectRecoverHp", function(target, effect) { | |
| // Edited to help plugins alter item effect recover hp in better ways | |
| const value = NEW._recoveredHp.call(this, target, effect); | |
| // | |
| if (value === 0) return; | |
| target.gainHp(value); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectRecoverMp", function(target, effect) { | |
| // Edited to help plugins alter item effect recover mp in better ways | |
| const value = NEW._recoveredMp.call(this, target, effect); | |
| // | |
| if (value === 0) return; | |
| target.gainMp(value); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectGainTp", function(target, effect) { | |
| // Edited to help plugins alter item effect gain tp in better ways | |
| const value = NEW._gainedTp.call(this, target, effect); | |
| // | |
| if (value === 0) return; | |
| target.gainTp(value); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectAddAttackState", function(target, effect) { | |
| this.subject().attackStates().forEach(stateId => { | |
| // Edited to help plugins alter item effect add state in better ways | |
| if (!NEW._isAddAtkState.call(this, target, effect, stateId)) return; | |
| // | |
| target.addState(stateId); | |
| this.makeSuccess(target); | |
| }); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectAddNormalState", function(target, effect) { | |
| // Edited to help plugins alter item effect add state in better ways | |
| if (!NEW._isAddNormState.call(this, target, effect)) return; | |
| // | |
| target.addState(effect.dataId); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectRemoveState", function(target, effect) { | |
| // Edited to help plugins alter item effect add debuff in better ways | |
| if (!NEW._isRemoveState.call(this, target, effect)) return; | |
| // | |
| target.removeState(effect.dataId); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("itemEffectAddDebuff", function(target, effect) { | |
| // Edited to help plugins alter item effect add debuff in better ways | |
| if (!NEW._isAddDebuff.call(this, target, effect)) return; | |
| // | |
| target.addDebuff(effect.dataId, effect.value1); | |
| this.makeSuccess(target); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("applyItemUserEffect", function() { | |
| // Edited to help plugins alter apply item user effect in better ways | |
| this.subject().gainSilentTp(NEW._gainedSilentTp.call(this)); | |
| // | |
| }); // v0.00a - v0.00a | |
| $.IS_SHOW_DAMAGE_FORMULA_ERRS = $.IS_CACHE_DAMAGE_FORMULA = false; | |
| $.NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX = new RegExp(".*[};] *", "gim"); | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The damage formula with the side effect parts removed | |
| */ | |
| proto.damageFormulaWithoutSideEffects = function() { | |
| const regex = $.NO_SIDE_EFFECT_DAMAGE_FORMULA_REGEX; | |
| return this.item().damage.formula.replace(regex, ""); | |
| }; // proto.damageFormulaWithoutSideEffects | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since 0.9.5 @version 0.9.5 | |
| * @returns {Game_Battler} The randomnly decided target for this action | |
| */ | |
| NEW._randomTarget = function() { | |
| if (this.isForDeadFriend()) { | |
| return NEW._randomDeadFriendTarget.call(this); | |
| } else if (this.isForFriend()) { | |
| return NEW._randomFriendTarget.call(this); | |
| } return NEW._randomOpponentTarget.call(this); | |
| }; // NEW._randomTarget | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since 0.9.5 @version 0.9.5 | |
| * @returns {Game_Battler} The randomnly decided target for this action | |
| */ | |
| NEW._randomDeadFriendTarget = function() { | |
| return this.friendsUnit().randomDeadTarget(); | |
| }; // NEW._randomDeadFriendTarget | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since 0.9.5 @version 0.9.5 | |
| * @returns {Game_Battler} The randomnly decided target for this action | |
| */ | |
| NEW._randomFriendTarget = function() { | |
| return this.friendsUnit().randomTarget(); | |
| }; // NEW._randomFriendTarget | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since 0.9.5 @version 0.9.5 | |
| * @returns {Game_Battler} The randomnly decided target for this action | |
| */ | |
| NEW._randomOpponentTarget = function() { | |
| return this.opponentsUnit().randomTarget(); | |
| }; // NEW._randomOpponentTarget | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._madeRawTargets = function() { | |
| if (NEW._isForConfused.call(this)) return [this.confusionTarget()]; | |
| if (this.isForEveryone()) return this.targetsForEveryone(); | |
| if (this.isForOpponent()) return this.targetsForOpponents(); | |
| if (this.isForFriend()) return this.targetsForFriends(); | |
| return []; | |
| }; // NEW._madeRawTargets | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the action's for confused targets | |
| */ | |
| NEW._isForConfused = function() { | |
| return !this._forcing && this.subject().isConfused(); | |
| }; // NEW._isForConfused | |
| NEW._IS_CONFUSION_OPPONENTS_TARGET = () => Math.randomInt(2) === 0; | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {[Game_Battler]} The list of confusion targets | |
| */ | |
| NEW._confusionAnyTarget = function() { | |
| if (NEW._IS_CONFUSION_OPPONENTS_TARGET()) { | |
| return NEW._randomOpponentTarget.call(this); | |
| } else return NEW._randomFriendTarget.call(this); | |
| }; // NEW._confusionAnyTarget | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Unit} unit - The list of battlers on the same side | |
| * @returns {[Game_Battler]} The list of dead targets | |
| */ | |
| NEW._targetForOneDead = function(unit) { | |
| return [unit.smoothDeadTarget(this._targetIndex)]; | |
| }; // NEW._targetForOneDead | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Unit} unit - The list of battlers on the same side | |
| * @returns {[Game_Battler]} The list of alive targets | |
| */ | |
| NEW._targetForOneAlive = function(unit) { | |
| if (this._targetIndex < 0) return [unit.randomTarget()]; | |
| return [unit.smoothTarget(this._targetIndex)]; | |
| }; // NEW._targetForOneAlive | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Unit} unit - The list of battlers on the same side | |
| * @returns {[Game_Battler]} The list of dead and alive targets | |
| */ | |
| NEW._targetForOneDeadAndAlive = function(unit) { | |
| return [unit.members()[this._targetIndex]]; | |
| }; // NEW._targetForOneDeadAndAlive | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The evaluated base damage this action | |
| */ | |
| NEW._evalBaseVal = function() { | |
| const targets = this.itemTargetCandidates(); | |
| if (this.isForAll()) return NEW._evalBaseValForAll.call(this, targets); | |
| return NEW._evalBaseValForOne.call(this, targets); | |
| }; // NEW._evalBaseVal | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[Game_Battler]} targets - The list of targets to be evaluated | |
| * @returns {number} The accumulated evaluated base damage of all targets | |
| */ | |
| NEW._evalBaseValForAll = function(targets) { | |
| return targets.reduce((value, target) => { | |
| return value += this.evaluateWithTarget(target); | |
| }, 0); | |
| }; // NEW._evalBaseValForAll | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[Game_Battler]} targets - The list of targets to be evaluated | |
| * @returns {number} The highest evaluated base damage with target index set | |
| */ | |
| NEW._evalBaseValForOne = function(targets) { | |
| let value = 0; | |
| targets.forEach(target => { | |
| const targetValue = this.evaluateWithTarget(target); | |
| if (targetValue <= value) return; | |
| value = targetValue; | |
| this._targetIndex = target.index(); | |
| }); | |
| return value; | |
| }; // NEW._evalBaseValForOne | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target of the action to be evaluated | |
| * @returns {number} The evaluated damage from applying the action to target | |
| */ | |
| NEW._evalDamageWithoutCri = function(target) { | |
| const baseValue = | |
| NEW._tryEvalDamageFormulaWithoutSideEffects.call(this, target); | |
| return NEW._execDamageVal.call(this, target, false, baseValue); | |
| }; // NEW._evalDamageWithoutCri | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target of the action to be evaluated | |
| * @returns {number} The evaluated damage from applying the action to target | |
| */ | |
| NEW._tryEvalDamageFormulaWithoutSideEffects = function(target) { | |
| // Edited to help plugins alter eval damage formula in better ways | |
| try { | |
| return NEW._evalDamageFormulaWithoutSideEffectsRescue.call( | |
| this, target); | |
| } catch (e) { | |
| NEW._onEvalDamageFormulaErr.call(this, e); | |
| return 0; | |
| } | |
| // | |
| }; // NEW._tryEvalDamageFormulaWithoutSideEffects | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target of the action to be evaluated | |
| * @returns {number} The evaluated damage from applying the action to target | |
| */ | |
| NEW._evalDamageFormulaWithoutSideEffectsRescue = function(target) { | |
| /** @todo Figures out if anyone will use sign in damage formula */ | |
| const sign = [3, 4].includes(this.item().damage.type) ? -1 : 1; | |
| // | |
| const damageFormula = this.damageFormulaWithoutSideEffects(), value = | |
| NEW._evalDamageFormula_.call(this, target, sign, damageFormula); | |
| if (!isNaN(value)) return Math.max(value, 0) * sign; | |
| // Edited to help RM users detect and fix damage formula errors | |
| throw new Error(`${damageFormula} doesn't return a number!`); | |
| // | |
| }; // NEW._evalDamageFormulaWithoutSideEffectsRescue | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the action's missed the target | |
| */ | |
| NEW._isMissed = function(target) { | |
| return target.result().used && Math.random() >= this.itemHit(target); | |
| }; // NEW._isMissed | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the action's evaded by the target | |
| */ | |
| NEW._isEvaded = function(target) { | |
| return !target.result().missed && Math.random() < this.itemEva(target); | |
| }; // NEW._isEvaded | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target to be hit by the applied action | |
| */ | |
| NEW._applyHit = function(target) { | |
| if (NEW._isApplyDamage.call(this)) NEW._applyDamage.call(this, target); | |
| this.item().effects.forEach(effect => { | |
| this.applyItemEffect(target, effect); | |
| }); | |
| this.applyItemUserEffect(target); | |
| }; // NEW._applyHit | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target to be hit by the applied action | |
| * @returns {boolean} Whether the applied action has damages | |
| */ | |
| NEW._isApplyDamage = function() { return this.item().damage.type > 0; }; | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target to be hit by the applied action | |
| */ | |
| NEW._applyDamage = function(target) { | |
| const result = target.result(); | |
| result.critical = NEW._isCritical.call(this, target); | |
| const value = this.makeDamageValue(target, result.critical); | |
| this.executeDamage(target, value); | |
| }; // _applyDamage | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target to be hit by the applied action | |
| * @returns {boolean} Whether the applied action damage's critical | |
| */ | |
| NEW._isCritical = function(target) { | |
| return Math.random() < this.itemCri(target); | |
| }; // NEW._isCritical | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target to have damage formula applied | |
| */ | |
| NEW._evalDamageFormulaWithoutRescue = function(target) { | |
| const item = this.item(); | |
| /** @todo Figures out if anyone will use sign in damage formula */ | |
| const sign = [3, 4].includes(item.damage.type) ? -1 : 1; | |
| // | |
| const damageFormula = item.damage.formula, value = | |
| NEW._evalDamageFormula_.call(this, target, sign, damageFormula); | |
| if (!isNaN(value)) return Math.max(value, 0) * sign; | |
| // Edited to help RM users detect and fix damage formula errors | |
| throw new Error(`${damageFormula} doesn't return a number!`); | |
| // | |
| }; // NEW._evalDamageFormulaWithoutRescue | |
| NEW._cachedScripts = new Map(); | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {Game_Battler} b - The target to have damage formula applied | |
| * @enum @param {number} sign - Whether it's damage or recovery(1/-1) | |
| * @enum @param {string} damageFormula - The damage formumal string data | |
| * @returns {number?} The evaluated applied damage of skill/item to target | |
| */ | |
| NEW._evalDamageFormula_ = function(b, sign, damageFormula) { | |
| const item = this.item(); | |
| const [a, v] = [this.subject(), $gameVariables._data]; | |
| if (!$.IS_CACHE_DAMAGE_FORMULA) return eval(damageFormula); | |
| // It's to avoid 1st call being eval and subsequent ones being functions | |
| if (!NEW._cachedScripts.has(damageFormula)) { | |
| const newDamageFormulaFunc = | |
| new Function("item", "a", "b", "v", "sign", damageFormula); | |
| NEW._cachedScripts.set(damageFormula, newDamageFormulaFunc); | |
| } | |
| const damageFormulaFunc = NEW._cachedScripts.get(damageFormula); | |
| return damageFormulaFunc.call(this, item, a, b, v, sign); | |
| // | |
| }; // NEW._evalDamageFormula_ | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Error} e - The error when failing to evaluate the damage formula | |
| */ | |
| NEW._onEvalDamageFormulaErr = function(e) { | |
| // Edited to help RM users detect and fix damage formula errors | |
| if (!$.IS_SHOW_DAMAGE_FORMULA_ERRS) return; | |
| const item = this.item(); | |
| console.warn(`${this._item._dataClass} id:`, item.id); | |
| console.warn("damage formula:", item.damage.formula); | |
| console.warn("error:", e.toString()); | |
| console.warn(e.stack); | |
| // | |
| }; // NEW._onEvalDamageFormulaErr | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The target of the action to be evaluated | |
| * @param {boolean} critical - Whether the target takes a critical hit | |
| * @param {number} baseValue - Base damage from applying action to target | |
| * @returns {number} The executed damage from applying the action to target | |
| */ | |
| NEW._execDamageVal = function(target, critical, baseValue) { | |
| let value = baseValue * this.calcElementRate(target); | |
| if (this.isPhysical()) value *= target.pdr; | |
| if (this.isMagical()) value *= target.mdr; | |
| if (baseValue < 0) value *= target.rec; | |
| if (critical) value = this.applyCritical(value); | |
| value = this.applyVariance(value, this.item().damage.variance); | |
| return Math.round(this.applyGuard(value, target)); | |
| }; // NEW._execDamageVal | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have hp recovered | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {number} Amount of hp recovery applied to the specified target | |
| */ | |
| NEW._recoveredHp = function(target, effect) { | |
| const value = (target.mhp * effect.value1 + effect.value2) * target.rec; | |
| return Math.floor(this.isItem() ? value * this.subject().pha : value); | |
| }; // NEW._recoveredHp | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have mp recovered | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {number} Amount of mp recovery applied to the specified target | |
| */ | |
| NEW._recoveredMp = function(target, effect) { | |
| const value = (target.mmp * effect.value1 + effect.value2) * target.rec; | |
| return Math.floor(this.isItem() ? value * this.subject().pha : value); | |
| }; // NEW._recoveredMp | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have tp gained | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {number} The amount of tp gain applied to the specified target | |
| */ | |
| NEW._gainedTp = function(target, effect) { | |
| // The arugment target's still passed to be used by other plugins | |
| return Math.floor(effect.value1); | |
| // | |
| }; // NEW._gainedTp | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have state added | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @param {id} stateId - The id of the specified attack state to be added | |
| * @returns {boolean} Whether the attack state should be added to the target | |
| */ | |
| NEW._isAddAtkState = function(target, effect, stateId) { | |
| /** @todo Figures out whether it's still right for certain hit attack */ | |
| const chance = effect.value1 * target.stateRate(stateId); | |
| // | |
| const atkStatesRate = this.subject().attackStatesRate(stateId); | |
| const lukEffectRate = this.lukEffectRate(target); | |
| return Math.random() < chance * atkStatesRate * lukEffectRate; | |
| }; // NEW._isAddAtkState | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have state added | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {boolean} Whether the normal state should be added to the target | |
| */ | |
| NEW._isAddNormState = function(target, effect) { | |
| const chance = NEW._addNormStateChance.call(this, target, effect); | |
| return Math.random() < chance; | |
| }; // NEW._isAddNormState | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have state added | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {number} Chance of the normal state to be added to the target | |
| */ | |
| NEW._addNormStateChance = function(target, effect) { | |
| const chance = effect.value1; | |
| if (this.isCertainHit()) return chance; | |
| const stateRate = target.stateRate(effect.dataId); | |
| const lukEffectRate = this.lukEffectRate(target); | |
| return chance * stateRate * lukEffectRate; | |
| }; // NEW._addNormStateChance | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have state removed | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {boolean} Whether the state should be removed from the target | |
| */ | |
| NEW._isRemoveState = function(target, effect) { | |
| // The arugment target's still passed to be used by other plugins | |
| return Math.random() < effect.value1; | |
| // | |
| }; // NEW._isRemoveState | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Battler} target - The specified target to have debuff added | |
| * @param {ItemEffect} effect - The specified item effect applied to target | |
| * @returns {boolean} Whether the debuff should be added to the target | |
| */ | |
| NEW._isAddDebuff = function(target, effect) { | |
| const lukEffectRate = this.lukEffectRate(target); | |
| Math.random() < target.debuffRate(effect.dataId) * lukEffectRate; | |
| }; // NEW._isAddDebuff | |
| /** | |
| * The this pointer is Game_Action.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The new silent tp applied to this action subject | |
| */ | |
| NEW._gainedSilentTp = function() { | |
| return Math.floor(this.item().tpGain * this.subject().tcr); | |
| }; // NEW._gainedSilentTp | |
| })(Game_Action, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_BattlerBase | |
| * - Improves code quality and adds some new battler APIs | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_BattlerBase", $, MZ_EC); | |
| rewriteFunc("resetStateCounts", function(stateId) { | |
| // Edited to help plugins alter reset state counts in better ways | |
| this._stateTurns[stateId] = NEW._newStateCounts.call(this, stateId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateStateTurns", function() { | |
| // Edited to help plugins alter update state turns in better ways | |
| this._states.forEach(NEW._updateStateTurn, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateBuffTurns", function() { | |
| // Edited to help plugins alter update buff turns in better ways | |
| this._buffTurns.forEach((buffTurn, i) => { | |
| NEW._updateBuffTurn.call(this, i); | |
| }); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateBuffTurns", function(buffLevel, paramId) { | |
| // Edited to help plugins alter buff incon index in better ways | |
| if (buffLevel > 0) { | |
| return NEW._positiveBuffIconIndex.call(this, buffLevel, paramId); | |
| } else if (buffLevel < 0) { | |
| return NEW._negativeBuffIconIndex.call(this, buffLevel, paramId); | |
| } else return 0; | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateBuffTurns", function() { | |
| // Edited to help plugins alter is dying behaviors in better ways | |
| return this.isAlive() && NEW._isLowHp.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("sortStates", function() { | |
| // Edited to help plugins alter sort states behaviors in better ways | |
| this._states.sort(NEW._sortState, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("addNewState", function(stateId) { | |
| if (stateId === this.deathStateId()) this.die(); | |
| const wasRestricted = this.isRestricted(); | |
| this._states.push(stateId); | |
| this.sortStates(); | |
| const isRestricted = this.isRestricted(); | |
| if (!wasRestricted && isRestricted) this.onRestrict(); | |
| // Added to help plugins listen to the unrestrict events | |
| if (wasRestricted && !isRestricted) this.onUnrestrict(); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| $.onUnrestrict = function() {}; | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} stateId - The id of the state to have its turn count reset | |
| * @returns {number} The reset state count of the state with the state id | |
| */ | |
| NEW._newStateCounts = function(stateId) { | |
| const { maxTurns, minTurns } = $dataStates[stateId]; | |
| return minTurns + Math.randomInt(1 + Math.max(maxTurns - minTurns, 0)); | |
| }; // NEW._newStateCounts | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Updates the turn counter of the state with the specified state id | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} stateId - The id of the state to have its turn count updated | |
| */ | |
| NEW._updateStateTurn = function(stateId) { | |
| if (this._stateTurns[stateId] > 0) this._stateTurns[stateId]--; | |
| }; // NEW._updateStateTurn | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Updates the turn counter of the buff with the specified parameter id | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - Param id of the buff to have its turn updated | |
| */ | |
| NEW._updateBuffTurn = function(paramId) { | |
| if (this._buffTurns[paramId] > 0) this._buffTurns[paramId]--; | |
| }; // NEW._updateBuffTurn | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} bufflevel - The current buff level of this battler | |
| * @param {index} paramId - The param id of the current buff of this battler | |
| * @returns {index} The icon index of the current buff of this battler | |
| */ | |
| NEW._positiveBuffIconIndex = function(buffLevel, paramId) { | |
| const iconStart = Game_BattlerBase.ICON_BUFF_START; | |
| return iconStart + (buffLevel - 1) * 8 + paramId; | |
| }; // NEW._positiveBuffIconIndex | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} bufflevel - The current debuff level of this battler | |
| * @param {index} paramId - Param id of the current debuff of this battler | |
| * @returns {index} The icon index of the current debuff of this battler | |
| */ | |
| NEW._negativeBuffIconIndex = function(buffLevel, paramId) { | |
| const iconStart = Game_BattlerBase.ICON_DEBUFF_START; | |
| return iconStart + (-buffLevel - 1) * 8 + paramId; | |
| }; // NEW._negativeBuffIconIndex | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the battler's current hp's considered as low | |
| */ | |
| NEW._isLowHp = function() { return this._hp < this.mhp / 4; }; | |
| /** | |
| * The this pointer is Game_BattlerBase.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} damage - Amount of damage right before applying critical | |
| * @returns {number} State sorting direction(-ve: ascending/+ve: descending) | |
| */ | |
| NEW._sortState = function(a, b) { | |
| const [p1, p2] = [$dataStates[a].priority, $dataStates[b].priority]; | |
| return p1 !== p2 ? p2 - p1 : a - b; | |
| }; // NEW._sortState | |
| })(Game_BattlerBase.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Battler | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const $$ = Game_BattlerBase.prototype, { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Battler", $, MZ_EC); | |
| extendFunc("refresh", function() { | |
| ORIG.refresh.apply(this, arguments); | |
| // Edited to ensures the battler notetags will return updated results | |
| MZ_EC.clearBattlerNotetagCache(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("applyTpbPenalty", function() { | |
| this._tpbState = "charging"; | |
| // Edited to help plugins alter apply tpb penalty in better ways | |
| this._tpbChargeTime = NEW._tpbChargeTimeWithPenalty.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("initTpbChargeTime", function(advantageous, disadvantageous) { | |
| this._tpbState = "charging"; | |
| // Edited to help plugins alter init tpb charge time in better ways | |
| this._tpbChargeTime = NEW._initializedTpbChargeTime.call( | |
| this, advantageous, disadvantageous); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTpb", function() { | |
| // Edited to help plugins alter update tpb behaviors in better ways | |
| if (this.canMove()) NEW._updateTpbWhenMovable.call(this); | |
| // | |
| if (this.isAlive()) this.updateTpbIdleTime(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTpbChargeTime", function() { | |
| // Edited to help plugins alter update tpb charge time in better ways | |
| if (this.isTpbCharging()) NEW._onUpdateTpbChargeTime.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTpbCastTime", function() { | |
| // Edited to help plugins alter update tpb cast time in better ways | |
| if (this.isTpbCasting()) NEW._onUpdateTpbCastTime.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTpbAutoBattle", function() { | |
| // Edited to help plugins alter update tpb auto battle in better ways | |
| if (NEW._isMakeAutoTpbActs.call(this)) this.makeTpbActions(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateTpbIdleTime", function() { | |
| // Edited to help plugins alter update tpb idle time in better ways | |
| if (this.isTpbIdle()) NEW._onUpdateTpbIdleTime.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("tpbRequiredCastTime", function() { | |
| // Edited to help plugins alter tpb required case time in better ways | |
| return Math.sqrt(NEW._tpbCastDelay.call(this)) / this.tpbSpeed(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeTpbActions", function() { | |
| this.makeActions(); | |
| if (this.canInput()) return this.setActionState("undecided"); | |
| // Edited to help plugins alter make tpb actions in better ways | |
| NEW._onAutoInputTpbActs.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("addState", function(stateId) { | |
| // Edited to help plugins alter add state behaviors in better ways | |
| if (this.isStateAddable(stateId)) NEW._onAddState.call(this, stateId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onRestrict", function() { | |
| $$.onRestrict.call(this); | |
| this.clearTpbChargeTime(); | |
| this.clearActions(); | |
| // Edited to help plugins alter on restrict behaviors in better ways | |
| this.states().forEach(NEW._removeStateByRestriction, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeState", function(stateId) { | |
| // Edited to help plugins alter remove state behaviors in better ways | |
| if (!this.isStateAffected(stateId)) return; | |
| NEW._onRemoveState.call(this, stateId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("addBuff", function(paramId, turns) { | |
| // Edited to help plugins alter add buff behaviors in better ways | |
| if (this.isAlive()) NEW._onAddBuff.call(this, paramId, turns); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("addDebuff", function(paramId, turns) { | |
| // Edited to help plugins alter add debuff behaviors in better ways | |
| if (this.isAlive()) NEW._onAddDebuff.call(this, paramId, turns); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeBuff", function(paramId) { | |
| // Edited to help plugins alter remove buff behaviors in better ways | |
| if (!NEW._isRemoveBuff.call(this, paramId)) return; | |
| NEW._onRemoveBuff.call(this, paramId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeBattleStates", function() { | |
| // Edited to help plugins alter remove battle states in better ways | |
| this.states().forEach(NEW._removeBattleState, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeStatesAuto", function(timing) { | |
| // Edited to help plugins alter remove states auto in better ways | |
| this.states().forEach(state => { | |
| NEW._removeStateAuto.call(this, timing, state); | |
| }); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeBuffsAuto", function() { | |
| for (let i = 0, l = this.buffLength(); i < l; i++) { | |
| // Edited to help plugins alter remove buffs auto in better ways | |
| NEW._removeBuffAuto.call(this, i); | |
| // | |
| } | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeStatesByDamage", function() { | |
| // Edited to help plugins remove states by damage in better ways | |
| this.states().forEach(NEW._removeStateByDamage, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeActions", function() { | |
| this.clearActions(); | |
| // Edited to help plugins alter make actions behaviors in better ways | |
| if (this.canMove()) NEW._makeActsWhenMovable.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("forceAction", function(skillId, targetIndex) { | |
| this.clearActions(); | |
| // Edited to help plugins alter force action behaviors in better ways | |
| this._actions.push(NEW._forcedAct.call(this, skillId, targetIndex)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("initTp", function() { | |
| // Edited to help plugins alter init tp behaviors in better ways | |
| this.setTp(NEW._initializedTp.call(this)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("chargeTpByDamage", function(damageRate) { | |
| // Edited to help plugins alter charge tp by damage in better ways | |
| this.gainSilentTp(NEW._chargedTpByDamage.call(this, damageRate)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("regenerateHp", function() { | |
| // Edited to help plugins alter regenerate hp behaviors in better ways | |
| const value = NEW._regeneratedHp.call(this); | |
| // | |
| if (value !== 0) this.gainHp(value); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("regenerateMp", function() { | |
| // Edited to help plugins alter regenerate mp behaviors in better ways | |
| const value = NEW._regeneratedMp.call(this); | |
| // | |
| if (value !== 0) this.gainMp(value); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("regenerateTp", function() { | |
| // Edited to help plugins alter regenerate tp behaviors in better ways | |
| this.gainSilentTp(NEW._regeneratedTp.call(this)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("regenerateAll", function() { | |
| // Edited to help plugins alter regenerate all behaviors in better ways | |
| if (this.isAlive()) NEW._regenerateAlive.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onBattleStart", function(advantageous, disadvantageous) { | |
| this.setActionState("undecided"); | |
| this.clearMotion(); | |
| // Edited to help plugins alter on battle start in better ways | |
| this.initTpbChargeTime(advantageous, disadvantageous); | |
| // | |
| this.initTpbTurn(); | |
| if (!this.isPreserveTp()) this.initTp(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The proportion of the skill/item casting progress | |
| */ | |
| $.tpbCastTime = function() { return this._tpbCastTime; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The proportion of the battler idling progress | |
| */ | |
| $.tpbIdleTime = function() { return this._tpbIdleTime; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's executing actions | |
| */ | |
| $.isTpbActing = function() { return this._tpbState === "acting"; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's charging the tpb bar | |
| */ | |
| $.isTpbCharging = function() { return this._tpbState === "charging"; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's idling | |
| */ | |
| $.isTpbIdling = function() { | |
| return this.isTpbCharged() && this._tpbIdleTime > 0; | |
| }; // $.isTpbIdling | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's casting tpb actions | |
| */ | |
| $.isTpbCasting = function() { return this._tpbState === "casting"; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| $.onTpbReady = function() { this._tpbState = "ready"; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's just ended charging tpb bar | |
| */ | |
| $.isEndTpbCharging = function() { return this._tpbChargeTime >= 1; }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's just ended casting actions | |
| */ | |
| $.isEndTpbCasting = function() { | |
| return this._tpbCastTime >= this.tpbRequiredCastTime(); | |
| }; // $.isEndTpbCasting | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the tpb battler's in the idle state | |
| */ | |
| $.isTpbIdle = function() { return !this.canMove() || this.isTpbCharged(); }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The new TPBS charge time value with the penalty applied | |
| */ | |
| NEW._tpbChargeTimeWithPenalty = function() { | |
| return this._tpbChargeTime - 1; | |
| }; // NEW._tpbChargeTimeWithPenalty | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {boolean} advantageous - Whether battler has advantageous start | |
| * @param {boolean} disadvantageous - If battler has disadvantageous start | |
| * @returns {number} The starting tpb bar charged proportion for the battler | |
| */ | |
| NEW._initializedTpbChargeTime = function(advantageous, disadvantageous) { | |
| // disadvantageous is added to be used by other plugins | |
| if (this.isRestricted()) return 0; | |
| return advantageous ? 1 : NEW._initializedNormTpbChargeTime.call(this); | |
| // | |
| }; // NEW._initializedTpbChargeTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The starting tpb bar charged proportion for the battler | |
| */ | |
| NEW._initializedNormTpbChargeTime = function() { | |
| return this.tpbRelativeSpeed() * Math.random() * 0.5; | |
| }; // NEW._initializedNormTpbChargeTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._updateTpbWhenMovable = function() { | |
| this.updateTpbChargeTime(); | |
| this.updateTpbCastTime(); | |
| this.updateTpbAutoBattle(); | |
| }; // NEW._updateTpbWhenMovable | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._onUpdateTpbChargeTime = function() { | |
| this._tpbChargeTime = NEW._updatedTpbChargeTime.call(this); | |
| if (!this.isEndTpbCharging()) return; | |
| this._tpbChargeTime = 1; | |
| this.onTpbCharged(); | |
| }; // NEW._onUpdateTpbChargeTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The updated tpb charge time value | |
| */ | |
| NEW._updatedTpbChargeTime = function() { | |
| return this._tpbChargeTime + this.tpbAcceleration(); | |
| }; // NEW._updatedTpbChargeTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| NEW._onUpdateTpbCastTime = function() { | |
| this._tpbCastTime = NEW._updatedTpbCastTime.call(this); | |
| if (!this.isEndTpbCasting()) return; | |
| this._tpbCastTime = this.tpbRequiredCastTime(); | |
| this.onTpbReady(); | |
| }; // NEW._onUpdateTpbCastTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The updated tpb cast time value | |
| */ | |
| NEW._updatedTpbCastTime = function() { | |
| return this._tpbCastTime + this.tpbAcceleration(); | |
| }; // NEW._updatedTpbCastTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the autobattle battlers will make tpb actions | |
| */ | |
| NEW._isMakeAutoTpbActs = function() { | |
| if (!this.isTpbCharged() || this.isTpbTurnEnd()) return false; | |
| return this.isAutoBattle(); | |
| }; // NEW._isMakeAutoTpbActs | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @todo Figures out why isTpbTimeout and onTpbTimeout aren't called here | |
| */ | |
| NEW._onUpdateTpbIdleTime = function() { | |
| this._tpbIdleTime = NEW._updatedTpbIdleTime.call(this); | |
| }; // NEW._onUpdateTpbIdleTime | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The updated tpb idle time value | |
| */ | |
| NEW._updatedTpbIdleTime = function() { | |
| return this._tpbIdleTime + this.tpbAcceleration(); | |
| }; // NEW._updatedTpbIdleTime | |
| NEW._IS_VALID_FUNC = act => act.isValid(); | |
| NEW._ITEM_FUNC = act => act.item(); | |
| NEW._ACCUM_SPEED_FUNC = (delay, { speed }) => delay + Math.max(0, -speed); | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The casting delay of the action to be executed | |
| */ | |
| NEW._tpbCastDelay = function() { | |
| /** @todo Uses filterMapReduce if it's faster than filterMap.reduce */ | |
| return this._actions.filterMap(NEW._IS_VALID_FUNC, NEW._ITEM_FUNC). | |
| reduce(NEW._ACCUM_SPEED_FUNC, 0); | |
| // | |
| }; // NEW._tpbCastDelay | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._onAutoInputTpbActs = function() { | |
| this.startTpbCasting(); | |
| this.setActionState("waiting"); | |
| }; // NEW._onAutoInputTpbActs | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} stateId - The id of the state to be added to this battler | |
| */ | |
| NEW._onAddState = function(stateId) { | |
| if (!this.isStateAffected(stateId)) { | |
| NEW._onAddNewState.call(this, stateId); | |
| } | |
| this.resetStateCounts(stateId); | |
| this._result.pushAddedState(stateId); | |
| }; // NEW._onAddState | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} stateId - The id of the new state to be added to this battler | |
| */ | |
| NEW._onAddNewState = function(stateId) { | |
| this.addNewState(stateId); | |
| this.refresh(); | |
| }; // NEW._onAddNewState | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataState} state - The state to be removed upon restriction | |
| */ | |
| NEW._removeStateByRestriction = function(state) { | |
| if (state.removeByRestriction) this.removeState(state.id); | |
| }; // NEW._removeStateByRestriction | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} stateId - The id of the state to be removed from this battler | |
| */ | |
| NEW._onRemoveState = function(stateId) { | |
| if (stateId === this.deathStateId()) this.revive(); | |
| this.eraseState(stateId); | |
| this.refresh(); | |
| this._result.pushRemovedState(stateId); | |
| }; // NEW._onRemoveState | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - The parameter id of the buff to be added | |
| * @param {number} turns - The number of turns of the buff to be added | |
| */ | |
| NEW._onAddBuff = function(paramId, turns) { | |
| this.increaseBuff(paramId); | |
| if (this.isBuffAffected(paramId)) { | |
| this.overwriteBuffTurns(paramId, turns); | |
| } | |
| this._result.pushAddedBuff(paramId); | |
| this.refresh(); | |
| }; // NEW._onAddBuff | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - The parameter id of the debuff to be added | |
| * @param {number} turns - The number of turns of the debuff to be added | |
| */ | |
| NEW._onAddDebuff = function(paramId, turns) { | |
| this.decreaseBuff(paramId); | |
| if (this.isDebuffAffected(paramId)) { | |
| this.overwriteBuffTurns(paramId, turns); | |
| } | |
| this._result.pushAddedDebuff(paramId); | |
| this.refresh(); | |
| }; // NEW._onAddDebuff | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - The parameter id of the buff to be removed | |
| * @returns {boolean} Whether the specified buff's to be removed | |
| */ | |
| NEW._isRemoveBuff = function(paramId) { | |
| return this.isAlive() && this.isBuffOrDebuffAffected(paramId); | |
| }; // NEW._isRemoveBuff | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - The parameter id of the buff to be removed | |
| */ | |
| NEW._onRemoveBuff = function(paramId) { | |
| this.eraseBuff(paramId); | |
| this._result.pushRemovedBuff(paramId); | |
| this.refresh(); | |
| }; // NEW._onRemoveBuff | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataState} state - Data of the state to be removed on battle end | |
| */ | |
| NEW._removeBattleState = function(state) { | |
| if (state.removeAtBattleEnd) this.removeState(state.id); | |
| }; // NEW._removeBattleState | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {number} timing - 1 is action end and 2 is turn end | |
| * @param {DataState} state - Data of the state to be removed automatically | |
| */ | |
| NEW._removeStateAuto = function(timing, state) { | |
| if (!NEW._isRemoveStateAuto.call(this, timing, state)) return; | |
| this.removeState(state.id); | |
| }; // NEW._removeStateAuto | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @enum @param {number} timing - 1 is action end and 2 is turn end | |
| * @param {DataState} state - Data of the state to be removed automatically | |
| * @returns {boolean} Whether the state's automatically removed from battler | |
| */ | |
| NEW._isRemoveStateAuto = function(timing, state) { | |
| if (!this.isStateExpired(state.id)) return; | |
| return state.autoRemovalTiming === timing; | |
| }; // NEW._isRemoveStateAuto | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} paramId - The parameter id of the buff to be removed | |
| */ | |
| NEW._removeBuffAuto = function(paramId) { | |
| if (this.isBuffExpired(paramId)) this.removeBuff(paramId); | |
| }; // NEW._removeBuffAuto | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataState} state - The data of the state to be removed by damage | |
| */ | |
| NEW._removeStateByDamage = function(state) { | |
| if (!NEW._isRemoveStateByDamage.call(this, state)) return; | |
| this.removeState(state.id); | |
| }; // NEW._removeStateByDamage | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataState} state - The data of the state to be removed by damage | |
| * @returns {boolean} Whether the state's to be removed by daamge | |
| */ | |
| NEW._isRemoveStateByDamage = function(state) { | |
| if (!state.removeByDamage) return false; | |
| return Math.randomInt(100) < state.chanceByDamage; | |
| }; // NEW._isRemoveStateByDamage | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._makeActsWhenMovable = function() { | |
| /** @todo Figures out why it's needed when clearActions is called */ | |
| this._actions = []; | |
| // | |
| const actionTimes = this.makeActionTimes(); | |
| for (let i = 0; i < actionTimes; i++) { | |
| this._actions.push(new Game_Action(this)); | |
| } | |
| }; // NEW._makeActsWhenMovable | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} skillId - The id of the skill as this new forced action | |
| * @param {index} targetIndex - The index of the target of the forced action | |
| * @returns {Game_Action} The newly creted forced action of this battler | |
| */ | |
| NEW._forcedAct = function(skillId, targetIndex) { | |
| const action = new Game_Action(this, true); | |
| action.setSkill(skillId); | |
| if (targetIndex === -2) { | |
| action.setTarget(this._lastTargetIndex); | |
| } else if (targetIndex === -1) { | |
| action.decideRandomTarget(); | |
| } else action.setTarget(targetIndex); | |
| return action; | |
| }; // NEW._forcedAct | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The amount of tp intiialized for this battler | |
| */ | |
| NEW._initializedTp = function() { return Math.randomInt(25); }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} damageRate - The proportion of the battler hp damaged | |
| * @returns {number} The amount of tp charged by damage for this battler | |
| */ | |
| NEW._chargedTpByDamage = function(damageRate) { | |
| return Math.floor(50 * damageRate * this.tcr); | |
| }; // NEW._chargedTpByDamage | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The amount of hp regenerated for this battler | |
| */ | |
| NEW._regeneratedHp = function() { | |
| return Math.max(Math.floor(this.mhp * this.hrg), -this.maxSlipDamage()); | |
| }; // NEW._regeneratedHp | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The amount of mp regenerated for this battler | |
| */ | |
| NEW._regeneratedMp = function() { return Math.floor(this.mmp * this.mrg); }; | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The amount of tp regenerated for this battler | |
| */ | |
| NEW._regeneratedTp = function() { | |
| return Math.floor(this.maxTp() * this.trg); | |
| }; // NEW._regeneratedTp | |
| /** | |
| * The this pointer is Game_Battler.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._regenerateAlive = function() { | |
| this.regenerateHp(); | |
| this.regenerateMp(); | |
| this.regenerateTp(); | |
| }; // NEW._regenerateAlive | |
| })(Game_Battler.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Actor | |
| * - Improves performance and code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const $$ = Game_Battler.prototype, { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Actor", $, MZ_EC); | |
| rewriteFunc("initSkills", function() { | |
| this._skills = []; | |
| // Edited to help plugins alter init skills behaviors in better ways | |
| this.currentClass().learnings.forEach(NEW._initLearntSkill, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("initEquips", function(equips) { | |
| // Edited to help plugins alter init equips behaviors in better ways | |
| this._equips = NEW._initializedEquips.call(this, equips); | |
| // | |
| this.releaseUnequippableItems(true); | |
| this.refresh(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("changeEquip", function(slotId, item) { | |
| // Edited to help plugins alter change equip behaviors in better ways | |
| if (!NEW._isChangeEquip.call(this, slotId, item)) return; | |
| NEW._onChangeEquip.call(this, slotId, item); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("tradeItemWithParty", function(newItem, oldItem) { | |
| if (newItem && !$gameParty.hasItem(newItem)) return false; | |
| // Edited to help plugins alter trade item with party in better ways | |
| NEW._onTradeItemWithParty.call(this, newItem, oldItem); | |
| // | |
| return true; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("releaseUnequippableItems", function(forcing) { | |
| const slots = this.equipSlots(); | |
| // Edited to help plugins alter release unequippable items in better way | |
| this._equips.forEach((equip, i) => { | |
| // There's no need to loop through equips multiple times | |
| NEW._releaseUnequippableItem.call(this, forcing, equip, slots[i]); | |
| // | |
| }); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("attackElements", function() { | |
| const set = $$.attackElements.call(this); | |
| // Edited to help plugins alter attack elements behaviors in better ways | |
| if (NEW._isIncludeBareHandElem.call(this, set)) { | |
| set.push(this.bareHandsElementId()); | |
| } | |
| // | |
| return set; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("changeExp", function(exp, show) { | |
| this._exp[this._classId] = Math.max(exp, 0); | |
| const [lastLevel, lastSkills] = [this._level, this.skills()]; | |
| // Edited to help plugins alter change exp behaviors in better ways | |
| while (NEW._isLevelUp.call(this)) this.levelUp(); | |
| while (NEW._isLevelDown.call(this)) this.levelDown(); | |
| if (NEW._isDisplayLevelUp.call(this, show, lastLevel)) { | |
| this.displayLevelUp(this.findNewSkills(lastSkills)); | |
| } | |
| // | |
| this.refresh(); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("levelUp", function() { | |
| this._level++; | |
| // Edited to help plugins alter level up behaviors in better ways | |
| this.currentClass().learnings.forEach(NEW._learnLevelUpSkill, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("gainExp", function(exp) { | |
| // Edited to help plugins alter gain exp behaviors in better ways | |
| const newExp = NEW._gainedExp.call(this, exp); | |
| // | |
| this.changeExp(newExp, this.shouldDisplayLevelUp()); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("learnSkill", function(skillId) { | |
| // Edited to help plugins alter learn skill behaviors in better ways | |
| if (this.isLearnedSkill(skillId)) return; | |
| NEW._onLearnSkill.call(this, skillId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("performAttack", function() { | |
| // Edited to help plugins alter perform attack behaviors in better ways | |
| const attackMotion = NEW._performedAtkMotion.call(this); | |
| if (attackMotion) NEW._performAtkMotion.call(this, attackMotion); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeAutoBattleActions", function() { | |
| // Edited to help plugins alter make auto battle actions in better ways | |
| NEW._setAutoBattleActs.call(this); | |
| // | |
| this.setActionState("waiting"); | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("onPlayerWalk", function() { | |
| this.clearResult(); | |
| this.checkFloorEffect(); | |
| // Edited to help plugins alter on player walk behaviors in better ways | |
| if ($gamePlayer.isNormal()) NEW._onNormPlayerWalk.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("showAddedStates", function() { | |
| // Edited to help plugins alter show added states in better ways | |
| this.result().addedStateObjects().forEach(NEW._showAddedState, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("showRemovedStates", function() { | |
| // Edited to help plugins alter show removed states in better ways | |
| this.result().removedStateObjects().forEach( | |
| NEW._showRemovedState, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("turnEndOnMap", function() { | |
| // Edited to help plugins alter turn end on map behaviors in better ways | |
| if (NEW._isTurnEndOnMap.call(this)) NEW._onTurnEndOnMap.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("executeFloorDamage", function() { | |
| // Edited to help plugins alter execute floor damage in better ways | |
| const realDamage = NEW._realFloorDamage.call(this); | |
| // | |
| this.gainHp(-realDamage); | |
| if (realDamage > 0) this.performMapDamage(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataLearning} learning - The skill that can be learned by actor | |
| */ | |
| NEW._initLearntSkill = function(learning) { | |
| if (!NEW._isInitLearntSkill.call(this, learning)) return; | |
| this.learnSkill(learning.skillId); | |
| }; // NEW._initLearntSkill | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataLearning} learning - The skill that can be learned by actor | |
| * @returns {boolean} Whether actor will learn skill upon initialization | |
| */ | |
| NEW._isInitLearntSkill = function(learning) { | |
| return learning.level <= this._level; | |
| }; // NEW._isInitLearntSkill | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[DatumEquip]} equips - List of data of equipments to initialize | |
| * @returns {[Game_Item]} The list of initialized equipments of this actor | |
| */ | |
| NEW._initializedEquips = function(equips) { | |
| const equipNum = equips.length; | |
| return this.equipSlots().fastMap((slot, i) => { | |
| const item = new Game_Item(); | |
| if (i < equipNum) item.setEquip(slot === 1, equips[i]); | |
| return item; | |
| }); | |
| }; // NEW._initializedEquips | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} slotId - The index of the equipment slot to be cleared | |
| * @param {DataEquip} item - New equipment as the replacement for the slot | |
| * @returns {boolean} Whether the current equip in the slot's to be changed | |
| */ | |
| NEW._isChangeEquip = function(slotId, item) { | |
| if (!this.tradeItemWithParty(item, this.equips()[slotId])) return false; | |
| return !item || this.equipSlots()[slotId] === item.etypeId; | |
| }; // NEW._isChangeEquip | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} slotId - The index of the equipment slot to be cleared | |
| * @param {DataEquip} item - New equipment as the replacement for the slot | |
| */ | |
| NEW._onChangeEquip = function(slotId, item) { | |
| this._equips[slotId].setObject(item); | |
| this.refresh(); | |
| }; // NEW._onChangeEquip | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataEquip|DataItem} newItem - The new item from party to actor | |
| * @param {DataEquip|DataItem} oldItem - The old item from actor to party | |
| */ | |
| NEW._onTradeItemWithParty = function(newItem, oldItem) { | |
| $gameParty.gainItem(oldItem, 1); | |
| $gameParty.loseItem(newItem, 1); | |
| }; // NEW._onTradeItemWithParty | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} slotId - The index of the equipment slot to be cleared | |
| */ | |
| NEW._clearEquip = function(slotId) { | |
| if (this.isEquipChangeOk(slotId)) this.changeEquip(slotId, null); | |
| }; // NEW._clearEquip | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {index} slotId - The index of the slot to have the optimized equip | |
| */ | |
| NEW._optimizeEquip = function(slotId) { | |
| if (!this.isEquipChangeOk(slotId)) return; | |
| this.changeEquip(slotId, this.bestEquipItem(slotId)); | |
| }; // NEW._optimizeEquip | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {boolean} forcing - Whether the equip's forcibly released | |
| * @param {Game_Item} equip - The unequippable item to be released | |
| * @param {number} slot - The type of the slot of the specified equipment | |
| */ | |
| NEW._releaseUnequippableItem = function(forcing, equip, slot) { | |
| if (!NEW._isUnequippableItem.call(this, equip.object(), slot)) return; | |
| NEW._onReleaseUnequippableItem.call(this, forcing, equip); | |
| }; // NEW._releaseUnequippableItem | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataEquip} item - The data of the equipment to be checked against | |
| * @param {number} slot - The type of the slot of the specified equipment | |
| * @returns {boolean} Whether the equip's not equippable to the slot | |
| */ | |
| NEW._isUnequippableItem = function(item, slot) { | |
| return item && (!this.canEquip(item) || item.etypeId !== slot); | |
| }; // NEW._isUnequippableItem | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {boolean} forcing - Whether the equip's forcibly released | |
| * @param {Game_Item} equip - The unequippable item to be released | |
| */ | |
| NEW._onReleaseUnequippableItem = function(forcing, equip) { | |
| if (!forcing) this.tradeItemWithParty(null, equip.object()); | |
| equip.setObject(null); | |
| }; // NEW._onReleaseUnequippableItem | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[DatumTrait]} set - The set of base attack elements of this actor | |
| * @returns {boolean} Whether attack elements should include barehand ones | |
| */ | |
| NEW._isIncludeBareHandElem = function(set) { | |
| return this.hasNoWeapons() && !set.includes(this.bareHandsElementId()); | |
| }; // NEW._isIncludeBareHandElem | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the level of this actor should be increased | |
| */ | |
| NEW._isLevelUp = function() { | |
| return !this.isMaxLevel() && this.currentExp() >= this.nextLevelExp(); | |
| }; // NEW._isLevelUp | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the level of this actor should be decreased | |
| */ | |
| NEW._isLevelDown = function() { | |
| return this.currentExp() < this.currentLevelExp(); | |
| }; // NEW._isLevelDown | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {boolean} show - Whether the level up display can be shown | |
| * @param {number} lastLevel - The last level of actor before exp changes | |
| * @returns {boolean} Whether the level up of this actor will be displayed | |
| */ | |
| NEW._isDisplayLevelUp = function(show, lastLevel) { | |
| return show && this._level > lastLevel; | |
| }; // NEW._isDisplayLevelUp | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataLearning} learning - The skill that can be learned by actor | |
| */ | |
| NEW._learnLevelUpSkill = function(learning) { | |
| if (!NEW._isLearnLevelUpSkill.call(this, learning)) return; | |
| this.learnSkill(learning.skillId); | |
| }; // NEW._learnLevelUpSkill | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataLearning} learning - The skill that can be learned by actor | |
| * @returns {boolean} Whether this actor will learn this skill upon level up | |
| */ | |
| NEW._isLearnLevelUpSkill = function(learning) { | |
| return learning.level === this._level; | |
| }; // NEW._isLearnLevelUpSkill | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} exp - The raw amount of experience gained | |
| * @returns {number} The new total number of experience of this actor | |
| */ | |
| NEW._gainedExp = function(exp) { | |
| return this.currentExp() + Math.round(exp * this.finalExpRate()); | |
| }; // NEW._gainedExp | |
| NEW._ASCENDING_SORT = (a, b) => a - b; | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._onLearnSkill = function(skillId) { | |
| this._skills.push(skillId); | |
| this._skills.sort(NEW._ASCENDING_SORT); | |
| }; // NEW._onLearnSkill | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {DataMotion} The data of the attack motion to be performed | |
| */ | |
| NEW._performedAtkMotion = function() { | |
| /** @todo Dries up these codes representing identical knowledge */ | |
| const firstWeapon = this.weapons()[0]; | |
| return $dataSystem.attackMotions[firstWeapon ? firstWeapon.wtypeId : 0]; | |
| // | |
| }; // NEW._performedAtkMotion | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataMotion} attackMotion - The attack motion to be performed | |
| */ | |
| NEW._performAtkMotion = function(attackMotion) { | |
| const { type, weaponImageId } = attackMotion; | |
| if (type === 0) { | |
| this.requestMotion("thrust"); | |
| } else if (type === 1) { | |
| this.requestMotion("swing"); | |
| } else if (type === 2) this.requestMotion("missile"); | |
| this.startWeaponAnimation(weaponImageId); | |
| }; // NEW._performAtkMotion | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._setAutoBattleActs = function() { | |
| const action = NEW._autoBattleAct.call(this); | |
| for (let i = 0, numActions = this.numActions(); i < numActions; i++) { | |
| // It's pointless to evaluate the same action multiple times | |
| this.setAction(i, action); | |
| // | |
| } | |
| }; // NEW._setAutoBattleActs | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the actor's turn has ended on the game map | |
| */ | |
| NEW._autoBattleAct = function() { | |
| let maxValue = -Number.MAX_VALUE, bestAct; | |
| this.makeActionList().forEach(action => { | |
| const value = action.evaluate(); | |
| if (value > maxValue) [maxValue, bestAct] = [value, action]; | |
| }); | |
| return bestAct; | |
| }; // NEW._autoBattleAct | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._onNormPlayerWalk = function() { | |
| this.turnEndOnMap(); | |
| this.states().forEach(this.updateStateSteps, this); | |
| this.showAddedStates(); | |
| this.showRemovedStates(); | |
| }; // NEW._onNormPlayerWalk | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {state} - The state for this actor to have its message shown | |
| */ | |
| NEW._showAddedState = function(state) { | |
| NEW._showState.call(this, state.message1); | |
| }; // NEW._showAddedState | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {state} - The state for this actor to have its message shown | |
| */ | |
| NEW._showRemovedState = function(state) { | |
| NEW._showState.call(this, state.message4); | |
| }; // NEW._showRemovedState | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {msg} - The message of the state for this actor to be shown | |
| */ | |
| NEW._showState = function(msg) { | |
| if (msg) $gameMessage.add(msg.format(this._name)); | |
| }; // NEW._showState | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the actor's turn has ended on the game map | |
| */ | |
| NEW._isTurnEndOnMap = function() { | |
| return $gameParty.steps() % this.stepsForTurn() === 0; | |
| }; // NEW._isTurnEndOnMap | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Potential Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._onTurnEndOnMap = function() { | |
| this.onTurnEnd(); | |
| if (this.result().hpDamage > 0) this.performMapDamage(); | |
| }; // NEW._onTurnEndOnMap | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Potential Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {number} The amount of the final floor damage applied to actor | |
| */ | |
| NEW._realFloorDamage = function() { | |
| const floorDamage = Math.floor(this.basicFloorDamage() * this.fdr); | |
| return Math.min(floorDamage, this.maxFloorDamage()); | |
| }; // NEW._realFloorDamage | |
| })(Game_Actor.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Enemy | |
| * - Improves performance and code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const $$ = Game_Battler.prototype, { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Enemy", $, MZ_EC); | |
| rewriteFunc("makeDropItems", function() { | |
| // Edited to help plugins alter make drop items in better ways | |
| return this.enemy().dropItems.reduce((dropItems, dropItem) => { | |
| return NEW._accumDropItems.call(this, dropItems, dropItem); | |
| }, []); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("selectAllActions", function(actionList) { | |
| // Edited to help plugins alter select all actions in better ways | |
| const ratingZero = NEW._ratingZero.call(this, actionList); | |
| // | |
| actionList = actionList.filter(({ rating }) => rating > ratingZero); | |
| for (let i = 0; i < this.numActions(); i++) { | |
| const selectedAct = this.selectAction(actionList, ratingZero); | |
| this.action(i).setEnemyAction(selectedAct); | |
| } | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("makeActions", function() { | |
| $$.makeActions.call(this); | |
| /** @todo Extracts these codes into well-named functions */ | |
| if (this.numActions() > 0) { | |
| // Edited to help plugins alter make actions behaviors in better way | |
| const actionList = NEW._validActs.call(this); | |
| // | |
| if (!actionList.isEmpty()) this.selectAllActions(actionList); | |
| } | |
| // | |
| this.setActionState("waiting"); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Enemy.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {[DatumDropItem]} dropItems - The items to be dropped by the enemy | |
| * @param {DataDropItem} dropItem - The item to be dropped by the enemy | |
| * @returns {[DatumDropItem]} The accumulated items to be dropped by enemy | |
| */ | |
| NEW._accumDropItems = function(dropItems, dropItem) { | |
| if (NEW._isDropItem.call(this, dropItem)) { | |
| dropItems.push(this.itemObject(dropItem.kind, dropItem.dataId)); | |
| } | |
| return dropItems; | |
| }; // NEW._accumDropItems | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataDropItem} dropItem - The item to be dropped by the enemy | |
| * @returns {boolean} Whether the specified item's to be dropped by enemy | |
| */ | |
| NEW._isDropItem = function(dropItem) { | |
| const rate = this.dropItemRate(); | |
| return dropItem.kind > 0 && Math.random() * dropItem.denominator < rate; | |
| }; // NEW._isDropItem | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent/Random | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataDropItem} actList - The list of actions to be selected | |
| * @returns {number} The rating to filter out those not having higher rating | |
| */ | |
| NEW._ratingZero = function(actList) { | |
| return Math.max(...actList.fastMap(({ rating }) => rating)) - 3; | |
| }; // NEW._ratingZero | |
| /** | |
| * The this pointer is Game_Actor.prototype | |
| * Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @returns {[DataAction]} The list of valid enemy actions to be inputted | |
| */ | |
| NEW._validActs = function() { | |
| return this.enemy().actions.filter(this.isActionValid, this); | |
| }; // NEW._validActs | |
| })(Game_Enemy.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Unit | |
| * - Uses the configurable Graphics fps instead of the constant 60 | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { rewriteFunc } = MZ_EC.setKlassContainer("Game_Unit", $, MZ_EC); | |
| rewriteFunc("onBattleStart", function(advantageous, disadvantageous) { | |
| this.members().forEach(mem => { | |
| // Edited to help plugins alter the on battle start in better ways | |
| mem.onBattleStart(advantageous, disadvantageous); | |
| // | |
| }); | |
| this._inBattle = true; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("tpbReferenceTime", function() { | |
| // Edited to help plugins alter the fps in better ways | |
| const fps = Graphics.gameFps; | |
| return BattleManager.isActiveTpb() ? 4 * fps : fps; | |
| // | |
| }); // v0.00a - v0.00a | |
| })(Game_Unit.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Party | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Party", $, MZ_EC); | |
| rewriteFunc("setupBattleTestMembers", function() { | |
| // Edited to help plugins alter setup battle test members in better ways | |
| $dataSystem.testBattlers.forEach(NEW._setupBattleTestMem, this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("addActor", function(actorId) { | |
| if (this._actors.includes(actorId)) return; | |
| // Edited to help plugins alter add actor behaviors in better ways | |
| NEW._addNewActor.call(this, actorId); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("removeActor", function(actorId) { | |
| if (!this._actors.includes(actorId)) return; | |
| // Edited to help plugins alter remove actor behaviors in better ways | |
| NEW._removeExistingActor.call(this, actorId); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Party.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataActor} battler - The data of the actor to be setup in test | |
| */ | |
| NEW._setupBattleTestMem = function(battler) { | |
| const actor = $gameActors.actor(battler.actorId); | |
| if (actor) NEW._setupExistingBattleTestMem.call(this, battler, actor); | |
| }; // NEW._setupBattleTestMem | |
| /** | |
| * The this pointer is Game_Party.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {DataActor} battler - The data of the actor to be setup in test | |
| * @param {Game_Actor} actor - The the actor to be setup in the battle test | |
| */ | |
| NEW._setupExistingBattleTestMem = function(battler, actor) { | |
| actor.changeLevel(battler.level, false); | |
| actor.initEquips(battler.equips); | |
| actor.recoverAll(); | |
| this.addActor(battler.actorId); | |
| }; // NEW._setupExistingBattleTestMem | |
| /** | |
| * The this pointer is Game_Party.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} actorId - The id of the actor to be added into the party | |
| */ | |
| NEW._addNewActor = function(actorId) { | |
| this._actors.push(actorId); | |
| $gamePlayer.refresh(); | |
| $gameMap.requestRefresh(); | |
| $gameTemp.requestBattleRefresh(); | |
| if (this.inBattle()) NEW._addNewActorInBattle.call(this, actorId); | |
| }; // NEW._addNewActor | |
| /** | |
| * The this pointer is Game_Party.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} actorId - The id of the actor to be added into the party | |
| */ | |
| NEW._addNewActorInBattle = function(actorId) { | |
| const actor = $gameActors.actor(actorId); | |
| if (this.battleMembers().includes(actor)) actor.onBattleStart(); | |
| }; // NEW._addNewActorInBattle | |
| /** | |
| * The this pointer is Game_Party.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {id} actorId - The id of the actor to be removed from the party | |
| */ | |
| NEW._removeExistingActor = function(actorId) { | |
| const actor = $gameActors.actor(actorId); | |
| const wasBattleMember = this.battleMembers().includes(actor); | |
| this._actors.remove(actorId); | |
| $gamePlayer.refresh(); | |
| $gameMap.requestRefresh(); | |
| $gameTemp.requestBattleRefresh(); | |
| if (this.inBattle() && wasBattleMember) actor.onBattleEnd(); | |
| }; // NEW._removeExistingActor | |
| })(Game_Party.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Troop | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Troop", $, MZ_EC); | |
| rewriteFunc("setup", function(troopId) { | |
| this.clear(); | |
| [this._troopId, this._enemies] = [troopId, []]; | |
| // Edited to help plugins alter setup behaviors in better ways | |
| this.troop().members.forEach(NEW._setupMem, this); | |
| // | |
| this.makeUniqueNames(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Troop.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Enemy} mem - The enemy to be setup in this troop | |
| */ | |
| NEW._setupMem = function(mem) { | |
| if ($dataEnemies[mem.enemyId]) NEW._setupExistingMem.call(this, mem); | |
| }; // NEW._setupMem | |
| /** | |
| * The this pointer is Game_Troop.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Enemy} mem - The enemy to be setup in this troop | |
| */ | |
| NEW._setupExistingMem = function(mem) { | |
| const enemy = new Game_Enemy(mem.enemyId, mem.x, mem.y); | |
| if (mem.hidden) enemy.hide(); | |
| this._enemies.push(enemy); | |
| }; // NEW._setupExistingMem | |
| })(Game_Troop.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Map | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Map", $, MZ_EC); | |
| rewriteFunc("roundXWithDirection", function(x, d) { | |
| // Edited to help plugins alter round x with direction in better ways | |
| return this.roundX(this.xWithDirection(x, d)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("roundYWithDirection", function(y, d) { | |
| // Edited to help plugins alter round y with direction in better ways | |
| return this.roundY(this.yWithDirection(y, d)); | |
| // | |
| }); // v0.00a - v0.00a | |
| })(Game_Map.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_CharacterBase | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| rewriteFunc, | |
| NEW | |
| } = MZ_EC.setKlassContainer("Game_CharacterBase", $, MZ_EC); | |
| rewriteFunc("moveStraight", function(d) { | |
| this.setMovementSuccess(this.canPass(this._x, this._y, d)); | |
| // Edited to help plugins alter move straight behaviors in better ways | |
| if (this.isMovementSucceeded()) { | |
| NEW._onMoveStraightSuc.call(this, d); | |
| } else NEW._onMoveStraightFail.call(this, d); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("moveDiagonally", function(horz, vert) { | |
| const canPass = this.canPassDiagonally(this._x, this._y, horz, vert); | |
| this.setMovementSuccess(canPass); | |
| if (this.isMovementSucceeded()) { | |
| // Edited to help plugins alter move diagonally in better ways | |
| NEW._onMoveDiagonallySuc.call(this, horz, vert); | |
| // | |
| } | |
| if (this._direction === this.reverseDir(horz)) this.setDirection(horz); | |
| if (this._direction === this.reverseDir(vert)) this.setDirection(vert); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} d - 2 for down/4 for left/6 for right/8 for up | |
| */ | |
| NEW._onMoveStraightSuc = function(d) { | |
| this.setDirection(d); | |
| NEW._updateStraightXY.call(this, d); | |
| this.increaseSteps(); | |
| }; // NEW._onMoveStraightSuc | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} d - 2 for down/4 for left/6 for right/8 for up | |
| */ | |
| NEW._updateStraightXY = function(d) { | |
| this._x = $gameMap.roundXWithDirection(this._x, d); | |
| this._y = $gameMap.roundYWithDirection(this._y, d); | |
| this._realX = $gameMap.xWithDirection(this._x, this.reverseDir(d)); | |
| this._realY = $gameMap.yWithDirection(this._y, this.reverseDir(d)); | |
| }; // NEW._updateStraightXY | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} d - 2 for down/4 for left/6 for right/8 for up | |
| */ | |
| NEW._onMoveStraightFail = function(d) { | |
| this.setDirection(d); | |
| this.checkEventTriggerTouchFront(d); | |
| }; // NEW._onMoveStraightFail | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} horz - 4 for left/6 for right | |
| * @enum @param {number} vert - 2 for down/8 for up | |
| */ | |
| NEW._onMoveDiagonallySuc = function(horz, vert) { | |
| NEW._updateDiagonalXY.call(this, horz, vert); | |
| this.increaseSteps(); | |
| }; // NEW._onMoveDiagonallySuc | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} horz - 4 for left/6 for right | |
| * @enum @param {number} vert - 2 for down/8 for up | |
| */ | |
| NEW._updateDiagonalXY = function(horz, vert) { | |
| this._x = $gameMap.roundXWithDirection(this._x, horz); | |
| this._y = $gameMap.roundYWithDirection(this._y, vert); | |
| this._realX = $gameMap.xWithDirection(this._x, this.reverseDir(horz)); | |
| this._realY = $gameMap.yWithDirection(this._y, this.reverseDir(vert)); | |
| }; // NEW._updateDiagonalXY | |
| })(Game_CharacterBase.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Player | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const $$ = Game_Character.prototype, { | |
| rewriteFunc, | |
| NEW | |
| } = MZ_EC.setKlassContainer("Game_Player", $, MZ_EC); | |
| rewriteFunc("update", function(sceneActive) { | |
| const lastScrolledX = this.scrolledX(); | |
| const lastScrolledY = this.scrolledY(); | |
| const wasMoving = this.isMoving(); | |
| this.updateDashing(); | |
| if (sceneActive) this.moveByInput(); | |
| $$.update.call(this); | |
| this.updateScroll(lastScrolledX, lastScrolledY); | |
| this.updateVehicle(); | |
| if (!this.isMoving()) this.updateNonmoving(wasMoving, sceneActive); | |
| this._followers.update(); | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @enum @param {number} horz - 4 for left/6 for right | |
| * @enum @param {number} vert - 2 for down/8 for up | |
| */ | |
| NEW._onMoveDiagonallySuc = function(horz, vert) { | |
| NEW._updateDiagonalXY.call(this, horz, vert); | |
| this.increaseSteps(); | |
| }; // NEW._onMoveDiagonallySuc | |
| })(Game_Player.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Game_Interpreter | |
| * - Improves code quality | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Game_Interpreter", $.prototype, MZ_EC); | |
| rewriteFunc("command111", function(params) { | |
| this._branch[this._indent] = NEW._condBranchResult.call(this, params); | |
| if (!this._branch[this._indent]) this.skipBranch(); | |
| return true; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("command122", function(params) { | |
| const [startId, endId, operationType] = params; | |
| const [value, randomMax] = NEW._varValRandMax.call(this, params); | |
| for (let i = startId; i <= endId; i++) { | |
| if (!isNaN(value)) { | |
| const realValue = value + Math.randomInt(randomMax); | |
| this.operateVariable(i, operationType, realValue); | |
| } else this.operateVariable(i, operationType, value); | |
| } | |
| return true; | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("command355", function() { | |
| // Edited to help plugins alter command 355 behaviors in better ways | |
| let script = NEW.curScriptLine.call(this); | |
| while (NEW.hasNextScriptLine.call(this)) { | |
| this._index++; | |
| script += NEW.curScriptLine.call(this); | |
| } | |
| NEW.evalScript_.call(this, script); | |
| return true; | |
| // | |
| }); // v0.00a - v0.00a | |
| $.IS_CACHE_SCRIPT = false; | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether there are still more script lines to be read | |
| */ | |
| NEW.hasNextScriptLine = function() { return this.nextEventCode() === 655; }; | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The current script line to be read from the script box | |
| */ | |
| NEW.curScriptLine = function() { | |
| return `${this.currentCommand().parameters[0]}\n`; | |
| }; // $.curScriptLine | |
| NEW._isSameSwitchState = params => { | |
| return $gameSwitches.value(params[1]) === (params[2] === 0); | |
| }; // NEW._isSameSwitchState | |
| NEW._isVarValRelationMet = params => { | |
| const value1 = $gameVariables.value(params[1]), rhs = params[3]; | |
| const value2 = params[2] === 0 ? rhs : $gameVariables.value(rhs); | |
| switch (params[4]) { | |
| case 0: return value1 === value2; | |
| case 1: return value1 >= value2; | |
| case 2: return value1 <= value2; | |
| case 3: return value1 > value2; | |
| case 4: return value1 < value2; | |
| case 5: return value1 !== value2; | |
| default: return false; | |
| } | |
| }; // NEW._isVarValRelationMet | |
| NEW._isSameSelfSwitchState = (eventId, mapId, params) => { | |
| if (eventId <= 0) return false; | |
| const key = [mapId, eventId, params[1]]; | |
| return $gameSelfSwitches.value(key) === (params[2] === 0); | |
| }; // NEW._isSameSwitchState | |
| NEW._isTimerValRelationMet = params => { | |
| if (!$gameTimer.isWorking()) return false; | |
| const secs = $gameTimer.seconds(), timerVal = params[1]; | |
| return params[2] === 0 ? secs >= timerVal : secs <= timerVal; | |
| }; // NEW._isTimerValRelationMet | |
| NEW._isActorCondMet = params => { | |
| const actor = $gameActors.actor(params[1]); | |
| if (!actor) return false; | |
| const n = params[3]; | |
| switch (params[2]) { | |
| case 0: return $gameParty.members().includes(actor); | |
| case 1: return actor.name() === n; | |
| case 2: return actor.isClass($dataClasses[n]); | |
| case 3: return actor.hasSkill(n); | |
| case 4: return actor.hasWeapon($dataWeapons[n]); | |
| case 5: return actor.hasArmor($dataArmors[n]); | |
| case 6: return actor.isStateAffected(n); | |
| default: return false; | |
| } | |
| }; // NEW._isActorCondMet | |
| NEW._isEnemyCondMet = params => { | |
| const enemy = $gameTroop.members()[params[1]]; | |
| if (!enemy) return false; | |
| switch (params[2]) { | |
| case 0: return enemy.isAlive(); | |
| case 1: return enemy.isStateAffected(params[3]); | |
| default: return false; | |
| } | |
| }; // NEW._isEnemyCondMet | |
| NEW._isSameCharDir = (char_, dir) => char_ && char_.direction() === dir; | |
| NEW._isGoldValRelationMet = params => { | |
| const goldVal = params[1]; | |
| switch (params[2]) { | |
| case 0: return $gameParty.gold() >= goldVal; | |
| case 1: return $gameParty.gold() <= goldVal; | |
| case 2: return $gameParty.gold() < goldVal; | |
| default: return false; | |
| } | |
| }; // NEW._isGoldValRelationMet | |
| NEW._isButtonEventRun = params => { | |
| const keyName = params[1]; | |
| switch (params[2] || 0) { | |
| case 0: return Input.isPressed(keyName); | |
| case 1: return Input.isTriggered(keyName); | |
| case 2: return Input.isRepeated(keyName); | |
| default: return false; | |
| } | |
| }; // NEW._isButtonEventRun | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {[*]} params - The conditional branch event parameters | |
| * @returns {boolean} Whether the if in the conditional branch is met | |
| */ | |
| NEW._condBranchResult = function(params) { | |
| switch (params[0]) { | |
| case 0: return NEW._isSameSwitchState(params); | |
| case 1: return NEW._isVarValRelationMet(params); | |
| case 2: return NEW._isSameSelfSwitchState( | |
| this._eventId, this._mapId, params); | |
| case 3: return NEW._isTimerValRelationMet(params); | |
| case 4: return NEW._isActorCondMet(params); | |
| case 5: return NEW._isEnemyCondMet(params); | |
| case 6: { | |
| return NEW._isSameCharDir(this.character(params[1]), params[2]); | |
| } case 7: return NEW._isGoldValRelationMet(params); | |
| case 8: return $gameParty.hasItem($dataItems[params[1]]); | |
| case 9: { | |
| return $gameParty.hasItem($dataWeapons[params[1]], params[2]); | |
| } case 10: { | |
| return $gameParty.hasItem($dataArmors[params[1]], params[2]); | |
| } case 11: return NEW._isButtonEventRun(params); | |
| case 12: return !!NEW.evalScriptLine_.call(this, params[1]); | |
| case 13: { | |
| return $gamePlayer.vehicle() === $gameMap.vehicle(params[1]); | |
| } | |
| } | |
| }; // NEW._condBranchResult | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {[*]} params - The control variable event parameters | |
| * @returns {[*]} The variable value and random max pair | |
| */ | |
| NEW._varValRandMax = function(params) { | |
| const [operand, rhs, param5] = [params[3], params[4], params[5]]; | |
| switch (operand) { | |
| case 0: return [rhs, 1]; | |
| case 1: return [$gameVariables.value(rhs), 1]; | |
| case 2: return [rhs, Math.max(param5 - rhs + 1, 1)]; | |
| case 3: return [this.gameDataOperand(rhs, param5, params[6]), 1]; | |
| case 4: return [NEW.evalScriptLine_.call(this, rhs), 1]; | |
| default: return [0, 1]; | |
| } | |
| }; // NEW._varValRandMax | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {string} scriptLine - The raw script string input to be evaluated | |
| * @returns {*?} The result returned by the evaluated script | |
| */ | |
| NEW.evalScriptLine_ = function(scriptLine) { | |
| return NEW.evalScript_.call(this, scriptLine); | |
| }; // NEW.evalScriptLine_ | |
| NEW._cachedScripts = new Map(); | |
| /** | |
| * The this pointer is Game_Interpreter.prototype | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @param {string} script - The raw script string input to be evaluated | |
| * @returns {*?} The result returned by the evaluated script | |
| */ | |
| NEW.evalScript_ = function(script) { | |
| if (!script) return undefined; | |
| if (!$.IS_CACHE_SCRIPT) return eval(script); | |
| // It's to avoid 1st call being eval and subsequent ones being functions | |
| if (!NEW._cachedScripts.has(script)) { | |
| NEW._cachedScripts.set(script, new Function(script)); | |
| } | |
| return NEW._cachedScripts.get(script).call(this); | |
| // | |
| }; // NEW.evalScript_ | |
| })(Game_Interpreter, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Scenes | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Scene_Battle | |
| * - Fixes some manifestations of the very rare but game-crashing bug | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| ORIG, | |
| extendFunc, | |
| rewriteFunc, | |
| } = MZ_EC.setKlassContainer("Scene_Battle", $, MZ_EC); | |
| [ | |
| "commandAttack", | |
| "commandGuard", | |
| "onActorOk", | |
| "onEnemyOk", | |
| "onSkillOk", | |
| "onItemOk", | |
| "onSelectAction" | |
| ].forEach(funcName => { | |
| extendFunc(funcName, function() { | |
| // Added to stop the bug when the inputting action doesn't exist | |
| if (!BattleManager.inputtingAction()) return; | |
| // | |
| ORIG[funcName].apply(this, arguments); | |
| }); // v0.00a - v0.00a | |
| }); | |
| extendFunc("commandSkill", function() { | |
| // Edited to stop the bug when the inputting actor doesn't exist | |
| if (BattleManager.actor()) ORIG.commandSkill.apply(this, arguments); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateStatusWindowPosition", function() { | |
| // Edited to remove the redundant check as at most 1 check can be true | |
| const statusWindow = this._statusWindow, targetX = this.statusWindowX(); | |
| if (statusWindow.x < targetX) { | |
| statusWindow.x = Math.min(statusWindow.x + 16, targetX); | |
| } else if (statusWindow.x > targetX) { | |
| statusWindow.x = Math.max(statusWindow.x - 16, targetX); | |
| } | |
| /** @todo Figures out where does this magic literal 16 come from */ | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("startActorCommandSelection", function() { | |
| // Edited to stop the bug when the inputting action doesn't exist | |
| const actor_ = BattleManager.actor(); | |
| if (actor_) NEW._startActorCmdSelection.call(this, actor_); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * The this pointer is Scene_Battle.prototype | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {Game_Actor} actor - The currently inputable actor | |
| */ | |
| NEW._startActorCmdSelection = function(actor) { | |
| this._statusWindow.show(); | |
| this._statusWindow.selectActor(actor); | |
| this._partyCommandWindow.close(); | |
| this._actorCommandWindow.show(); | |
| this._actorCommandWindow.setup(actor); | |
| }; // NEW._startActorCmdSelection | |
| })(Scene_Battle.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Sprites | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Sprite_Gauge | |
| * - Makes this class better at adding bar types/editing their behaviors | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Sprite_Gauge", $, MZ_EC); | |
| rewriteFunc("gaugeX", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const gaugeXFunc = NEW._GAUGE_X_FUNCS[this._statusType]; | |
| return NEW[gaugeXFunc || "defaultGaugeX"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateBitmap", function() { | |
| const [val, maxVal] = [this.currentValue(), this.currentMaxValue()]; | |
| // Edited to help plugins alter update bitmap behaviors in better ways | |
| if (NEW._isUpdateTargetVal.call(val, maxVal)) { | |
| this.updateTargetValue(val, maxVal); | |
| } | |
| // | |
| this.updateGaugeAnimation(); | |
| this.updateFlashing(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("smoothness", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const smoothnessFunc = NEW._SMOOTHNESS_FUNCS[this._statusType]; | |
| return NEW[smoothnessFunc || "defaultSmoothness"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("updateFlashing", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const updateFlashingFunc = NEW._UPDATE_FLASHING_FUNCS[this._statusType]; | |
| NEW[updateFlashingFunc || "updateDefaultFlashing"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("isValid", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| if (!this._battler) return false; | |
| const isValidFunc = NEW._IS_VALID_FUNCS[this._statusType]; | |
| return NEW[isValidFunc || "isDefaultValid"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("currentValue", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| if (!this._battler) return NEW._INVALID_VAL; | |
| const validCurValFunc = NEW._VALID_CUR_VAL_FUNCS[this._statusType]; | |
| if (!validCurValFunc) return NEW._INVALID_VAL; | |
| return NEW[validCurValFunc].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("currentMaxValue", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| if (!this._battler) return NEW._INVALID_VAL; | |
| const validMaxValFunc = NEW._VALID_CUR_MAX_VAL_FUNCS[this._statusType]; | |
| if (!validMaxValFunc) return NEW._INVALID_VAL; | |
| return NEW[validMaxValFunc].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("label", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const labelFunc = NEW._LABEL_FUNCS[this._statusType]; | |
| return NEW[labelFunc || "defaultLabel"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("gaugeColor1", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const gaugeColor1Func = NEW._GAUGE_COLOR_1_FUNCS[this._statusType]; | |
| return NEW[gaugeColor1Func || "defaultGaugeColor1"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("gaugeColor2", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const gaugeColor2 = NEW._GAUGE_COLOR_2_FUNCS[this._statusType]; | |
| return NEW[gaugeColor2 || "defaultGaugeColor2"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("valueColor", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| const valueColor = NEW._VALUE_COLOR_FUNCS[this._statusType]; | |
| return NEW[valueColor || "defaultvalueColor"].call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("redraw", function() { | |
| // Edited to break different bar type behaviors into separate methods | |
| this.bitmap.clear(); | |
| if (!isNaN(this.currentValue())) NEW._redraw.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| NEW._INVALID_VAL = NaN; | |
| NEW._STATUS_TYPE_HP = "hp", NEW._STATUS_TYPE_MP = "mp"; | |
| NEW._STATUS_TYPE_TP = "tp", NEW._STATUS_TYPE_TIME = "time"; | |
| NEW._GAUGE_X_FUNCS = { [NEW._STATUS_TYPE_TIME]: "timeGaugeX" }; | |
| NEW._SMOOTHNESS_FUNCS = { [NEW._STATUS_TYPE_TIME]: "timeSmoothness" }; | |
| NEW._UPDATE_FLASHING_FUNCS = { | |
| [NEW._STATUS_TYPE_TIME]: "updateTimeFlashing" | |
| }; // NEW._UPDATE_FLASHING_FUNCS | |
| NEW._IS_VALID_FUNCS = { [NEW._STATUS_TYPE_TP]: "isTpValid" }; | |
| NEW._VALID_CUR_VAL_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "validCurHPVal", | |
| [NEW._STATUS_TYPE_MP]: "validCurMPVal", | |
| [NEW._STATUS_TYPE_TP]: "validCurTPVal", | |
| [NEW._STATUS_TYPE_TIME]: "validCurTimeVal" | |
| }; // NEW._VALID_CUR_VAL_FUNCS | |
| NEW._VALID_CUR_MAX_VAL_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "validCurMaxHPVal", | |
| [NEW._STATUS_TYPE_MP]: "validCurMaxMPVal", | |
| [NEW._STATUS_TYPE_TP]: "validCurMaxTPVal", | |
| [NEW._STATUS_TYPE_TIME]: "validCurMaxTimeVal" | |
| }; // NEW._VALID_CUR_MAX_VAL_FUNCS | |
| NEW._LABEL_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "hpLabel", | |
| [NEW._STATUS_TYPE_MP]: "mpLabel", | |
| [NEW._STATUS_TYPE_TP]: "tpLabel" | |
| }; // NEW._LABEL_FUNCS | |
| NEW._GAUGE_COLOR_1_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "hpGaugeColor1", | |
| [NEW._STATUS_TYPE_MP]: "mpGaugeColor1", | |
| [NEW._STATUS_TYPE_TP]: "tpGaugeColor1", | |
| [NEW._STATUS_TYPE_TIME]: "timeGaugeColor1" | |
| }; // NEW._GAUGE_COLOR_1_FUNCS | |
| NEW._GAUGE_COLOR_2_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "hpGaugeColor2", | |
| [NEW._STATUS_TYPE_MP]: "mpGaugeColor2", | |
| [NEW._STATUS_TYPE_TP]: "tpGaugeColor2", | |
| [NEW._STATUS_TYPE_TIME]: "timeGaugeColor2" | |
| }; // NEW._GAUGE_COLOR_2_FUNCS | |
| NEW._VALUE_COLOR_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "hpValueColor", | |
| [NEW._STATUS_TYPE_MP]: "mpValueColor", | |
| [NEW._STATUS_TYPE_TP]: "tpValueColor" | |
| }; // NEW._VALUE_COLOR_FUNCS | |
| NEW._DRAW_TEXT_FUNCS = { | |
| [NEW._STATUS_TYPE_HP]: "drawDefaultTexts", | |
| [NEW._STATUS_TYPE_MP]: "drawDefaultTexts", | |
| [NEW._STATUS_TYPE_TP]: "drawDefaultTexts" | |
| }; // NEW._DRAW_TEXT_FUNCS | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The x position of the time sprite gauge | |
| */ | |
| NEW.timeGaugeX = function() { return 0; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The default x position of the other sprite gauges | |
| */ | |
| NEW.defaultGaugeX = function() { return this.measureLabelWidth() + 6; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The smoothness of the time sprite gauge | |
| */ | |
| NEW.timeSmoothness = function() { return 5; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The default smoothness of the other sprite gauges | |
| */ | |
| NEW.defaultSmoothness = function() { return 20; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @todo Figures out where do these magic literals 40 and 15 come from | |
| */ | |
| NEW.updateTimeFlashing = function() { | |
| this._flashingCount++; | |
| if (!this._battler.isInputting()) { | |
| this.setBlendColor([0, 0, 0, 0]); | |
| } else if (this._flashingCount % 30 < 15) { | |
| this.setBlendColor(this.flashingColor1()); | |
| } else this.setBlendColor(this.flashingColor2()); | |
| }; // NEW.updateTimeFlashing | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| NEW.updateDefaultFlashing = function() {}; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether this tp sprite gauge's valid right now | |
| */ | |
| NEW.isTpValid = function() { | |
| return this._battler.isPreserveTp() || $gameParty.inBattle(); | |
| }; // NEW.isTpValid | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {boolean} Whether the other sprite gauges' valid by default | |
| */ | |
| NEW.isDefaultValid = function() { return true; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The current value of the hp gauge sprite | |
| */ | |
| NEW.validCurHPVal = function() { return this._battler.hp; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The current value of the mp gauge sprite | |
| */ | |
| NEW.validCurMPVal = function() { return this._battler.mp; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The current value of the tp gauge sprite | |
| */ | |
| NEW.validCurTPVal = function() { return this._battler.tp; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The current value of the TPB gauge sprite | |
| */ | |
| NEW.validCurTimeVal = function() { return this._battler.tpbChargeTime(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The maximum value of the hp gauge sprite | |
| */ | |
| NEW.validCurMaxHPVal = function() { return this._battler.mhp; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The maximum value of the mp gauge sprite | |
| */ | |
| NEW.validCurMaxMPVal = function() { return this._battler.mmp; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The maximum value of the tp gauge sprite | |
| */ | |
| NEW.validCurMaxTPVal = function() { return this._battler.maxTp(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The maximum value of the TPB gauge sprite | |
| */ | |
| NEW.validCurMaxTimeVal = function() { return 1; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The label of the hp sprite gauge | |
| */ | |
| NEW.hpLabel = function() { return TextManager.hpA; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The label of the mp sprite gauge | |
| */ | |
| NEW.mpLabel = function() { return TextManager.mpA; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The label of the tp sprite gauge | |
| */ | |
| NEW.tpLabel = function() { return TextManager.tpA; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The default label of the other sprite gauges | |
| */ | |
| NEW.defaultLabel = function() { return ""; }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the hp gauge sprite | |
| */ | |
| NEW.hpGaugeColor1 = function() { return ColorManager.hpGaugeColor1(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the mp gauge sprite | |
| */ | |
| NEW.mpGaugeColor1 = function() { return ColorManager.mpGaugeColor1(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the tp gauge sprite | |
| */ | |
| NEW.tpGaugeColor1 = function() { return ColorManager.tpGaugeColor1(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the TPB gauge sprite | |
| */ | |
| NEW.timeGaugeColor1 = function() { return ColorManager.ctGaugeColor1(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The default 1st color of the other gauge sprites | |
| */ | |
| NEW.defaultGaugeColor1 = function() { return ColorManager.normalColor(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the hp gauge sprite | |
| */ | |
| NEW.hpGaugeColor2 = function() { return ColorManager.hpGaugeColor2(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the mp gauge sprite | |
| */ | |
| NEW.mpGaugeColor2 = function() { return ColorManager.mpGaugeColor2(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the tp gauge sprite | |
| */ | |
| NEW.tpGaugeColor2 = function() { return ColorManager.tpGaugeColor2(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The 1st color of the TPB gauge sprite | |
| */ | |
| NEW.timeGaugeColor2 = function() { return ColorManager.ctGaugeColor2(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {number} The default 1st color of the other gauge sprites | |
| */ | |
| NEW.defaultGaugeColor2 = function() { return ColorManager.normalColor(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The value color of the hp sprite gauge | |
| */ | |
| NEW.hpValueColor = function() { | |
| return ColorManager.hpColor(this._battler); | |
| }; // NEW.hpValueColor | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The value color of the mp sprite gauge | |
| */ | |
| NEW.mpValueColor = function() { | |
| return ColorManager.mpColor(this._battler); | |
| }; // NEW.mpValueColor | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The value color of the tp sprite gauge | |
| */ | |
| NEW.tpValueColor = function() { | |
| return ColorManager.tpColor(this._battler); | |
| }; // NEW.tpValueColor | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Nullipotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| * @returns {string} The default value color of the other sprite gauges | |
| */ | |
| NEW.defaultValueColor = function() { return ColorManager.normalColor(); }; | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Idempotent | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| NEW.drawDefaultTexts = function() { | |
| this.drawLabel(); | |
| if (this.isValid()) this.drawValue(); | |
| }; // NEW.drawDefaultTexts | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Hotspot/Nullipotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} val - The target value of the bitmap to be updated | |
| * @param {number} maxVal - The target max value of the bitmap to be updated | |
| * @returns {boolean} Whether the target value of the bitmap's to be updated | |
| */ | |
| NEW._isUpdateTargetVal = function(val, maxVal) { | |
| return val !== this._targetValue || maxVal !== this._targetMaxValue; | |
| }; // NEW._isUpdateTargetVal | |
| /** | |
| * The this pointer is Sprite_Gauge.prototype | |
| * Idempotent | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._redraw = function() { | |
| this.drawGauge(); | |
| const drawTextFunc = NEW._DRAW_TEXT_FUNCS[this._statusType]; | |
| if (drawTextFunc) NEW[drawTextFunc].call(this); | |
| }; // NEW._redraw | |
| })(Sprite_Gauge.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * ## Sprites | |
| *----------------------------------------------------------------------------*/ | |
| /*---------------------------------------------------------------------------- | |
| * # Edited class: Window_Selectable | |
| * - Makes this class better at adding bar types/editing their behaviors | |
| *----------------------------------------------------------------------------*/ | |
| (($, MZ_EC) => { | |
| "use strict"; | |
| const { | |
| NEW, | |
| rewriteFunc | |
| } = MZ_EC.setKlassContainer("Window_Selectable", $, MZ_EC); | |
| rewriteFunc("cursorDown", function(wrap) { | |
| // Edited to help plugins alter cursor down behaviors in better ways | |
| const index = this.index(); | |
| const [maxItems, maxCols] = [this.maxItems(), this.maxCols()]; | |
| const isSmoothSelectDown = NEW._isSmoothSelectDown.call( | |
| this, index, maxItems, maxCols, wrap); | |
| if (isSmoothSelectDown) this.smoothSelect( | |
| NEW._smoothSelectDownIndex.call(this, index, maxItems, maxCols)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("cursorUp", function(wrap) { | |
| // Edited to help plugins alter cursor up behaviors in better ways | |
| const index = Math.max(0, this.index()); | |
| const [maxItems, maxCols] = [this.maxItems(), this.maxCols()]; | |
| const isSmoothSelectUp = NEW._isSmoothSelectUp.call( | |
| this, index, maxItems, maxCols, wrap); | |
| if (isSmoothSelectUp) this.smoothSelect( | |
| NEW._smoothSelectUpIndex.call(this, index, maxItems, maxCols)); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("processCursorMove", function() { | |
| // Edited to help plugins alter process cursor move in better ways | |
| if (this.isCursorMovable()) NEW._procMovableCursor.call(this); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("processHandling", function() { | |
| // Edited to help plugins alter process handling behavior in better ways | |
| if (this.isOpenAndActive()) this.procOpenActiveHandling(); | |
| // | |
| }); // v0.00a - v0.00a | |
| rewriteFunc("processTouch", function() { | |
| // Edited to help plugins alter process touch behaviors in better ways | |
| if (this.isOpenAndActive()) this.procOpenActiveTouch(); | |
| // | |
| }); // v0.00a - v0.00a | |
| /** | |
| * Hotspot | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| $.procOpenActiveHandling = function() { | |
| if (this.isOkEnabled() && this.isOkTriggered()) return this.processOk(); | |
| if (this.isCancelEnabled() && this.isCancelTriggered()) { | |
| return this.processCancel(); | |
| } | |
| if (this.isHandled("pagedown") && Input.isTriggered("pagedown")) { | |
| return this.processPagedown(); | |
| } else if (this.isHandled("pageup") && Input.isTriggered("pageup")) { | |
| return this.processPageup(); | |
| } | |
| }; // $.procOpenActiveHandling | |
| /** | |
| * Hotspot | |
| * @author DoubleX @interface @since v0.00a @version v0.00a | |
| */ | |
| $.procOpenActiveTouch = function() { | |
| if (this.isHoverEnabled() && TouchInput.isHovered()) { | |
| this.onTouchSelect(false); | |
| } else if (TouchInput.isTriggered()) this.onTouchSelect(true); | |
| if (TouchInput.isClicked()) return this.onTouchOk(); | |
| if (TouchInput.isCancelled()) this.onTouchCancel(); | |
| }; // $.procOpenActiveTouch | |
| /** | |
| * The this pointer is Window_Selectable.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} index - The current selection index | |
| * @param {number} maxItems - The maximum number of items in the selections | |
| * @param {number} maxCols - The maximum number of columns in the selections | |
| * @param {boolean} wrap - Whether the cursor can be wrapped | |
| * @returns {boolean} Whether the cursor down's a smooth select downwards | |
| */ | |
| NEW._isSmoothSelectDown = function(index, maxItems, maxCols, wrap) { | |
| return index < maxItems - maxCols || (wrap && maxCols === 1); | |
| }; // NEW._isSmoothSelectDown | |
| /** | |
| * The this pointer is Window_Selectable.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} index - The current selection index | |
| * @param {number} maxItems - The maximum number of items in the selections | |
| * @param {number} maxCols - The maximum number of columns in the selections | |
| * @returns {number} The smooth select down index as the new selection index | |
| */ | |
| NEW._smoothSelectDownIndex = function(index, maxItems, maxCols) { | |
| return (index + maxCols) % maxItems; | |
| }; // NEW._smoothSelectDownIndex | |
| /** | |
| * The this pointer is Window_Selectable.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} index - The current selection index | |
| * @param {number} maxItems - The maximum number of items in the selections | |
| * @param {number} maxCols - The maximum number of columns in the selections | |
| * @param {boolean} wrap - Whether the cursor can be wrapped | |
| * @returns {boolean} Whether the cursor up's a smooth select upwards | |
| */ | |
| NEW._isSmoothSelectUp = function(index, maxItems, maxCols, wrap) { | |
| return index >= maxCols || (wrap && maxCols === 1); | |
| }; // NEW._isSmoothSelectUp | |
| /** | |
| * The this pointer is Window_Selectable.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| * @param {number} index - The current selection index | |
| * @param {number} maxItems - The maximum number of items in the selections | |
| * @param {number} maxCols - The maximum number of columns in the selections | |
| * @returns {number} The smooth select up index as the new selection index | |
| */ | |
| NEW._smoothSelectUpIndex = function(index, maxItems, maxCols) { | |
| return (index - maxCols + maxItems) % maxItems; | |
| }; // NEW._smoothSelectUpIndex | |
| /** | |
| * The this pointer is Window_Selectable.prototype | |
| * Hotspot | |
| * @author DoubleX @since v0.00a @version v0.00a | |
| */ | |
| NEW._procMovableCursor = function() { | |
| const lastIndex = this.index(); | |
| if (Input.isRepeated("down")) { | |
| this.cursorDown(Input.isTriggered("down")); | |
| } | |
| if (Input.isRepeated("up")) this.cursorUp(Input.isTriggered("up")); | |
| if (Input.isRepeated("right")) { | |
| this.cursorRight(Input.isTriggered("right")); | |
| } | |
| if (Input.isRepeated("left")) { | |
| this.cursorLeft(Input.isTriggered("left")); | |
| } | |
| if (!this.isHandled("pagedown") && Input.isTriggered("pagedown")) { | |
| this.cursorPagedown(); | |
| } | |
| if (!this.isHandled("pageup") && Input.isTriggered("pageup")) { | |
| this.cursorPageup(); | |
| } | |
| if (this.index() !== lastIndex) this.playCursorSound(); | |
| }; // NEW._procMovableCursor | |
| })(Window_Selectable.prototype, DoubleX_RMMZ.Enhanced_Codebase); | |
| /*============================================================================*/ |