diff --git a/.eslintrc.js b/.eslintrc.js index 59d7715..76fb97f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,6 +10,6 @@ module.exports = { "sourceType": "module", }, "rules": { - "no-prototype-builtins": false, + "no-prototype-builtins": 0, } }; diff --git a/build/app.js b/build/app.js index 1b3a4da..2633687 100644 --- a/build/app.js +++ b/build/app.js @@ -16,7 +16,7 @@ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"HKReadTextArea\": () => /* binding */ HKReadTextArea\n/* harmony export */ });\n/* harmony import */ var _hk_database_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hk-database.js */ \"./src/js/hk-database.js\");\n/* harmony import */ var _hk_dictionary_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./hk-dictionary.js */ \"./src/js/hk-dictionary.js\");\n/* harmony import */ var _page_functions_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./page-functions.js */ \"./src/js/page-functions.js\");\n/* harmony import */ var _hk_functions_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./hk-functions.js */ \"./src/js/hk-functions.js\");\n/* harmony import */ var _img_health_mask_png__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../img/health-mask.png */ \"./src/img/health-mask.png\");\n/* harmony import */ var _img_health_mask_steel_png__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../img/health-mask-steel.png */ \"./src/img/health-mask-steel.png\");\n/* harmony import */ var _img_soul_orb_png__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../img/soul-orb.png */ \"./src/img/soul-orb.png\");\n/* harmony import */ var _img_notch_png__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../img/notch.png */ \"./src/img/notch.png\");\n/* harmony import */ var _img_notch_filled_png__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../img/notch-filled.png */ \"./src/img/notch-filled.png\");\n/* harmony import */ var _img_notch_overcharmed_png__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../img/notch-overcharmed.png */ \"./src/img/notch-overcharmed.png\");\n/* harmony import */ var _img_geo_png__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../img/geo.png */ \"./src/img/geo.png\");\n/* harmony import */ var _img_geo_shade_png__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../img/geo-shade.png */ \"./src/img/geo-shade.png\");\n/* eslint-disable no-prototype-builtins */\n// ---------------- Load main Hollow Knight database files ----------------- //\n\n\n/* ----------------- Helper functions --------------------------------------- */\n\n\n // ---------------- Load image files (necessary for Webpack) ----------------- //\n\n\n\n\n\n\n\n\n // ---------------- Constants ----------------- //\n// const DATA_UNKNOWN = \"Data unknown\";\n\nvar SYMBOL_FALSE = \"\"; // \"❌ \"\n\nvar SYMBOL_TRUE = \"\"; // \"✅ \"\n// const SYMBOL_INFO = \"\"; // \"ℹ \"\n\nvar SYMBOL_EMPTY = \"\";\nvar FLEUR_DIVIDE = \"
\"; // ---------------- Variables ----------------- //\n// let currentData = DATA_UNKNOWN;\n\nvar completionSymbol = SYMBOL_FALSE;\nvar divStart = [\"
\"].join(\"\\n\");\nvar divStartCenter = [\"
\"].join(\"\\n\");\nvar divEnd = [\"
\"].join(\"\\n\");\nvar pSpan = \"\";\nvar benchHKCCBegin, benchHKCCEnd; // ---------------- Functions ----------------- //\n\n/**\r\n * Main Function. Checks Hollow Knight game completion by analyzing the save file\r\n * @param {object} jsonObject Decoded save data in JavaScript Object Notation form (JSON)\r\n */\n\nfunction HKCheckCompletion(jsonObject) {\n // start benchmark\n benchHKCCBegin = new Date();\n var HKPlayerData;\n var HKWorldItems;\n var HKSceneData;\n\n if (jsonObject.hasOwnProperty(\"playerData\")) {\n HKPlayerData = jsonObject.playerData;\n } else return false;\n\n if (jsonObject.hasOwnProperty(\"sceneData\")) {\n HKSceneData = jsonObject.sceneData;\n\n if (jsonObject.sceneData.hasOwnProperty(\"persistentBoolItems\")) {\n HKWorldItems = jsonObject.sceneData.persistentBoolItems;\n } else return false;\n } else return false; // Pre-Cleaning and filling initial data (h2, id) needed for FillHTML()\n\n\n PrefillHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID); // Prevents adding current percent data after each function call (each click of Analyze button)\n\n ResetCompletion(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID); // ================================================================================== //\n // ---------------- Time Played ----------------- //\n\n CheckPlayTime(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.playTime); // ---------------- Game Completion Status ----------------- //\n\n CheckCompletionPercent(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.completionPercentage); // ---------------- Game Completion Status ----------------- //\n\n CheckSaveFileVersion(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.version); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, FLEUR_DIVIDE); // ---------------- Health Masks ----------------- //\n\n CheckHealthMasks(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.maxHealthBase, HKPlayerData.permadeathMode); // ---------------- Soul Orbs ----------------- //\n\n CheckSoulOrbs(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.maxMP + HKPlayerData.MPReserveMax); // ---------------- Charm Notches (Slots) ----------------- //\n\n CheckNotches(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.charmSlots, HKPlayerData.charmSlotsFilled); // ---------------- Geo Amount ----------------- //\n\n CheckGeo(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.geo, HKPlayerData.geoPool); // ---------------- Bosses (Base Game) --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.bosses, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES, HKPlayerData); // ---------------- Gruz Mother and Mawlek (World Map) --------------------- //\n\n if (HKWorldItems) CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.bosses, \"Battle Scene\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES_WORLD, HKWorldItems); // ---------------- Charms --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.charms, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.CHARMS, HKPlayerData); // ---------------- Colosseum of Fools --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.colosseum, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.COLOSSEUM, HKPlayerData); // ---------------- Dreamers --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.dreamers, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMERS, HKPlayerData); // ---------------- Dream Nail and Essence --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.dreamNail, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMNAIL, HKPlayerData); // ---------------- Equipment --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.equipment, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.EQUIPMENT, HKPlayerData); // ---------------- Nail Upgrades --------------------- //\n\n CheckNailUpgrades(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.nailUpgrades, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES, HKPlayerData); // ---------------- Mask Shards --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.maskShards, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS, HKPlayerData); // ---------------- Mask Shards (World Map) --------------------- //\n\n CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.maskShards, \"Heart Piece\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS_WORLD, HKWorldItems); // ---------------- Nail Arts --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.nailArts, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILARTS, HKPlayerData); // ---------------- Spells --------------------- //\n\n CheckSpellLevel(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.spells, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS, HKPlayerData); // ---------------- Vessel Fragments --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.vesselFragments, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS, HKPlayerData); // ---------------- Vessel Fragments (World Map) --------------------- //\n\n CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.vesselFragments, \"Vessel Fragment\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS_WORLD, HKWorldItems); // ---------------- Warrior Dreams --------------------- //\n\n CheckWarriorDreams(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.warriorDreams, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.WARRIORDREAMS, HKPlayerData); // ---------------- Grimm Troupe Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.grimmTroupe, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRIMMTROUPE, HKPlayerData); // ---------------- Lifeblood Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.lifeblood, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.LIFEBLOOD, HKPlayerData); // ---------------- Godmaster Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER, HKPlayerData);\n CheckGodmasterDoors(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS, HKPlayerData); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, FLEUR_DIVIDE); // ------------------------- Essential Things ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.essential, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ESSENTIAL, HKPlayerData, HKWorldItems); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.essential, FLEUR_DIVIDE); // ------------------------- Achievements ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.achievements, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS, HKPlayerData, HKWorldItems); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.achievements, FLEUR_DIVIDE); // ------------------------- Game Statistics ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.statistics, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.STATISTICS, HKPlayerData, HKWorldItems, HKSceneData); // ------------------------- Hints ----------------------------- //\n\n CheckHintsTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.hints, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.HINTS, HKPlayerData, HKWorldItems); // ------------------------- Fill completion ----------------------------- //\n\n CompletionHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID, HKPlayerData.completionPercentage); // Prevents wrong checkbox behaviour (must run after everything is finished)\n\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_2__.CheckboxHintsToggle)();\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_2__.CheckboxSpoilersToggle)(); // finish and show benchmark\n\n benchHKCCEnd = new Date();\n console.info(\"HKCheckCompletion() time (ms) =\", benchHKCCEnd - benchHKCCBegin);\n return true;\n}\n/**\r\n * Cleans \"generated\" and fills all HTML elements of ids from a given list. Creates only div with id, and h2 with title inside it.\r\n * @param {object} jsObj Object with HTML data to fill\r\n */\n\n\nfunction PrefillHTML(jsObj) {\n // Clean \"generated\" div\n document.getElementById(\"generated\").innerHTML = \"\";\n var id = \"\";\n var h2 = \"\";\n var h2id = \"\";\n var mp = \"\"; // max Percent\n\n var cl = \"\"; // class\n\n for (var i in jsObj) {\n id = jsObj[i].id;\n h2 = jsObj[i].h2;\n h2id = \"h2-\" + jsObj[i].id;\n mp = \"
\".concat(i === \"intro\" ? 0 : jsObj[i].maxPercent, \"%
\");\n if (!jsObj[i].hasOwnProperty(\"maxPercent\")) mp = \"\";\n document.getElementById(\"generated\").innerHTML += \"
\" + \"
\"; // document.getElementById(id).innerHTML += \"

\" + h2 + mp + \"

\";\n\n document.getElementById(id).innerHTML += \"

\").concat(h2).concat(mp, \"

\");\n }\n}\n/**\r\n * Replaces the h2 titles with a current percent/max percent values as read from the save file\r\n * @param {object} jsObj Object with HTML data to fill\r\n */\n\n\nfunction CompletionHTML(jsObj, hkGameCompletion) {\n var h2 = \"\";\n var h2id = \"\";\n var cl = \"\";\n var clGreen = \"box-green\";\n var clRed = \"box-red\";\n var cp = 0; // current Percent\n\n var mp = 0; // max Percent\n\n var fillText = \"\";\n\n for (var i in jsObj) {\n h2 = jsObj[i].h2;\n h2id = \"h2-\" + jsObj[i].id;\n jsObj[i].hasOwnProperty(\"percent\") ? cp = jsObj[i].percent : cp = 0;\n if (i === \"intro\") cp = hkGameCompletion; // Don't use percent-box for Essentials, Achievements, Statistics\n\n if (!jsObj[i].hasOwnProperty(\"maxPercent\")) {\n fillText = \"\";\n } // otherwise use percent-box with values cp/mp%\n else {\n mp = jsObj[i].maxPercent;\n\n if (i === \"maskShards\") {\n var perc = jsObj[i].percent;\n perc % 4 ? cp = Math.floor(perc / 4) : cp = perc / 4;\n } else if (i === \"vesselFragments\") {\n var _perc = jsObj[i].percent;\n _perc % 3 ? cp = Math.floor(_perc / 3) : cp = _perc / 3;\n } // switches the box to red when a section (h2) is 0\n\n\n if (cp === 0) {\n cl = \" \".concat(clRed);\n } // switches the box to green when a section (h2) is completed\n else if (cp === mp) {\n cl = \" \".concat(clGreen);\n } // default is blue (partially completed and starting value)\n else cl = \"\"; // needed for Game Status to show percentage properly (adds a slash for all boxes except the Game Status one)\n\n\n if (jsObj[i].hasOwnProperty(\"percent\")) cp += \"/\";\n fillText = \"
\").concat(i === \"intro\" ? cp : cp + jsObj[i].maxPercent, \"%
\");\n }\n\n document.getElementById(h2id).innerHTML = h2 + fillText;\n }\n}\n/**\r\n * Generates and appends a new entry inside the HTML of a given ID\r\n * @param {object} divId object containing div ID and h2 title of the HTML element\r\n * @param {string} textPrefix Main name of the entry\r\n * @param {string} textSuffix Optional suffix after the main name (spoilers: locations, costs etc.)\r\n */\n\n\nfunction FillHTML(divId) {\n var textPrefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"Unknown Completion Element: \";\n var textSuffix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"Unknown Description Element\";\n var icon = completionSymbol;\n var b = [\"\", \"\"];\n if (!textPrefix.length) b = [\"\", \"\"];\n var span = [\"\", \"\"];\n var spoilerSpan = [\"\", \"\"];\n\n if (divId === _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.hints) {\n span[0] = \"\";\n icon = \"\";\n }\n\n var dash = \"\";\n if (textSuffix.length && textPrefix.length) dash = \"— \";\n document.getElementById(divId.id).innerHTML += divStart + icon + b[0] + textPrefix + b[1] + span[0] + pSpan + spoilerSpan[0] + dash + textSuffix + spoilerSpan[1] + span[1] + divEnd;\n}\n/**\r\n * Adds HTML string to an element with a given ID.\r\n * @param {object} divId object containing div ID of the HTML element to append to\r\n * @param {string} content HTML contents to append\r\n */\n\n\nfunction AppendHTML(divId, content) {\n document.getElementById(divId.id).innerHTML += \"\\n\" + content;\n}\n/**\r\n * Switches global variable to a \"completed\" symbol. Adds +1 or +2 to percent property.\r\n */\n\n\nfunction CurrentDataTrue() {\n var divId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n completionSymbol = SYMBOL_TRUE;\n\n if (divId) {\n divId.percent++;\n if (divId.id === \"hk-equipment\") divId.percent++; // double % for equipment\n }\n}\n/**\r\n * Switches global variable to a \"not completed\" symbol\r\n */\n\n\nfunction CurrentDataFalse() {\n completionSymbol = SYMBOL_FALSE;\n}\n/**\r\n * Switches global variable to an \"information\" symbol\r\n */\n\n/* function CurrentDataInfo() {\r\n completionSymbol = SYMBOL_INFO;\r\n} */\n\n/**\r\n * Switches global variable to no symbol (span with left padding)\r\n */\n\n\nfunction CurrentDataBlank() {\n completionSymbol = SYMBOL_EMPTY;\n}\n/**\r\n * Fills HTML with the playTime value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} playTime Number of total gameplay time in seconds\r\n */\n\n\nfunction CheckPlayTime(divId, playTime) {\n var icon = \"\";\n var seconds = Math.floor(playTime);\n var minutes = Math.floor(seconds / 60 % 60);\n var hours = Math.floor(seconds / 3600);\n var sec = Math.floor(seconds % 60);\n if (sec < 10) sec = \"0\" + sec;\n if (minutes < 10) minutes = \"0\" + minutes;\n var textFill = \"Time Played:\" + pSpan + \"\" + hours + \" h \" + minutes + \" min \" + sec + \" sec\";\n document.getElementById(divId.id).innerHTML += divStart + icon + textFill + divEnd;\n}\n/**\r\n * Searches for completionPercentage in playerData and fills HTML with the value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} completionPercentage Number of completion percentage\r\n */\n\n\nfunction CheckCompletionPercent(divId, completionPercentage) {\n completionPercentage >= 112 ? CurrentDataTrue() : CurrentDataFalse();\n var textFill = \"Game Completion:\" + pSpan + \"\" + completionPercentage + \" %\" + pSpan + \"(out of \" + divId.maxPercent + \" %)\";\n document.getElementById(divId.id).innerHTML += divStart + completionSymbol + textFill + divEnd;\n}\n/**\r\n * Reads the \"version\" string from the save file and appends it to the selected div ID element\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {string} saveVersion Save File version in format 0.0.0.0\r\n */\n\n\nfunction CheckSaveFileVersion(divId) {\n var saveVersion = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro.saveVersion;\n CurrentDataBlank();\n var textFill = \"Save Version:\".concat(pSpan, \"\").concat(saveVersion, \"\").concat(pSpan);\n document.getElementById(divId.id).innerHTML += divStart + completionSymbol + textFill + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of health mask images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} masks Number of max health masks from the save (baseline without charms and lifeblood)\r\n * @param {number} permadeathMode Value of permadeathMode property. 0 = Normal, 1 = Steel Soul, 2 = Steel Soul broken save\r\n */\n\n\nfunction CheckHealthMasks(divId) {\n var masks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;\n var permadeathMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Health:\";\n var maskImages = \"\";\n var maskNormal = \"health mask image\");\n var maskSteel = \"steel health mask image\");\n var maskImg = \"\";\n permadeathMode > 0 ? maskImg = maskSteel : maskImg = maskNormal;\n\n for (var i = 0; i < masks; i++) {\n maskImages += maskImg;\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + maskImages + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of soul orbs images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} totalSoul Number of max Soul reserve from the save. 99 = full Soul Orb\r\n */\n\n\nfunction CheckSoulOrbs(divId, totalSoul) {\n var icon = SYMBOL_EMPTY;\n var textFill = \"Soul:\";\n var soulImages = \"\";\n var soulNormal = \"soul orb image\");\n var soulImg = soulNormal;\n\n for (var i = 0, total = totalSoul / 33; i < total; i++) {\n soulImages += soulImg;\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + soulImages + divEnd;\n}\n/**\r\n * Fills HTML with the Geo value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} geoValue Number of total Geo value\r\n */\n\n\nfunction CheckGeo(divId) {\n var geoValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var geoPoolValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Geo:geo symbol image\").concat(geoValue, \"\"); // Show Shade Geo value and image only if Shade has at least 1 Geo on it\n\n if (geoPoolValue > 0) textFill += \"\\n \".concat(pSpan, \"+shade geo symbol image\").concat(geoPoolValue, \"\"); // Show also total Geo (Geo + Shade Geo) if player has at least 1 geo alongside the shade geo\n\n if (geoValue > 0 && geoPoolValue > 0) textFill += \"\".concat(pSpan, \"=\").concat(pSpan, \"\").concat(geoValue + geoPoolValue, \"\");\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of notch images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} totalNotches Number of total Charm Notches the player has. 11 = max\r\n * @param {number} filledNotches Number of total used Charm Notches (including overcharmed notches). 15 = max\r\n */\n\n\nfunction CheckNotches(divId) {\n var totalNotches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;\n var filledNotches = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var _ = 0,\n overcharmedNotches = _.overcharmedNotches,\n unusedNotches = _.unusedNotches; // How many overcharmed notches images to show\n\n overcharmedNotches = filledNotches - totalNotches;\n if (overcharmedNotches < 1) overcharmedNotches = 0; // How many unused notches images to show\n\n unusedNotches = totalNotches - filledNotches;\n if (unusedNotches < 1) unusedNotches = 0; // Correct number of filled/used notches images to show when player is overcharmed\n\n if (filledNotches > totalNotches) filledNotches = totalNotches;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Notches:\".concat(pSpan);\n var notchImages = \"\";\n var notchNormalImage = \"notch image\");\n var notchFilledImage = \"notch image\");\n var notchOvercharmedImage = \"notch image\"); // First check filled (used) notches and fill them (skips if no filled notches)\n\n if (filledNotches > 0) {\n for (var i = 0; i < filledNotches; i++) {\n notchImages += notchFilledImage;\n }\n } // Second check overcharmed notches and fill them (skips if player is not overcharmed)\n\n\n if (overcharmedNotches > 0) {\n for (var _i = 0; _i < overcharmedNotches; _i++) {\n notchImages += notchOvercharmedImage;\n }\n } // Lastly, fill all unused notches\n\n\n if (unusedNotches > 0) {\n for (var _i2 = 0; _i2 < unusedNotches; _i2++) {\n notchImages += notchNormalImage;\n }\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + notchImages + divEnd;\n}\n/**\r\n * Verifies if the data in a specific object is true or false, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified (use copy - data inside this object will be deleted)\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckIfDataTrue(divId, dataObject, playerData) {\n var _ref = \"\",\n textPrefix = _ref.textPrefix,\n textSuffix = _ref.textSuffix;\n\n for (var i in dataObject) {\n textPrefix = dataObject[i].name;\n textSuffix = dataObject[i].spoiler;\n\n switch (i) {\n case \"gotCharm_36\":\n // prevents green checkbox and adding 1% when only got one white fragment\n playerData.gotQueenFragment === true && playerData.gotKingFragment === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n\n case \"gotCharm_37\":\n case \"gotCharm_38\":\n case \"gotCharm_39\":\n case \"gotCharm_40\":\n case \"killedGrimm\":\n case \"grimmChildLevel\":\n case \"killedHiveKnight\":\n case \"hasGodfinder\":\n // fades out the entries if save file is from older game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n if (i === \"grimmChildLevel\") {\n playerData.grimmChildLevel >= 4 ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n\n default:\n playerData[i] === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n }\n\n FillHTML(divId, textPrefix, textSuffix);\n }\n}\n/**\r\n * Verifies if the data in a specific object is 0 or > 0, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified (use copy - data inside this object will be deleted)\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckSpellLevel(divId, dataObject, playerData) {\n for (var i in dataObject) {\n switch (i) {\n case \"vengefulSpirit\":\n case \"shadeSoul\":\n playerData.fireballLevel >= dataObject[i].fireballLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n case \"desolateDive\":\n case \"descendingDark\":\n playerData.quakeLevel >= dataObject[i].quakeLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n case \"howlingWraiths\":\n case \"abyssShriek\":\n playerData.screamLevel >= dataObject[i].screamLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n default:\n break;\n }\n }\n}\n/**\r\n * Verifies if the data in a specific object is 0 or > 0, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckWarriorDreams(divId, dataObject, playerData) {\n for (var i in dataObject) {\n playerData[i] >= 2 ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n }\n}\n/**\r\n * Verifies if the Godmaster Pantheons 1-4 are completed by the player, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing pantheon data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search in the save file\r\n */\n\n\nfunction CheckGodmasterDoors(divId, dataObject, playerData) {\n // appends \"pantheon\" to every array element\n // same as names in the database object\n var pantheon = [\"Master\", \"Artist\", \"Sage\", \"Knight\"].map(function (element) {\n return \"pantheon\" + element;\n });\n\n for (var i = 0; i < 4; i++) {\n // compatibility with earlier game versions\n if (playerData.hasOwnProperty(\"bossDoorStateTier\" + (i + 1)) === false) {\n CurrentDataBlank();\n FillHTML(divId, \"\".concat(dataObject[pantheon[i]].name, \"\"), \"\".concat(dataObject[pantheon[i]].spoiler, \"\"));\n } else {\n playerData[\"bossDoorStateTier\" + (i + 1)].completed === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[pantheon[i]].name, dataObject[pantheon[i]].spoiler);\n }\n }\n}\n/**\r\n * Verifies the level of player's nail upgrades, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing nail upgrades data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search in the save file\r\n */\n\n\nfunction CheckNailUpgrades(divId, dataObject, playerData) {\n // appends \"Nail\" to every array element\n // same as names in the database object\n var nail = [\"old\", \"sharpened\", \"channeled\", \"coiled\", \"pure\"].map(function (element) {\n return element + \"Nail\";\n });\n\n for (var i = 0; i < 5; i++) {\n playerData.nailSmithUpgrades >= i ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[nail[i]].name, dataObject[nail[i]].spoiler);\n }\n\n if (divId.percent) divId.percent--; // subject one for the Old Nail\n}\n/**\r\n * Verifies if the data in a specific object are true or false, and appends HTML accordingly. Creates a copy of dataObject.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {string} idText Text string inside save data to search for\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} worldData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckWorldDataTrue(divId, idText, dataObject, worldData) {\n var orderedArray = [];\n var size = (0,_hk_functions_js__WEBPACK_IMPORTED_MODULE_3__.ObjectLength)(dataObject); // Order the items before displaying them (creates a copy of dataObject)\n\n for (var i in dataObject) {\n orderedArray.push([i, dataObject[i].name, dataObject[i].spoiler, false]);\n } // Search for completed items and mark them for display\n\n\n for (var _i3 = 0, length = worldData.length; _i3 < length; _i3++) {\n for (var j = 0; j < size; j++) {\n if (worldData[_i3].id === idText && worldData[_i3].sceneName === orderedArray[j][0] && worldData[_i3].activated === true) {\n orderedArray[j][3] = true;\n }\n }\n } // Display the items as they were initially ordered\n\n\n for (var _i4 = 0; _i4 < size; _i4++) {\n CurrentDataFalse();\n if (orderedArray[_i4][3] === true) CurrentDataTrue(divId);\n FillHTML(divId, orderedArray[_i4][1], orderedArray[_i4][2]);\n }\n}\n/**\r\n * Verifies if the data in a specific object are true or false, or checks what values they have, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n * @param {object} worldData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckAdditionalThings(divId, dataObject, playerData, worldData, sceneData) {\n var textPrefix = \"\";\n var textSuffix = \"\"; // Start main loop\n\n for (var i in dataObject) {\n textPrefix = dataObject[i].name;\n dataObject[i].hasOwnProperty(\"spoiler\") ? textSuffix = dataObject[i].spoiler : textSuffix = \"\";\n var _2 = 0,\n amount = _2.amount,\n countTotal = _2.countTotal,\n total = _2.total,\n unbroken = _2.unbroken,\n broken = _2.broken,\n discoveredTotal = _2.discoveredTotal;\n\n switch (i) {\n case \"areaMaps\":\n case \"grubsCollected\":\n case \"dreamOrbs\":\n case \"fountainGeo\":\n case \"nailDamage\":\n case \"stationsOpened\":\n case \"charmSlots\":\n case \"whisperingRoots\":\n case \"journalEntriesCompleted\":\n case \"journalNotesCompleted\":\n case \"whiteDefenderDefeats\":\n case \"greyPrinceDefeats\":\n if (i === \"areaMaps\") {\n amount = CountMaps(dataObject[i].list);\n } else if (i === \"whisperingRoots\") {\n amount = CountWorldItem(\"Dream Plant\");\n } else {\n amount = playerData[i];\n }\n\n if (i === \"stationsOpened\") {\n if (playerData.openedHiddenStation === true) amount++;\n }\n\n countTotal = amount;\n\n if (i === \"journalEntriesCompleted\" || i === \"journalNotesCompleted\") {\n countTotal = amount + \" / \" + playerData.journalEntriesTotal;\n }\n\n if (i === \"grubsCollected\") LogMissingGrubs();\n textPrefix += \": \" + countTotal;\n\n if (i === \"greyPrinceDefeats\") {\n // backwards compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(dataObject[i].name, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n } else if (playerData.zoteDead === true || playerData.zoteRescuedBuzzer === false && playerData.hasWalljump === true) {\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n }\n }\n\n if (i === \"whiteDefenderDefeats\") {\n // backwards compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(dataObject[i].name, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n }\n\n amount >= dataObject[i].max ? CurrentDataTrue() : CurrentDataBlank();\n break;\n\n case \"geoPool\":\n case \"rancidEggs\":\n case \"jinnEggsSold\":\n case \"xunFlowerBrokeTimes\":\n textPrefix += \": \" + Math.abs(playerData[i]);\n i === \"geoPool\" && playerData[i] > 0 ? CurrentDataBlank() : CurrentDataTrue();\n\n if (i === \"jinnEggsSold\") {\n // fade out if not on Steel Soul\n if (playerData.permadeathMode < 1) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n }\n\n break;\n\n case \"geoRocks\":\n discoveredTotal = sceneData.geoRocks.length;\n unbroken = CountGeoRocks(discoveredTotal, \"unbroken\");\n broken = CountGeoRocks(discoveredTotal, \"broken\");\n textPrefix += \": \".concat(unbroken, \" | \").concat(broken, \" | \").concat(discoveredTotal);\n CurrentDataTrue();\n break;\n\n case \"shopkeeperKey\":\n playerData.hasSlykey === true || playerData.gaveSlykey === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"elegantKey\":\n playerData.hasWhiteKey === true || playerData.usedWhiteKey === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"loveKey\":\n playerData.hasLoveKey === true || playerData.openedLoveDoor === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"simpleKeyCityOfTears\":\n // #2\n FindWorldItem(\"Ruins1_17\", \"Shiny Item\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"simpleKeyAncientBasin\":\n // #3\n FindWorldItem(\"Abyss_20\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"gotLurkerKey\":\n case \"nightmareLanternLit\":\n case \"killedPaleLurker\":\n case \"whiteDefenderDefeated\":\n case \"gotGrimmNotch\":\n case \"fragileGreed_unbreakable\":\n case \"fragileHealth_unbreakable\":\n case \"fragileStrength_unbreakable\":\n case \"killedBindingSeal\":\n case \"killedGodseekerMask\":\n case \"givenGodseekerFlower\":\n case \"givenOroFlower\":\n case \"givenWhiteLadyFlower\":\n case \"givenEmilitiaFlower\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreAncientBasin\":\n // #1\n FindWorldItem(\"Abyss_17\", \"Battle Scene Ore\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreSeer\":\n // #2\n playerData.dreamReward2 === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreCrystalPeak\":\n // #3\n FindWorldItem(\"Mines_34\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreDeepnest\":\n // #4\n FindWorldItem(\"Deepnest_32\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreGrubfather\":\n // #5\n FindWorldItem(\"Crossroads_38\", \"Shiny Item Ore\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreColosseum\":\n // #6\n FindWorldItem(\"Room_Colosseum_Silver\", \"Shiny Item\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"relicsWandererJournal\":\n case \"relicsHallownestSeal\":\n case \"relicsKingsIdol\":\n case \"relicsArcaneEgg\":\n total = playerData[dataObject[i].nameHeld] + playerData[dataObject[i].nameSold];\n total >= dataObject[i].max ? CurrentDataTrue() : CurrentDataBlank();\n textPrefix += \": \" + total;\n break;\n\n case \"bossDoorStateTier5\":\n if (playerData.hasOwnProperty(\"bossDoorStateTier5\") === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n } else {\n playerData[i].completed === true ? CurrentDataTrue() : CurrentDataFalse();\n }\n\n break;\n\n case \"killsBindingSeal\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] == 0 ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"killedVoidIdol_1\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n if (playerData[i] === false && (playerData.killedVoidIdol_2 === true || playerData.killedVoidIdol_3 === true)) CurrentDataTrue();\n break;\n\n case \"killedVoidIdol_2\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n if (playerData[i] === false && playerData.killedVoidIdol_3 === true) CurrentDataTrue();\n break;\n\n case \"killedVoidIdol_3\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"greyPrinceDefeated\":\n // compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n } else if (playerData.zoteDead === true || playerData.zoteRescuedBuzzer === false && playerData.hasWalljump === true) {\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataBlank();\n if (playerData.zoteRescuedBuzzer === true && playerData[i] === false) CurrentDataFalse();\n break;\n\n case \"zoteStatus\":\n CurrentDataFalse();\n\n if (playerData.zoteDead === true) {\n textPrefix = dataObject[i].nameNeglect;\n textSuffix = dataObject[i].spoilerNeglect;\n CurrentDataTrue();\n } else if (playerData.killedZote === true) {\n textPrefix = dataObject[i].nameRivalry;\n textSuffix = dataObject[i].spoilerRivalry;\n CurrentDataTrue();\n } else if (playerData.zoteRescuedBuzzer === false) {\n if (playerData.hasWalljump === false) {\n textPrefix = dataObject[i].nameTrappedVengefly;\n textSuffix = dataObject[i].spoilerTrappedVengefly;\n } else if (playerData.hasWalljump === true) {\n textPrefix = dataObject[i].nameNotRescuedVengefly;\n textSuffix = dataObject[i].spoilerNotRescuedVengefly;\n }\n } else if (playerData.zoteRescuedBuzzer === true) {\n if (playerData.zoteRescuedDeepnest === false) {\n textPrefix = dataObject[i].nameTrappedDeepnest;\n textSuffix = dataObject[i].spoilerTrappedDeepnest;\n } else if (playerData.zoteRescuedDeepnest === true) {\n if (playerData.killedZote === false) {\n textPrefix = dataObject[i].nameColosseum;\n textSuffix = dataObject[i].spoilerColosseum;\n }\n }\n }\n\n break;\n\n case \"nailsmithStatus\":\n CurrentDataFalse();\n\n if (playerData.nailsmithKilled === true) {\n textPrefix = dataObject[i].namePurity;\n textSuffix = dataObject[i].spoilerPurity;\n CurrentDataTrue();\n } else if (playerData.nailsmithConvoArt === true) {\n textPrefix = dataObject[i].nameHappyCouple;\n textSuffix = dataObject[i].spoilerHappyCouple;\n CurrentDataTrue();\n } else if (playerData.nailsmithSpared === true) {\n textPrefix = dataObject[i].nameSheoHutWaiting;\n textSuffix = dataObject[i].spoilerSheoHutWaiting;\n } else {\n textPrefix = dataObject[i].nameUpgradeNail;\n textSuffix = dataObject[i].spoilerUpgradeNail;\n }\n\n break;\n\n case \"mrMushroomState\":\n CheckMrMushroomState(divId, dataObject[i], playerData[i]);\n break;\n\n default:\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n } // end switch (i)\n\n\n if (i === \"mrMushroomState\") continue;\n FillHTML(divId, textPrefix, textSuffix);\n } // end for (let i in dataObject)\n // ==========================================\n // -------------- Methods ---------------- //\n\n /**\r\n * Searches for a given item in the in-game area and returns true when found and collected.\r\n * @param {string} itemArea Code of the in-game area on the map\r\n * @param {string} itemId Name of the item\r\n * @returns {boolean}\r\n */\n\n\n function FindWorldItem() {\n var itemArea = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var itemId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"Shiny Item\";\n\n for (var _i5 = 0, length = worldData.length; _i5 < length; _i5++) {\n if (worldData[_i5].id === itemId) {\n if (worldData[_i5].sceneName === itemArea) {\n if (worldData[_i5].activated === true) return true;\n }\n }\n }\n\n return false;\n }\n /**\r\n * Searches for a given item that the player has found and returns the amount of them that the player completed.\r\n * @param {string} itemId Name of the item\r\n * @returns {number}\r\n */\n\n\n function CountWorldItem() {\n var itemId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var total = 0;\n\n for (var _i6 = 0, length = worldData.length; _i6 < length; _i6++) {\n if (worldData[_i6].id === itemId) {\n if (worldData[_i6].activated === true) total++;\n }\n }\n\n return total;\n }\n /**\r\n * Counts the number of maps the player has acquired (from the list in an array)\r\n * @param {array} mapArray Array of strings with area map names\r\n * @returns {number}\r\n */\n\n\n function CountMaps(mapArray) {\n var totalMaps = 0;\n\n for (var _i7 = 0, len = mapArray.length; _i7 < len; _i7++) {\n if (playerData[mapArray[_i7]] === true) totalMaps++;\n }\n\n return totalMaps;\n }\n /**\r\n * Counts the total amount of Geo Rocks Unbroken or Broken. Logs to console all the Unbroken IDs and Map locations.\r\n * @param {number} arrayLength How many items the Geo Rocks array is currently storing (for iteration)\r\n * @param {string} mode Choose which Geo Rocks to count (broken or unbroken)\r\n */\n\n\n function CountGeoRocks(arrayLength) {\n var mode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"unbroken\";\n var countTotal = 0;\n var geoRocksLog = [];\n\n if (mode === \"unbroken\") {\n for (var _i8 = 0; _i8 < arrayLength; _i8++) {\n if (sceneData.geoRocks[_i8].hitsLeft > 0) {\n countTotal++;\n geoRocksLog.push(\"#\".concat(countTotal, \" \\uD83C\\uDFD4\\uFE0F \").concat(sceneData.geoRocks[_i8].id, \" \\uD83D\\uDDFA\\uFE0F \").concat(TranslateMapName(sceneData.geoRocks[_i8].sceneName), \" \\u2328\\uFE0F \").concat(sceneData.geoRocks[_i8].sceneName));\n }\n }\n\n if (!countTotal) {\n console.log(\"%cAll Geo Rocks Broken!\", \"color: #16c60c; font-weight: 700;\");\n } else {\n console.groupCollapsed(\"%cUnbroken Geo Rocks (\".concat(countTotal, \"):\"), \"color: #16c60c; font-weight: 700;\");\n\n for (var _i9 = 0, length = geoRocksLog.length; _i9 < length; _i9++) {\n console.log(geoRocksLog[_i9]);\n }\n\n console.groupEnd();\n }\n } else {\n for (var _i10 = 0; _i10 < arrayLength; _i10++) {\n if (sceneData.geoRocks[_i10].hitsLeft === 0) countTotal++;\n }\n }\n\n return countTotal;\n }\n /**\r\n * Compares and logs all unrescued Grubs in a list: IDs and map locations\r\n */\n\n\n function LogMissingGrubs() {\n var rescuedGrubsSceneList = [];\n\n for (var _i11 = 0, _length = worldData.length; _i11 < _length; _i11++) {\n if (worldData[_i11].id.includes(\"Grub Bottle\")) {\n if (worldData[_i11].activated === true) {\n // There are 3 duplicates of the same map scene name from older game save files. Prevents adding duplicates\n\n /* if (worldData[i].sceneName === \"Ruins2_11\" && worldData[i].id === \"Grub Bottle (1)\") {\r\n continue;\r\n } else if (worldData[i].sceneName === \"Ruins2_11\" && worldData[i].id === \"Grub Bottle (2)\") {\r\n continue;\r\n } else { */\n rescuedGrubsSceneList.push(worldData[_i11].sceneName); // }\n }\n }\n } // Filtering the reference database Grub list to include only the missing values\n\n\n var missingGrubsList = _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRUBS_LIST.filter(function (x) {\n return !rescuedGrubsSceneList.includes(x);\n });\n var length = missingGrubsList.length;\n\n if (!length) {\n console.log(\"%cAll Grubs Rescued!\", \"color: #16c60c; font-weight: 700;\");\n } else {\n console.groupCollapsed(\"%cUnrescued Grubs (\".concat(length, \"):\"), \"color: #16c60c; font-weight: 700;\");\n\n for (var _i12 = 0; _i12 < length; _i12++) {\n console.log(\"#\".concat(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRUBS_LIST.indexOf(missingGrubsList[_i12]) + 1, \" \\uD83D\\uDDFA\\uFE0F \").concat(TranslateMapName(missingGrubsList[_i12]), \" \\u2328\\uFE0F \").concat(missingGrubsList[_i12]));\n }\n\n console.groupEnd();\n }\n\n return false;\n }\n}\n/**\r\n * Checks and fills all the 7 locations of Mr Mushroom.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject object containing the Mr Mushroom name and spoilers/locations\r\n * @param {number} mrMushroomState playerData.mrMushroomState read from the save file. (0-8)\r\n */\n\n\nfunction CheckMrMushroomState(divId, dataObject) {\n var mrMushroomState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n\n if (mrMushroomState > 1) {\n for (var i = 1; i <= 7; i++) {\n mrMushroomState > i ? CurrentDataTrue() : CurrentDataFalse();\n FillHTML(divId, \"\".concat(dataObject.name, \" #\").concat(i), dataObject[\"spoiler\" + i]);\n }\n } else {\n CurrentDataFalse();\n\n for (var _i13 = 1; _i13 <= 7; _i13++) {\n FillHTML(divId, \"\".concat(dataObject.name, \" #\").concat(_i13), dataObject[\"spoiler\" + _i13]);\n }\n }\n}\n/**\r\n * Checks, validates and shows hints to the player depending on their save progression, in chronological order. Shows only hint for the last uncompleted event. If Hollow Knight is defeated, shows a dummy text.\r\n * @param {object} divId object containing div hints ID and h2 title\r\n * @param {object} dataObject object containing all hints data\r\n * @param {object} playerData object containing HK Player Data to look in\r\n * @param {object} worldData object containing HK World Data to look in\r\n * @returns {bool} true when defeated Hollow Knight, false if not\r\n */\n\n\nfunction CheckHintsTrue(divId, dataObject, playerData, worldData) {\n if (playerData.killedHollowKnight === true) {\n // a text to show when player already finished their first playthrough (killed Hollow Knight first time)\n FillHTML(divId, \"\", \"...a successful Knight who doesn't need hints anymore. The Knight explores the world of Hallownest patiently in constant search of its remaining secrets...\");\n return true;\n }\n\n for (var i in dataObject) {\n if (playerData[i] === true) {\n continue;\n } else if (i === \"fireballLevel\") {\n if (playerData[i] >= 1) {\n continue;\n } else {\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"Crossroads_04\") {\n var GruzMotherDefeated = false;\n\n for (var k = 0, length = worldData.length; k < length; k++) {\n if (worldData[k].id === \"Battle Scene\" && worldData[k].sceneName === \"Crossroads_04\" && worldData[k].activated === true) {\n GruzMotherDefeated = true;\n break;\n }\n }\n\n if (GruzMotherDefeated) {\n continue; // next dataObject (i)\n } else {\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"dungDefenderOrHornet2\") {\n if (playerData.defeatedDungDefender === true) {\n continue;\n } else if (playerData.hornetOutskirtsDefeated === true) {\n continue;\n } else {\n // if no Dung Defender or Hornet 2\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"ismaTearOrShadeCloak\") {\n if (playerData.hasAcidArmour === true) {\n continue;\n } else if (playerData.hasKingsBrand === true) {\n if (playerData.hasShadowDash === true) {\n continue;\n } else {\n // if Kings Brand but no Shade Cloak\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else {\n // if no Isma's Tear or Kings Brand\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else {\n // if anything from the hints list is not done\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } // end: for (let i in dataObject)\n\n} // function CheckHintsTrue()\n\n/**\r\n * Pre-Cleans HTML. Reads contents inside text area and parses it to a JavaScript object. If not empty, runs HKCheckCompletion() to check data.\r\n */\n\n\nfunction HKReadTextArea() {\n var textAreaId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n // refresh and prepare document for filling with data from the save\n InitialHTMLPopulate(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID);\n var contents = document.getElementById(textAreaId).value;\n\n if (contents.length) {\n try {\n var jsonObject = JSON.parse(contents); // console.log(jsonObject);\n\n if (jsonObject.hasOwnProperty(\"playerData\")) HKCheckCompletion(jsonObject); // console.log(jsonObject);\n } catch (error) {\n alert(\"This seems like not a valid Hollow Knight save. \".concat(error));\n console.info(\"This seems like not a valid Hollow Knight save. \".concat(error));\n }\n }\n}\n/**\r\n * Populate all HTML with given ID and their initial data set as false (used at DOM load)\r\n * @param {object} divIdObj JavaScript Object containing all HTML IDs to populate\r\n */\n\n\nfunction InitialHTMLPopulate(divIdObj) {\n CurrentDataFalse();\n PrefillHTML(divIdObj); // Play Time\n\n CheckPlayTime(divIdObj.intro, 0); // Game Completion\n\n CheckCompletionPercent(divIdObj.intro, 0); // Save File Version\n\n CheckSaveFileVersion(divIdObj.intro); // Fleur Divide\n\n AppendHTML(divIdObj.intro, FLEUR_DIVIDE); // Health Masks\n\n CheckHealthMasks(divIdObj.intro); // Soul Orbs\n\n CheckSoulOrbs(divIdObj.intro, 99); // Charm Notches\n\n CheckNotches(divIdObj.intro); // Geo\n\n CheckGeo(divIdObj.intro); // Keep symbol False\n\n CurrentDataFalse(); // First Hint Only\n\n FillHTML(divIdObj.hints, \"\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.HINTS.fireballLevel.spoiler); // Temp arrays storing references (addresses) to objects for looping through them (duplicates important)\n\n var hkObjArray = [_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.CHARMS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.EQUIPMENT, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILARTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMERS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.COLOSSEUM, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMNAIL, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.WARRIORDREAMS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRIMMTROUPE, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.LIFEBLOOD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ESSENTIAL, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.STATISTICS]; // duplicates and order important - must be the same as in hkObjArray[]\n\n var divObjArray = [divIdObj.bosses, divIdObj.bosses, divIdObj.charms, divIdObj.equipment, divIdObj.nailArts, divIdObj.maskShards, divIdObj.maskShards, divIdObj.vesselFragments, divIdObj.vesselFragments, divIdObj.dreamers, divIdObj.colosseum, divIdObj.dreamNail, divIdObj.warriorDreams, divIdObj.grimmTroupe, divIdObj.lifeblood, divIdObj.godmaster, divIdObj.essential, divIdObj.achievements, divIdObj.statistics]; // Looped filling to reduce redundancy\n\n do {\n for (var entry in hkObjArray[0]) {\n if (entry === \"mrMushroomState\") continue;\n FillHTML(divObjArray[0], hkObjArray[0][entry].name, hkObjArray[0][entry].spoiler);\n }\n\n divObjArray.shift();\n } while (hkObjArray.shift()); // Nail Upgrades Misc\n\n\n for (var i in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES) {\n FillHTML(divIdObj.nailUpgrades, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES[i].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES[i].spoiler);\n } // Spells Misc\n\n\n for (var _i14 in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS) {\n FillHTML(divIdObj.spells, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS[_i14].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS[_i14].spoiler);\n } // Godmaster Doors Misc\n\n\n for (var _i15 in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS) {\n FillHTML(divIdObj.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS[_i15].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS[_i15].spoiler);\n } // Mr Mushroom 1 - 7\n\n\n CheckMrMushroomState(divIdObj.achievements, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS.mrMushroomState); // Fleur Dividers\n\n AppendHTML(divIdObj.godmaster, FLEUR_DIVIDE);\n AppendHTML(divIdObj.essential, FLEUR_DIVIDE);\n AppendHTML(divIdObj.achievements, FLEUR_DIVIDE); // Check local storage first to set proper checkbox state before the below functions start (default is always unchecked)\n\n if ((0,_page_functions_js__WEBPACK_IMPORTED_MODULE_2__.StorageAvailable)('localStorage')) {\n if (localStorage.getItem(\"hkCheckboxHints\") === \"checked\") document.getElementById(\"checkbox-hints\").checked = true;\n if (localStorage.getItem(\"hkCheckboxSpoilers\") === \"checked\") document.getElementById(\"checkbox-spoilers\").checked = true;\n } // if (localStorage.getItem(\"hkCheckboxHints\") === \"checked\") document.getElementById(\"checkbox-hints\").checked = true;\n // if (localStorage.getItem(\"hkCheckboxSpoilers\") === \"checked\") document.getElementById(\"checkbox-spoilers\").checked = true;\n // Prevents wrong checkbox behaviour (must run after everything is finished)\n\n\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_2__.CheckboxHintsToggle)();\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_2__.CheckboxSpoilersToggle)();\n}\n/**\r\n * Zero-fill all \"percent\" properties in the JSON Object (reset to default)\r\n * @param {object} jsObj object containing the \"percent\" properties to be reset to 0\r\n */\n\n\nfunction ResetCompletion(jsObj) {\n for (var i in jsObj) {\n if (jsObj[i].hasOwnProperty(\"percent\")) jsObj[i].percent = 0;\n }\n}\n/**\r\n * Focuses, selects and copies to clipboard contents inside a clicked element. Includes optional tooltip update after the copying is done.\r\n * @param {MouseEvent} mouseEvent from the clicked element (AddEventListener)\r\n * @param {string} tooltipId Element ID of the tooltip to update\r\n * @param {string} tooltipFill Updated contents of the tooltip\r\n */\n\n\nfunction SelectCopyInputText(mouseEvent) {\n var tooltipId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n var tooltipFill = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"\";\n var element = document.getElementById(mouseEvent.target.id); // this prevents the un-selected effect after clicking the second time (clears all selection first)\n\n if (window.getSelection) {\n window.getSelection().removeAllRanges();\n }\n\n element.focus(); // best to focus the element first before selecting\n\n element.select();\n element.setSelectionRange(0, 99999); // for mobile devices\n // Copy the text inside the text field to clipboard\n\n document.execCommand(\"copy\"); // optional tooltip showing\n\n if (tooltipFill.length && tooltipId.length) FillInnerHTML(tooltipId, tooltipFill);\n}\n/**\r\n * Fills the innerHTML of a given HTML Element with provided contents\r\n * @param {string} elementId Element ID to update\r\n * @param {string} textFill Updated contents (innerHTML)\r\n */\n\n\nfunction FillInnerHTML(elementId, textFill) {\n var element = document.getElementById(elementId);\n element.innerHTML = textFill;\n}\n/**\r\n * Returns a translated map location name string.\r\n * @param {string} mapCode Code of the Hollow Knight map location the game developers use\r\n * @param {object} dictionary Main data source for translation\r\n */\n\n\nfunction TranslateMapName(mapCode) {\n var dictionary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _hk_dictionary_js__WEBPACK_IMPORTED_MODULE_1__.default;\n var translation = mapCode;\n if (dictionary.hasOwnProperty(mapCode)) translation = dictionary[mapCode];\n return translation;\n} // Populate HTML at load (before img and css)\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n InitialHTMLPopulate(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID);\n}); // Does an action when the save file location input text is clicked once (auto select & copy to clipboard)\n\ndocument.getElementById(\"save-location-input\").addEventListener(\"click\", function (e) {\n SelectCopyInputText(e, \"save-location-input-tooltip\", \"Copied save file location to clipboard\");\n}, false); // Choose File input field\n\ndocument.getElementById(\"save-location-input\").addEventListener(\"mouseout\", function () {\n FillInnerHTML(\"save-location-input-tooltip\", \"Click once to copy to clipboard\");\n}, false); // Analyze Text button\n\ndocument.getElementById(\"save-area-read\").addEventListener(\"click\", function () {\n HKReadTextArea(\"save-area\");\n}, false);\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/HKCheckCompletion.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"HKReadTextArea\": () => /* binding */ HKReadTextArea\n/* harmony export */ });\n/* harmony import */ var _hk_database_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hk-database.js */ \"./src/js/hk-database.js\");\n/* harmony import */ var _page_functions_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./page-functions.js */ \"./src/js/page-functions.js\");\n/* harmony import */ var _hk_functions_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./hk-functions.js */ \"./src/js/hk-functions.js\");\n/* harmony import */ var _img_health_mask_png__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../img/health-mask.png */ \"./src/img/health-mask.png\");\n/* harmony import */ var _img_health_mask_steel_png__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../img/health-mask-steel.png */ \"./src/img/health-mask-steel.png\");\n/* harmony import */ var _img_soul_orb_png__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../img/soul-orb.png */ \"./src/img/soul-orb.png\");\n/* harmony import */ var _img_notch_png__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../img/notch.png */ \"./src/img/notch.png\");\n/* harmony import */ var _img_notch_filled_png__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../img/notch-filled.png */ \"./src/img/notch-filled.png\");\n/* harmony import */ var _img_notch_overcharmed_png__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../img/notch-overcharmed.png */ \"./src/img/notch-overcharmed.png\");\n/* harmony import */ var _img_geo_png__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../img/geo.png */ \"./src/img/geo.png\");\n/* harmony import */ var _img_geo_shade_png__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../img/geo-shade.png */ \"./src/img/geo-shade.png\");\n/* eslint-disable no-prototype-builtins */\n\n/* ---------------- Load main Hollow Knight database files ----------------- */\n\n/* ----------------- Helper functions --------------------------------------- */\n\n\n // ---------------- Load image files (necessary for Webpack) ----------------- //\n\n\n\n\n\n\n\n\n // ---------------- Constants ----------------- //\n// const DATA_UNKNOWN = \"Data unknown\";\n\nvar SYMBOL_FALSE = \"\"; // \"❌ \"\n\nvar SYMBOL_TRUE = \"\"; // \"✅ \"\n// const SYMBOL_INFO = \"\"; // \"ℹ \"\n\nvar SYMBOL_EMPTY = \"\";\nvar FLEUR_DIVIDE = \"
\"; // ---------------- Variables ----------------- //\n// let currentData = DATA_UNKNOWN;\n\nvar completionSymbol = SYMBOL_FALSE;\nvar divStart = [\"
\"].join(\"\\n\");\nvar divStartCenter = [\"
\"].join(\"\\n\");\nvar divEnd = [\"
\"].join(\"\\n\");\nvar pSpan = \"\";\nvar benchHKCCBegin, benchHKCCEnd;\n/* -------------------------- Functions ----------------------------- */\n\n/**\r\n * Main Function. Checks Hollow Knight game completion by analyzing the save file\r\n * @param {object} jsonObject Decoded save data in JavaScript Object Notation form (JSON)\r\n */\n\nfunction HKCheckCompletion(jsonObject) {\n // start benchmark\n benchHKCCBegin = new Date();\n var HKPlayerData;\n var HKWorldItems;\n var HKSceneData;\n\n if (jsonObject.hasOwnProperty(\"playerData\")) {\n HKPlayerData = jsonObject.playerData;\n } else return false;\n\n if (jsonObject.hasOwnProperty(\"sceneData\")) {\n HKSceneData = jsonObject.sceneData;\n\n if (jsonObject.sceneData.hasOwnProperty(\"persistentBoolItems\")) {\n HKWorldItems = jsonObject.sceneData.persistentBoolItems;\n } else return false;\n } else return false; // Pre-Cleaning and filling initial data (h2, id) needed for FillHTML()\n\n\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.PrefillHTML)(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID); // Prevents adding current percent data after each function call (each click of Analyze button)\n\n ResetCompletion(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID); // ================================================================================== //\n // ---------------- Time Played ----------------- //\n\n CheckPlayTime(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.playTime); // ---------------- Game Completion Status ----------------- //\n\n CheckCompletionPercent(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.completionPercentage); // ---------------- Game Completion Status ----------------- //\n\n CheckSaveFileVersion(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.version); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, FLEUR_DIVIDE); // ---------------- Health Masks ----------------- //\n\n CheckHealthMasks(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.maxHealthBase, HKPlayerData.permadeathMode); // ---------------- Soul Orbs ----------------- //\n\n CheckSoulOrbs(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.maxMP + HKPlayerData.MPReserveMax); // ---------------- Charm Notches (Slots) ----------------- //\n\n CheckNotches(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.charmSlots, HKPlayerData.charmSlotsFilled); // ---------------- Geo Amount ----------------- //\n\n CheckGeo(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro, HKPlayerData.geo, HKPlayerData.geoPool); // ---------------- Bosses (Base Game) --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.bosses, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES, HKPlayerData); // ---------------- Gruz Mother and Mawlek (World Map) --------------------- //\n\n if (HKWorldItems) CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.bosses, \"Battle Scene\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES_WORLD, HKWorldItems); // ---------------- Charms --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.charms, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.CHARMS, HKPlayerData); // ---------------- Colosseum of Fools --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.colosseum, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.COLOSSEUM, HKPlayerData); // ---------------- Dreamers --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.dreamers, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMERS, HKPlayerData); // ---------------- Dream Nail and Essence --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.dreamNail, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMNAIL, HKPlayerData); // ---------------- Equipment --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.equipment, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.EQUIPMENT, HKPlayerData); // ---------------- Nail Upgrades --------------------- //\n\n CheckNailUpgrades(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.nailUpgrades, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES, HKPlayerData); // ---------------- Mask Shards --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.maskShards, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS, HKPlayerData); // ---------------- Mask Shards (World Map) --------------------- //\n\n CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.maskShards, \"Heart Piece\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS_WORLD, HKWorldItems); // ---------------- Nail Arts --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.nailArts, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILARTS, HKPlayerData); // ---------------- Spells --------------------- //\n\n CheckSpellLevel(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.spells, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS, HKPlayerData); // ---------------- Vessel Fragments --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.vesselFragments, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS, HKPlayerData); // ---------------- Vessel Fragments (World Map) --------------------- //\n\n CheckWorldDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.vesselFragments, \"Vessel Fragment\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS_WORLD, HKWorldItems); // ---------------- Warrior Dreams --------------------- //\n\n CheckWarriorDreams(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.warriorDreams, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.WARRIORDREAMS, HKPlayerData); // ---------------- Grimm Troupe Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.grimmTroupe, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRIMMTROUPE, HKPlayerData); // ---------------- Lifeblood Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.lifeblood, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.LIFEBLOOD, HKPlayerData); // ---------------- Godmaster Content Pack --------------------- //\n\n CheckIfDataTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER, HKPlayerData);\n CheckGodmasterDoors(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS, HKPlayerData); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.godmaster, FLEUR_DIVIDE); // ------------------------- Essential Things ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.essential, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ESSENTIAL, HKPlayerData, HKWorldItems); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.essential, FLEUR_DIVIDE); // ------------------------- Achievements ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.achievements, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS, HKPlayerData, HKWorldItems); // ---------------- Fleur Divide ----------------- //\n\n AppendHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.achievements, FLEUR_DIVIDE); // ------------------------- Game Statistics ----------------------------- //\n\n CheckAdditionalThings(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.statistics, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.STATISTICS, HKPlayerData, HKWorldItems, HKSceneData); // ------------------------- Hints ----------------------------- //\n\n CheckHintsTrue(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.hints, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.HINTS, HKPlayerData, HKWorldItems); // ------------------------- Fill completion ----------------------------- //\n\n CompletionHTML(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID, HKPlayerData.completionPercentage); // Prevents wrong checkbox behaviour (must run after everything is finished)\n\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.CheckboxHintsToggle)();\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.CheckboxSpoilersToggle)(); // finish and show benchmark\n\n benchHKCCEnd = new Date();\n console.info(\"HKCheckCompletion() time (ms) =\", benchHKCCEnd - benchHKCCBegin);\n return true;\n}\n/**\r\n * Replaces the h2 titles with a current percent/max percent values as read from the save file\r\n * @param {object} jsObj Object with HTML data to fill\r\n */\n\n\nfunction CompletionHTML(jsObj, hkGameCompletion) {\n var h2 = \"\";\n var h2id = \"\";\n var cl = \"\";\n var clGreen = \"box-green\";\n var clRed = \"box-red\";\n var cp = 0; // current Percent\n\n var mp = 0; // max Percent\n\n var fillText = \"\";\n\n for (var i in jsObj) {\n h2 = jsObj[i].h2;\n h2id = \"h2-\" + jsObj[i].id;\n jsObj[i].hasOwnProperty(\"percent\") ? cp = jsObj[i].percent : cp = 0;\n if (i === \"intro\") cp = hkGameCompletion; // Don't use percent-box for Essentials, Achievements, Statistics\n\n if (!jsObj[i].hasOwnProperty(\"maxPercent\")) {\n fillText = \"\";\n } // otherwise use percent-box with values cp/mp%\n else {\n mp = jsObj[i].maxPercent;\n\n if (i === \"maskShards\") {\n var perc = jsObj[i].percent;\n perc % 4 ? cp = Math.floor(perc / 4) : cp = perc / 4;\n } else if (i === \"vesselFragments\") {\n var _perc = jsObj[i].percent;\n _perc % 3 ? cp = Math.floor(_perc / 3) : cp = _perc / 3;\n } // switches the box to red when a section (h2) is 0\n\n\n if (cp === 0) {\n cl = \" \".concat(clRed);\n } // switches the box to green when a section (h2) is completed\n else if (cp === mp) {\n cl = \" \".concat(clGreen);\n } // default is blue (partially completed and starting value)\n else cl = \"\"; // needed for Game Status to show percentage properly (adds a slash for all boxes except the Game Status one)\n\n\n if (jsObj[i].hasOwnProperty(\"percent\")) cp += \"/\";\n fillText = \"
\").concat(i === \"intro\" ? cp : cp + jsObj[i].maxPercent, \"%
\");\n }\n\n document.getElementById(h2id).innerHTML = h2 + fillText;\n }\n}\n/**\r\n * Generates and appends a new entry inside the HTML of a given ID\r\n * @param {object} divId object containing div ID and h2 title of the HTML element\r\n * @param {string} textPrefix Main name of the entry\r\n * @param {string} textSuffix Optional suffix after the main name (spoilers: locations, costs etc.)\r\n */\n\n\nfunction FillHTML(divId) {\n var textPrefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"Unknown Completion Element: \";\n var textSuffix = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"Unknown Description Element\";\n var icon = completionSymbol;\n var b = [\"\", \"\"];\n if (!textPrefix.length) b = [\"\", \"\"];\n var span = [\"\", \"\"];\n var spoilerSpan = [\"\", \"\"];\n\n if (divId === _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.hints) {\n span[0] = \"\";\n icon = \"\";\n }\n\n var dash = \"\";\n if (textSuffix.length && textPrefix.length) dash = \"— \";\n document.getElementById(divId.id).innerHTML += divStart + icon + b[0] + textPrefix + b[1] + span[0] + pSpan + spoilerSpan[0] + dash + textSuffix + spoilerSpan[1] + span[1] + divEnd;\n}\n/**\r\n * Adds HTML string to an element with a given ID.\r\n * @param {object} divId object containing div ID of the HTML element to append to\r\n * @param {string} content HTML contents to append\r\n */\n\n\nfunction AppendHTML(divId, content) {\n document.getElementById(divId.id).innerHTML += \"\\n\" + content;\n}\n/**\r\n * Switches global variable to a \"completed\" symbol. Adds +1 or +2 to percent property.\r\n */\n\n\nfunction CurrentDataTrue() {\n var divId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n completionSymbol = SYMBOL_TRUE;\n\n if (divId) {\n divId.percent++;\n if (divId.id === \"hk-equipment\") divId.percent++; // double % for equipment\n }\n}\n/**\r\n * Switches global variable to a \"not completed\" symbol\r\n */\n\n\nfunction CurrentDataFalse() {\n completionSymbol = SYMBOL_FALSE;\n}\n/**\r\n * Switches global variable to an \"information\" symbol\r\n */\n\n/* function CurrentDataInfo() {\r\n completionSymbol = SYMBOL_INFO;\r\n} */\n\n/**\r\n * Switches global variable to no symbol (span with left padding)\r\n */\n\n\nfunction CurrentDataBlank() {\n completionSymbol = SYMBOL_EMPTY;\n}\n/**\r\n * Fills HTML with the playTime value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} playTime Number of total gameplay time in seconds\r\n */\n\n\nfunction CheckPlayTime(divId, playTime) {\n var icon = \"\";\n var seconds = Math.floor(playTime);\n var minutes = Math.floor(seconds / 60 % 60);\n var hours = Math.floor(seconds / 3600);\n var sec = Math.floor(seconds % 60);\n if (sec < 10) sec = \"0\" + sec;\n if (minutes < 10) minutes = \"0\" + minutes;\n var textFill = \"Time Played:\" + pSpan + \"\" + hours + \" h \" + minutes + \" min \" + sec + \" sec\";\n document.getElementById(divId.id).innerHTML += divStart + icon + textFill + divEnd;\n}\n/**\r\n * Searches for completionPercentage in playerData and fills HTML with the value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} completionPercentage Number of completion percentage\r\n */\n\n\nfunction CheckCompletionPercent(divId, completionPercentage) {\n completionPercentage >= 112 ? CurrentDataTrue() : CurrentDataFalse();\n var textFill = \"Game Completion:\" + pSpan + \"\" + completionPercentage + \" %\" + pSpan + \"(out of \" + divId.maxPercent + \" %)\";\n document.getElementById(divId.id).innerHTML += divStart + completionSymbol + textFill + divEnd;\n}\n/**\r\n * Reads the \"version\" string from the save file and appends it to the selected div ID element\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {string} saveVersion Save File version in format 0.0.0.0\r\n */\n\n\nfunction CheckSaveFileVersion(divId) {\n var saveVersion = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID.intro.saveVersion;\n CurrentDataBlank();\n var textFill = \"Save Version:\".concat(pSpan, \"\").concat(saveVersion, \"\").concat(pSpan);\n document.getElementById(divId.id).innerHTML += divStart + completionSymbol + textFill + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of health mask images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} masks Number of max health masks from the save (baseline without charms and lifeblood)\r\n * @param {number} permadeathMode Value of permadeathMode property. 0 = Normal, 1 = Steel Soul, 2 = Steel Soul broken save\r\n */\n\n\nfunction CheckHealthMasks(divId) {\n var masks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;\n var permadeathMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Health:\";\n var maskImages = \"\";\n var maskNormal = \"health mask image\");\n var maskSteel = \"steel health mask image\");\n var maskImg = \"\";\n permadeathMode > 0 ? maskImg = maskSteel : maskImg = maskNormal;\n\n for (var i = 0; i < masks; i++) {\n maskImages += maskImg;\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + maskImages + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of soul orbs images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} totalSoul Number of max Soul reserve from the save. 99 = full Soul Orb\r\n */\n\n\nfunction CheckSoulOrbs(divId, totalSoul) {\n var icon = SYMBOL_EMPTY;\n var textFill = \"Soul:\";\n var soulImages = \"\";\n var soulNormal = \"soul orb image\");\n var soulImg = soulNormal;\n\n for (var i = 0, total = totalSoul / 33; i < total; i++) {\n soulImages += soulImg;\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + soulImages + divEnd;\n}\n/**\r\n * Fills HTML with the Geo value of the save file\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} geoValue Number of total Geo value\r\n */\n\n\nfunction CheckGeo(divId) {\n var geoValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var geoPoolValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Geo:geo symbol image\").concat(geoValue, \"\"); // Show Shade Geo value and image only if Shade has at least 1 Geo on it\n\n if (geoPoolValue > 0) textFill += \"\\n \".concat(pSpan, \"+shade geo symbol image\").concat(geoPoolValue, \"\"); // Show also total Geo (Geo + Shade Geo) if player has at least 1 geo alongside the shade geo\n\n if (geoValue > 0 && geoPoolValue > 0) textFill += \"\".concat(pSpan, \"=\").concat(pSpan, \"\").concat(geoValue + geoPoolValue, \"\");\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + divEnd;\n}\n/**\r\n * Fills HTML with appropriate number of notch images\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {number} totalNotches Number of total Charm Notches the player has. 11 = max\r\n * @param {number} filledNotches Number of total used Charm Notches (including overcharmed notches). 15 = max\r\n */\n\n\nfunction CheckNotches(divId) {\n var totalNotches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;\n var filledNotches = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n var _ = 0,\n overcharmedNotches = _.overcharmedNotches,\n unusedNotches = _.unusedNotches; // How many overcharmed notches images to show\n\n overcharmedNotches = filledNotches - totalNotches;\n if (overcharmedNotches < 1) overcharmedNotches = 0; // How many unused notches images to show\n\n unusedNotches = totalNotches - filledNotches;\n if (unusedNotches < 1) unusedNotches = 0; // Correct number of filled/used notches images to show when player is overcharmed\n\n if (filledNotches > totalNotches) filledNotches = totalNotches;\n var icon = SYMBOL_EMPTY;\n var textFill = \"Notches:\".concat(pSpan);\n var notchImages = \"\";\n var notchNormalImage = \"notch image\");\n var notchFilledImage = \"notch image\");\n var notchOvercharmedImage = \"notch image\"); // First check filled (used) notches and fill them (skips if no filled notches)\n\n if (filledNotches > 0) {\n for (var i = 0; i < filledNotches; i++) {\n notchImages += notchFilledImage;\n }\n } // Second check overcharmed notches and fill them (skips if player is not overcharmed)\n\n\n if (overcharmedNotches > 0) {\n for (var _i = 0; _i < overcharmedNotches; _i++) {\n notchImages += notchOvercharmedImage;\n }\n } // Lastly, fill all unused notches\n\n\n if (unusedNotches > 0) {\n for (var _i2 = 0; _i2 < unusedNotches; _i2++) {\n notchImages += notchNormalImage;\n }\n }\n\n document.getElementById(divId.id).innerHTML += divStartCenter + icon + textFill + notchImages + divEnd;\n}\n/**\r\n * Verifies if the data in a specific object is true or false, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified (use copy - data inside this object will be deleted)\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckIfDataTrue(divId, dataObject, playerData) {\n var _ref = \"\",\n textPrefix = _ref.textPrefix,\n textSuffix = _ref.textSuffix;\n\n for (var i in dataObject) {\n textPrefix = dataObject[i].name;\n textSuffix = dataObject[i].spoiler;\n\n switch (i) {\n case \"gotCharm_36\":\n // prevents green checkbox and adding 1% when only got one white fragment\n playerData.gotQueenFragment === true && playerData.gotKingFragment === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n\n case \"gotCharm_37\":\n case \"gotCharm_38\":\n case \"gotCharm_39\":\n case \"gotCharm_40\":\n case \"killedGrimm\":\n case \"grimmChildLevel\":\n case \"killedHiveKnight\":\n case \"hasGodfinder\":\n // fades out the entries if save file is from older game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n if (i === \"grimmChildLevel\") {\n playerData.grimmChildLevel >= 4 ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n break;\n\n default:\n playerData[i] === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n }\n\n FillHTML(divId, textPrefix, textSuffix);\n }\n}\n/**\r\n * Verifies if the data in a specific object is 0 or > 0, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified (use copy - data inside this object will be deleted)\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckSpellLevel(divId, dataObject, playerData) {\n for (var i in dataObject) {\n switch (i) {\n case \"vengefulSpirit\":\n case \"shadeSoul\":\n playerData.fireballLevel >= dataObject[i].fireballLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n case \"desolateDive\":\n case \"descendingDark\":\n playerData.quakeLevel >= dataObject[i].quakeLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n case \"howlingWraiths\":\n case \"abyssShriek\":\n playerData.screamLevel >= dataObject[i].screamLevel ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n break;\n\n default:\n break;\n }\n }\n}\n/**\r\n * Verifies if the data in a specific object is 0 or > 0, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckWarriorDreams(divId, dataObject, playerData) {\n for (var i in dataObject) {\n playerData[i] >= 2 ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[i].name, dataObject[i].spoiler);\n }\n}\n/**\r\n * Verifies if the Godmaster Pantheons 1-4 are completed by the player, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing pantheon data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search in the save file\r\n */\n\n\nfunction CheckGodmasterDoors(divId, dataObject, playerData) {\n // appends \"pantheon\" to every array element\n // same as names in the database object\n var pantheon = [\"Master\", \"Artist\", \"Sage\", \"Knight\"].map(function (element) {\n return \"pantheon\" + element;\n });\n\n for (var i = 0; i < 4; i++) {\n // compatibility with earlier game versions\n if (playerData.hasOwnProperty(\"bossDoorStateTier\" + (i + 1)) === false) {\n CurrentDataBlank();\n FillHTML(divId, \"\".concat(dataObject[pantheon[i]].name, \"\"), \"\".concat(dataObject[pantheon[i]].spoiler, \"\"));\n } else {\n playerData[\"bossDoorStateTier\" + (i + 1)].completed === true ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[pantheon[i]].name, dataObject[pantheon[i]].spoiler);\n }\n }\n}\n/**\r\n * Verifies the level of player's nail upgrades, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing nail upgrades data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search in the save file\r\n */\n\n\nfunction CheckNailUpgrades(divId, dataObject, playerData) {\n // appends \"Nail\" to every array element\n // same as names in the database object\n var nail = [\"old\", \"sharpened\", \"channeled\", \"coiled\", \"pure\"].map(function (element) {\n return element + \"Nail\";\n });\n\n for (var i = 0; i < 5; i++) {\n playerData.nailSmithUpgrades >= i ? CurrentDataTrue(divId) : CurrentDataFalse();\n FillHTML(divId, dataObject[nail[i]].name, dataObject[nail[i]].spoiler);\n }\n\n if (divId.percent) divId.percent--; // subject one for the Old Nail\n}\n/**\r\n * Verifies if the data in a specific object are true or false, and appends HTML accordingly. Creates a copy of dataObject.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {string} idText Text string inside save data to search for\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} worldData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckWorldDataTrue(divId, idText, dataObject, worldData) {\n var orderedArray = [];\n var size = (0,_hk_functions_js__WEBPACK_IMPORTED_MODULE_2__.ObjectLength)(dataObject); // Order the items before displaying them (creates a copy of dataObject)\n\n for (var i in dataObject) {\n orderedArray.push([i, dataObject[i].name, dataObject[i].spoiler, false]);\n } // Search for completed items and mark them for display\n\n\n for (var _i3 = 0, length = worldData.length; _i3 < length; _i3++) {\n for (var j = 0; j < size; j++) {\n if (worldData[_i3].id === idText && worldData[_i3].sceneName === orderedArray[j][0] && worldData[_i3].activated === true) {\n orderedArray[j][3] = true;\n }\n }\n } // Display the items as they were initially ordered\n\n\n for (var _i4 = 0; _i4 < size; _i4++) {\n CurrentDataFalse();\n if (orderedArray[_i4][3] === true) CurrentDataTrue(divId);\n FillHTML(divId, orderedArray[_i4][1], orderedArray[_i4][2]);\n }\n}\n/**\r\n * Verifies if the data in a specific object are true or false, or checks what values they have, and appends HTML accordingly.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject Object containing data to be verified\r\n * @param {object} playerData Reference/pointer to specific data where to search\r\n * @param {object} worldData Reference/pointer to specific data where to search\r\n */\n\n\nfunction CheckAdditionalThings(divId, dataObject, playerData, worldData, sceneData) {\n var textPrefix = \"\";\n var textSuffix = \"\"; // Start main loop\n\n for (var i in dataObject) {\n textPrefix = dataObject[i].name;\n dataObject[i].hasOwnProperty(\"spoiler\") ? textSuffix = dataObject[i].spoiler : textSuffix = \"\";\n var _2 = 0,\n amount = _2.amount,\n countTotal = _2.countTotal,\n total = _2.total,\n unbroken = _2.unbroken,\n broken = _2.broken,\n discoveredTotal = _2.discoveredTotal;\n\n switch (i) {\n case \"areaMaps\":\n case \"grubsCollected\":\n case \"dreamOrbs\":\n case \"fountainGeo\":\n case \"nailDamage\":\n case \"stationsOpened\":\n case \"charmSlots\":\n case \"whisperingRoots\":\n case \"journalEntriesCompleted\":\n case \"journalNotesCompleted\":\n case \"whiteDefenderDefeats\":\n case \"greyPrinceDefeats\":\n if (i === \"areaMaps\") {\n amount = CountMaps(dataObject[i].list);\n } else if (i === \"whisperingRoots\") {\n amount = CountWorldItem(\"Dream Plant\");\n } else {\n amount = playerData[i];\n }\n\n if (i === \"stationsOpened\") {\n if (playerData.openedHiddenStation === true) amount++;\n }\n\n countTotal = amount;\n\n if (i === \"journalEntriesCompleted\" || i === \"journalNotesCompleted\") {\n countTotal = amount + \" / \" + playerData.journalEntriesTotal;\n }\n\n if (i === \"grubsCollected\") LogMissingGrubs();\n textPrefix += \": \" + countTotal;\n\n if (i === \"greyPrinceDefeats\") {\n // backwards compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(dataObject[i].name, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n } else if (playerData.zoteDead === true || playerData.zoteRescuedBuzzer === false && playerData.hasWalljump === true) {\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n }\n }\n\n if (i === \"whiteDefenderDefeats\") {\n // backwards compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(dataObject[i].name, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n }\n\n amount >= dataObject[i].max ? CurrentDataTrue() : CurrentDataBlank();\n break;\n\n case \"geoPool\":\n case \"rancidEggs\":\n case \"jinnEggsSold\":\n case \"xunFlowerBrokeTimes\":\n textPrefix += \": \" + Math.abs(playerData[i]);\n i === \"geoPool\" && playerData[i] > 0 ? CurrentDataBlank() : CurrentDataTrue();\n\n if (i === \"jinnEggsSold\") {\n // fade out if not on Steel Soul\n if (playerData.permadeathMode < 1) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n }\n\n break;\n\n case \"geoRocks\":\n discoveredTotal = sceneData.geoRocks.length;\n unbroken = CountGeoRocks(discoveredTotal, \"unbroken\");\n broken = CountGeoRocks(discoveredTotal, \"broken\");\n textPrefix += \": \".concat(unbroken, \" | \").concat(broken, \" | \").concat(discoveredTotal);\n CurrentDataTrue();\n break;\n\n case \"shopkeeperKey\":\n playerData.hasSlykey === true || playerData.gaveSlykey === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"elegantKey\":\n playerData.hasWhiteKey === true || playerData.usedWhiteKey === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"loveKey\":\n playerData.hasLoveKey === true || playerData.openedLoveDoor === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"simpleKeyCityOfTears\":\n // #2\n FindWorldItem(\"Ruins1_17\", \"Shiny Item\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"simpleKeyAncientBasin\":\n // #3\n FindWorldItem(\"Abyss_20\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"gotLurkerKey\":\n case \"nightmareLanternLit\":\n case \"killedPaleLurker\":\n case \"whiteDefenderDefeated\":\n case \"gotGrimmNotch\":\n case \"fragileGreed_unbreakable\":\n case \"fragileHealth_unbreakable\":\n case \"fragileStrength_unbreakable\":\n case \"killedBindingSeal\":\n case \"killedGodseekerMask\":\n case \"givenGodseekerFlower\":\n case \"givenOroFlower\":\n case \"givenWhiteLadyFlower\":\n case \"givenEmilitiaFlower\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreAncientBasin\":\n // #1\n FindWorldItem(\"Abyss_17\", \"Battle Scene Ore\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreSeer\":\n // #2\n playerData.dreamReward2 === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreCrystalPeak\":\n // #3\n FindWorldItem(\"Mines_34\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreDeepnest\":\n // #4\n FindWorldItem(\"Deepnest_32\", \"Shiny Item Stand\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreGrubfather\":\n // #5\n FindWorldItem(\"Crossroads_38\", \"Shiny Item Ore\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"paleOreColosseum\":\n // #6\n FindWorldItem(\"Room_Colosseum_Silver\", \"Shiny Item\") ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"relicsWandererJournal\":\n case \"relicsHallownestSeal\":\n case \"relicsKingsIdol\":\n case \"relicsArcaneEgg\":\n total = playerData[dataObject[i].nameHeld] + playerData[dataObject[i].nameSold];\n total >= dataObject[i].max ? CurrentDataTrue() : CurrentDataBlank();\n textPrefix += \": \" + total;\n break;\n\n case \"bossDoorStateTier5\":\n if (playerData.hasOwnProperty(\"bossDoorStateTier5\") === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n } else {\n playerData[i].completed === true ? CurrentDataTrue() : CurrentDataFalse();\n }\n\n break;\n\n case \"killsBindingSeal\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] == 0 ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"killedVoidIdol_1\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n if (playerData[i] === false && (playerData.killedVoidIdol_2 === true || playerData.killedVoidIdol_3 === true)) CurrentDataTrue();\n break;\n\n case \"killedVoidIdol_2\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n if (playerData[i] === false && playerData.killedVoidIdol_3 === true) CurrentDataTrue();\n break;\n\n case \"killedVoidIdol_3\":\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n break;\n\n case \"greyPrinceDefeated\":\n // compatibility with earlier game versions\n if (playerData.hasOwnProperty(i) === false) {\n CurrentDataBlank();\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n break;\n } else if (playerData.zoteDead === true || playerData.zoteRescuedBuzzer === false && playerData.hasWalljump === true) {\n textPrefix = \"\".concat(textPrefix, \"\");\n textSuffix = \"\".concat(textSuffix, \"\");\n }\n\n playerData[i] === true ? CurrentDataTrue() : CurrentDataBlank();\n if (playerData.zoteRescuedBuzzer === true && playerData[i] === false) CurrentDataFalse();\n break;\n\n case \"zoteStatus\":\n CurrentDataFalse();\n\n if (playerData.zoteDead === true) {\n textPrefix = dataObject[i].nameNeglect;\n textSuffix = dataObject[i].spoilerNeglect;\n CurrentDataTrue();\n } else if (playerData.killedZote === true) {\n textPrefix = dataObject[i].nameRivalry;\n textSuffix = dataObject[i].spoilerRivalry;\n CurrentDataTrue();\n } else if (playerData.zoteRescuedBuzzer === false) {\n if (playerData.hasWalljump === false) {\n textPrefix = dataObject[i].nameTrappedVengefly;\n textSuffix = dataObject[i].spoilerTrappedVengefly;\n } else if (playerData.hasWalljump === true) {\n textPrefix = dataObject[i].nameNotRescuedVengefly;\n textSuffix = dataObject[i].spoilerNotRescuedVengefly;\n }\n } else if (playerData.zoteRescuedBuzzer === true) {\n if (playerData.zoteRescuedDeepnest === false) {\n textPrefix = dataObject[i].nameTrappedDeepnest;\n textSuffix = dataObject[i].spoilerTrappedDeepnest;\n } else if (playerData.zoteRescuedDeepnest === true) {\n if (playerData.killedZote === false) {\n textPrefix = dataObject[i].nameColosseum;\n textSuffix = dataObject[i].spoilerColosseum;\n }\n }\n }\n\n break;\n\n case \"nailsmithStatus\":\n CurrentDataFalse();\n\n if (playerData.nailsmithKilled === true) {\n textPrefix = dataObject[i].namePurity;\n textSuffix = dataObject[i].spoilerPurity;\n CurrentDataTrue();\n } else if (playerData.nailsmithConvoArt === true) {\n textPrefix = dataObject[i].nameHappyCouple;\n textSuffix = dataObject[i].spoilerHappyCouple;\n CurrentDataTrue();\n } else if (playerData.nailsmithSpared === true) {\n textPrefix = dataObject[i].nameSheoHutWaiting;\n textSuffix = dataObject[i].spoilerSheoHutWaiting;\n } else {\n textPrefix = dataObject[i].nameUpgradeNail;\n textSuffix = dataObject[i].spoilerUpgradeNail;\n }\n\n break;\n\n case \"mrMushroomState\":\n CheckMrMushroomState(divId, dataObject[i], playerData[i]);\n break;\n\n default:\n playerData[i] === true ? CurrentDataTrue() : CurrentDataFalse();\n } // end switch (i)\n\n\n if (i === \"mrMushroomState\") continue;\n FillHTML(divId, textPrefix, textSuffix);\n } // end for (let i in dataObject)\n // ==========================================\n // -------------- Methods ---------------- //\n\n /**\r\n * Searches for a given item in the in-game area and returns true when found and collected.\r\n * @param {string} itemArea Code of the in-game area on the map\r\n * @param {string} itemId Name of the item\r\n * @returns {boolean}\r\n */\n\n\n function FindWorldItem() {\n var itemArea = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var itemId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"Shiny Item\";\n\n for (var _i5 = 0, length = worldData.length; _i5 < length; _i5++) {\n if (worldData[_i5].id === itemId) {\n if (worldData[_i5].sceneName === itemArea) {\n if (worldData[_i5].activated === true) return true;\n }\n }\n }\n\n return false;\n }\n /**\r\n * Searches for a given item that the player has found and returns the amount of them that the player completed.\r\n * @param {string} itemId Name of the item\r\n * @returns {number}\r\n */\n\n\n function CountWorldItem() {\n var itemId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n var total = 0;\n\n for (var _i6 = 0, length = worldData.length; _i6 < length; _i6++) {\n if (worldData[_i6].id === itemId) {\n if (worldData[_i6].activated === true) total++;\n }\n }\n\n return total;\n }\n /**\r\n * Counts the number of maps the player has acquired (from the list in an array)\r\n * @param {array} mapArray Array of strings with area map names\r\n * @returns {number}\r\n */\n\n\n function CountMaps(mapArray) {\n var totalMaps = 0;\n\n for (var _i7 = 0, len = mapArray.length; _i7 < len; _i7++) {\n if (playerData[mapArray[_i7]] === true) totalMaps++;\n }\n\n return totalMaps;\n }\n /**\r\n * Counts the total amount of Geo Rocks Unbroken or Broken. Logs to console all the Unbroken IDs and Map locations.\r\n * @param {number} arrayLength How many items the Geo Rocks array is currently storing (for iteration)\r\n * @param {string} mode Choose which Geo Rocks to count (broken or unbroken)\r\n */\n\n\n function CountGeoRocks(arrayLength) {\n var mode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"unbroken\";\n var countTotal = 0;\n var geoRocksLog = [];\n\n if (mode === \"unbroken\") {\n for (var _i8 = 0; _i8 < arrayLength; _i8++) {\n if (sceneData.geoRocks[_i8].hitsLeft > 0) {\n countTotal++;\n geoRocksLog.push(\"#\".concat(countTotal, \" \\uD83C\\uDFD4\\uFE0F \").concat(sceneData.geoRocks[_i8].id, \" \\uD83D\\uDDFA\\uFE0F \").concat((0,_hk_functions_js__WEBPACK_IMPORTED_MODULE_2__.TranslateMapName)(sceneData.geoRocks[_i8].sceneName), \" \\u2328\\uFE0F \").concat(sceneData.geoRocks[_i8].sceneName));\n }\n }\n\n if (!countTotal) {\n console.log(\"%cAll Geo Rocks Broken!\", \"color: #16c60c; font-weight: 700;\");\n } else {\n console.groupCollapsed(\"%cUnbroken Geo Rocks (\".concat(countTotal, \"):\"), \"color: #16c60c; font-weight: 700;\");\n\n for (var _i9 = 0, length = geoRocksLog.length; _i9 < length; _i9++) {\n console.log(geoRocksLog[_i9]);\n }\n\n console.groupEnd();\n }\n } else {\n for (var _i10 = 0; _i10 < arrayLength; _i10++) {\n if (sceneData.geoRocks[_i10].hitsLeft === 0) countTotal++;\n }\n }\n\n return countTotal;\n }\n /**\r\n * Compares and logs all unrescued Grubs in a list: IDs and map locations\r\n */\n\n\n function LogMissingGrubs() {\n var rescuedGrubsSceneList = [];\n\n for (var _i11 = 0, _length = worldData.length; _i11 < _length; _i11++) {\n if (worldData[_i11].id.includes(\"Grub Bottle\")) {\n if (worldData[_i11].activated === true) {\n // There are 3 duplicates of the same map scene name from older game save files. Prevents adding duplicates\n\n /* if (worldData[i].sceneName === \"Ruins2_11\" && worldData[i].id === \"Grub Bottle (1)\") {\r\n continue;\r\n } else if (worldData[i].sceneName === \"Ruins2_11\" && worldData[i].id === \"Grub Bottle (2)\") {\r\n continue;\r\n } else { */\n rescuedGrubsSceneList.push(worldData[_i11].sceneName); // }\n }\n }\n } // Filtering the reference database Grub list to include only the missing values\n\n\n var missingGrubsList = _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRUBS_LIST.filter(function (x) {\n return !rescuedGrubsSceneList.includes(x);\n });\n var length = missingGrubsList.length;\n\n if (!length) {\n console.log(\"%cAll Grubs Rescued!\", \"color: #16c60c; font-weight: 700;\");\n } else {\n console.groupCollapsed(\"%cUnrescued Grubs (\".concat(length, \"):\"), \"color: #16c60c; font-weight: 700;\");\n\n for (var _i12 = 0; _i12 < length; _i12++) {\n console.log(\"#\".concat(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRUBS_LIST.indexOf(missingGrubsList[_i12]) + 1, \" \\uD83D\\uDDFA\\uFE0F \").concat((0,_hk_functions_js__WEBPACK_IMPORTED_MODULE_2__.TranslateMapName)(missingGrubsList[_i12]), \" \\u2328\\uFE0F \").concat(missingGrubsList[_i12]));\n }\n\n console.groupEnd();\n }\n\n return false;\n }\n}\n/**\r\n * Checks and fills all the 7 locations of Mr Mushroom.\r\n * @param {object} divId ID of the HTML element for data appending\r\n * @param {object} dataObject object containing the Mr Mushroom name and spoilers/locations\r\n * @param {number} mrMushroomState playerData.mrMushroomState read from the save file. (0-8)\r\n */\n\n\nfunction CheckMrMushroomState(divId, dataObject) {\n var mrMushroomState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n\n if (mrMushroomState > 1) {\n for (var i = 1; i <= 7; i++) {\n mrMushroomState > i ? CurrentDataTrue() : CurrentDataFalse();\n FillHTML(divId, \"\".concat(dataObject.name, \" #\").concat(i), dataObject[\"spoiler\" + i]);\n }\n } else {\n CurrentDataFalse();\n\n for (var _i13 = 1; _i13 <= 7; _i13++) {\n FillHTML(divId, \"\".concat(dataObject.name, \" #\").concat(_i13), dataObject[\"spoiler\" + _i13]);\n }\n }\n}\n/**\r\n * Checks, validates and shows hints to the player depending on their save progression, in chronological order. Shows only hint for the last uncompleted event. If Hollow Knight is defeated, shows a dummy text.\r\n * @param {object} divId object containing div hints ID and h2 title\r\n * @param {object} dataObject object containing all hints data\r\n * @param {object} playerData object containing HK Player Data to look in\r\n * @param {object} worldData object containing HK World Data to look in\r\n * @returns {bool} true when defeated Hollow Knight, false if not\r\n */\n\n\nfunction CheckHintsTrue(divId, dataObject, playerData, worldData) {\n if (playerData.killedHollowKnight === true) {\n // a text to show when player already finished their first playthrough (killed Hollow Knight first time)\n FillHTML(divId, \"\", \"...a successful Knight who doesn't need hints anymore. The Knight explores the world of Hallownest patiently in constant search of its remaining secrets...\");\n return true;\n }\n\n for (var i in dataObject) {\n if (playerData[i] === true) {\n continue;\n } else if (i === \"fireballLevel\") {\n if (playerData[i] >= 1) {\n continue;\n } else {\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"Crossroads_04\") {\n var GruzMotherDefeated = false;\n\n for (var k = 0, length = worldData.length; k < length; k++) {\n if (worldData[k].id === \"Battle Scene\" && worldData[k].sceneName === \"Crossroads_04\" && worldData[k].activated === true) {\n GruzMotherDefeated = true;\n break;\n }\n }\n\n if (GruzMotherDefeated) {\n continue; // next dataObject (i)\n } else {\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"dungDefenderOrHornet2\") {\n if (playerData.defeatedDungDefender === true) {\n continue;\n } else if (playerData.hornetOutskirtsDefeated === true) {\n continue;\n } else {\n // if no Dung Defender or Hornet 2\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else if (i === \"ismaTearOrShadeCloak\") {\n if (playerData.hasAcidArmour === true) {\n continue;\n } else if (playerData.hasKingsBrand === true) {\n if (playerData.hasShadowDash === true) {\n continue;\n } else {\n // if Kings Brand but no Shade Cloak\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else {\n // if no Isma's Tear or Kings Brand\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } else {\n // if anything from the hints list is not done\n FillHTML(divId, \"\", dataObject[i].spoiler);\n return false;\n }\n } // end: for (let i in dataObject)\n\n} // function CheckHintsTrue()\n\n/**\r\n * Pre-Cleans HTML. Reads contents inside text area and parses it to a JavaScript object. If not empty, runs HKCheckCompletion() to check data.\r\n */\n\n\nfunction HKReadTextArea() {\n var textAreaId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"\";\n // refresh and prepare document for filling with data from the save\n InitialHTMLPopulate(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID);\n var contents = document.getElementById(textAreaId).value;\n\n if (contents.length) {\n try {\n var jsonObject = JSON.parse(contents); // console.log(jsonObject);\n\n if (jsonObject.hasOwnProperty(\"playerData\")) HKCheckCompletion(jsonObject); // console.log(jsonObject);\n } catch (error) {\n alert(\"This seems like not a valid Hollow Knight save. \".concat(error));\n console.info(\"This seems like not a valid Hollow Knight save. \".concat(error));\n }\n }\n}\n/**\r\n * Populate all HTML with given ID and their initial data set as false (used at DOM load)\r\n * @param {object} divIdObj JavaScript Object containing all HTML IDs to populate\r\n */\n\n\nfunction InitialHTMLPopulate(divIdObj) {\n CurrentDataFalse();\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.PrefillHTML)(divIdObj); // Play Time\n\n CheckPlayTime(divIdObj.intro, 0); // Game Completion\n\n CheckCompletionPercent(divIdObj.intro, 0); // Save File Version\n\n CheckSaveFileVersion(divIdObj.intro); // Fleur Divide\n\n AppendHTML(divIdObj.intro, FLEUR_DIVIDE); // Health Masks\n\n CheckHealthMasks(divIdObj.intro); // Soul Orbs\n\n CheckSoulOrbs(divIdObj.intro, 99); // Charm Notches\n\n CheckNotches(divIdObj.intro); // Geo\n\n CheckGeo(divIdObj.intro); // Keep symbol False\n\n CurrentDataFalse(); // First Hint Only\n\n FillHTML(divIdObj.hints, \"\", _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.HINTS.fireballLevel.spoiler); // Temp arrays storing references (addresses) to objects for looping through them (duplicates important)\n\n var hkObjArray = [_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.BOSSES_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.CHARMS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.EQUIPMENT, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILARTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.MASKSHARDS_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.VESSELFRAGMENTS_WORLD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMERS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.COLOSSEUM, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DREAMNAIL, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.WARRIORDREAMS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GRIMMTROUPE, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.LIFEBLOOD, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ESSENTIAL, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.STATISTICS]; // duplicates and order important - must be the same as in hkObjArray[]\n\n var divObjArray = [divIdObj.bosses, divIdObj.bosses, divIdObj.charms, divIdObj.equipment, divIdObj.nailArts, divIdObj.maskShards, divIdObj.maskShards, divIdObj.vesselFragments, divIdObj.vesselFragments, divIdObj.dreamers, divIdObj.colosseum, divIdObj.dreamNail, divIdObj.warriorDreams, divIdObj.grimmTroupe, divIdObj.lifeblood, divIdObj.godmaster, divIdObj.essential, divIdObj.achievements, divIdObj.statistics]; // Looped filling to reduce redundancy\n\n do {\n for (var entry in hkObjArray[0]) {\n if (entry === \"mrMushroomState\") continue;\n FillHTML(divObjArray[0], hkObjArray[0][entry].name, hkObjArray[0][entry].spoiler);\n }\n\n divObjArray.shift();\n } while (hkObjArray.shift()); // Nail Upgrades Misc\n\n\n for (var i in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES) {\n FillHTML(divIdObj.nailUpgrades, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES[i].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.NAILUPGRADES[i].spoiler);\n } // Spells Misc\n\n\n for (var _i14 in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS) {\n FillHTML(divIdObj.spells, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS[_i14].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.SPELLS[_i14].spoiler);\n } // Godmaster Doors Misc\n\n\n for (var _i15 in _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS) {\n FillHTML(divIdObj.godmaster, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS[_i15].name, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.GODMASTER_DOORS[_i15].spoiler);\n } // Mr Mushroom 1 - 7\n\n\n CheckMrMushroomState(divIdObj.achievements, _hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.ACHIEVEMENTS.mrMushroomState); // Fleur Dividers\n\n AppendHTML(divIdObj.godmaster, FLEUR_DIVIDE);\n AppendHTML(divIdObj.essential, FLEUR_DIVIDE);\n AppendHTML(divIdObj.achievements, FLEUR_DIVIDE); // Check local storage first to set proper checkbox state before the below functions start (default is always unchecked)\n\n if ((0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.StorageAvailable)('localStorage')) {\n if (localStorage.getItem(\"hkCheckboxHints\") === \"checked\") document.getElementById(\"checkbox-hints\").checked = true;\n if (localStorage.getItem(\"hkCheckboxSpoilers\") === \"checked\") document.getElementById(\"checkbox-spoilers\").checked = true;\n } // if (localStorage.getItem(\"hkCheckboxHints\") === \"checked\") document.getElementById(\"checkbox-hints\").checked = true;\n // if (localStorage.getItem(\"hkCheckboxSpoilers\") === \"checked\") document.getElementById(\"checkbox-spoilers\").checked = true;\n // Prevents wrong checkbox behaviour (must run after everything is finished)\n\n\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.CheckboxHintsToggle)();\n (0,_page_functions_js__WEBPACK_IMPORTED_MODULE_1__.CheckboxSpoilersToggle)();\n}\n/**\r\n * Zero-fill all \"percent\" properties in the JSON Object (reset to default)\r\n * @param {object} jsObj object containing the \"percent\" properties to be reset to 0\r\n */\n\n\nfunction ResetCompletion(jsObj) {\n for (var i in jsObj) {\n if (jsObj[i].hasOwnProperty(\"percent\")) jsObj[i].percent = 0;\n }\n}\n/**\r\n * Focuses, selects and copies to clipboard contents inside a clicked element. Includes optional tooltip update after the copying is done.\r\n * @param {MouseEvent} mouseEvent from the clicked element (AddEventListener)\r\n * @param {string} tooltipId Element ID of the tooltip to update\r\n * @param {string} tooltipFill Updated contents of the tooltip\r\n */\n\n\nfunction SelectCopyInputText(mouseEvent) {\n var tooltipId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n var tooltipFill = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"\";\n var element = document.getElementById(mouseEvent.target.id); // this prevents the un-selected effect after clicking the second time (clears all selection first)\n\n if (window.getSelection) {\n window.getSelection().removeAllRanges();\n }\n\n element.focus(); // best to focus the element first before selecting\n\n element.select();\n element.setSelectionRange(0, 99999); // for mobile devices\n // Copy the text inside the text field to clipboard\n\n document.execCommand(\"copy\"); // optional tooltip showing\n\n if (tooltipFill.length && tooltipId.length) FillInnerHTML(tooltipId, tooltipFill);\n}\n/**\r\n * Fills the innerHTML of a given HTML Element with provided contents\r\n * @param {string} elementId Element ID to update\r\n * @param {string} textFill Updated contents (innerHTML)\r\n */\n\n\nfunction FillInnerHTML(elementId, textFill) {\n var element = document.getElementById(elementId);\n element.innerHTML = textFill;\n}\n/* ----------------------- Event Listeners -------------------------- */\n// Populate HTML at load (before img and css)\n\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n InitialHTMLPopulate(_hk_database_js__WEBPACK_IMPORTED_MODULE_0__.default.DIV_ID);\n}); // Does an action when the save file location input text is clicked once (auto select & copy to clipboard)\n\ndocument.getElementById(\"save-location-input\").addEventListener(\"click\", function (e) {\n SelectCopyInputText(e, \"save-location-input-tooltip\", \"Copied save file location to clipboard\");\n}, false); // Choose File input field\n\ndocument.getElementById(\"save-location-input\").addEventListener(\"mouseout\", function () {\n FillInnerHTML(\"save-location-input-tooltip\", \"Click once to copy to clipboard\");\n}, false); // Analyze Text button\n\ndocument.getElementById(\"save-area-read\").addEventListener(\"click\", function () {\n HKReadTextArea(\"save-area\");\n}, false);\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/HKCheckCompletion.js?"); /***/ }), @@ -71,7 +71,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ObjectLength\": () => /* binding */ ObjectLength\n/* harmony export */ });\n/**\r\n * Checks the length of a JavaScript Object like Array.length\r\n * @param {object} object JavaScript Object\r\n * @return {number} length of the Object\r\n */\nfunction ObjectLength(object) {\n var length = 0;\n\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n ++length;\n }\n }\n\n return length;\n}\n/* ------------------------- Exports ------------------------------- */\n\n\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/hk-functions.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ObjectLength\": () => /* binding */ ObjectLength,\n/* harmony export */ \"TranslateMapName\": () => /* binding */ TranslateMapName\n/* harmony export */ });\n/* harmony import */ var _hk_dictionary_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hk-dictionary.js */ \"./src/js/hk-dictionary.js\");\n/* ---------------- Load main Hollow Knight database files ----------------- */\n\n/* -------------------------- Functions ----------------------------- */\n\n/**\r\n * Checks the length of a JavaScript Object like Array.length\r\n * @param {object} object JavaScript Object\r\n * @return {number} length of the Object\r\n */\n\nfunction ObjectLength(object) {\n var length = 0;\n\n for (var key in object) {\n if (object.hasOwnProperty(key)) {\n ++length;\n }\n }\n\n return length;\n}\n/**\r\n * Returns a translated map location name string.\r\n * @param {string} mapCode Code of the Hollow Knight map location the game developers use\r\n * @param {object} dictionary Main data source for translation\r\n */\n\n\nfunction TranslateMapName(mapCode) {\n var dictionary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _hk_dictionary_js__WEBPACK_IMPORTED_MODULE_0__.default;\n var translation = mapCode;\n if (dictionary.hasOwnProperty(mapCode)) translation = dictionary[mapCode];\n return translation;\n}\n/* ------------------------- Exports ------------------------------- */\n\n\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/hk-functions.js?"); /***/ }), @@ -82,7 +82,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"CheckboxHintsToggle\": () => /* binding */ CheckboxHintsToggle,\n/* harmony export */ \"CheckboxSpoilersToggle\": () => /* binding */ CheckboxSpoilersToggle,\n/* harmony export */ \"StorageAvailable\": () => /* binding */ StorageAvailable\n/* harmony export */ });\nvar ROOT = document.documentElement;\nvar SCROLL_BUTTON = document.querySelector(\".scroll-up-button\");\n\nfunction ScrollToElement(element) {\n /* Scroll to the element top */\n element.scrollTo({\n top: 0,\n behavior: \"smooth\"\n });\n}\n\nfunction ShowElement(element) {\n element.classList.add(\"visible-block\");\n element.classList.add(\"opacity-full\");\n element.classList.remove(\"hidden\");\n}\n\nfunction HideElement(element) {\n element.classList.remove(\"visible-block\");\n element.classList.remove(\"opacity-full\");\n element.classList.add(\"hidden\");\n}\n\nfunction TogglePageScrollElement(root, element, ratio) {\n /* Maximum number of pixels that can be scrolled by the user */\n var scrollTotal = root.scrollHeight - root.clientHeight;\n\n if (root.scrollTop / scrollTotal > ratio) {\n /* Show button */\n ShowElement(element);\n } else {\n /* Hide button */\n HideElement(element);\n }\n}\n/**\r\n * Toggles display of \"hk-hints\". On click with no parameters or on demand when called with a parameter\r\n * @param {string} param \"hide\", \"show\" or none (optional)\r\n */\n\n\nfunction CheckboxHintsToggle() {\n var param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"none\";\n var checkboxId = document.getElementById(\"checkbox-hints\");\n\n switch (param) {\n case \"hide\":\n document.getElementById(\"hk-hints\").classList.add(\"hidden\");\n checkboxId.value = \"hints-off\";\n checkboxId.checked = false; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"unchecked\");\n }\n\n break;\n\n case \"show\":\n document.getElementById(\"hk-hints\").classList.remove(\"hidden\");\n checkboxId.value = \"hints-on\";\n checkboxId.checked = true; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"checked\");\n }\n\n break;\n\n default:\n // This runs when the checkbox is not checked\n if (checkboxId.checked === false) {\n document.getElementById(\"hk-hints\").classList.add(\"hidden\");\n checkboxId.value = \"hints-off\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"unchecked\");\n }\n } // This runs when the checkbox is checked\n else {\n document.getElementById(\"hk-hints\").classList.remove(\"hidden\");\n checkboxId.value = \"hints-on\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"checked\");\n }\n }\n\n }\n}\n/**\r\n * Toggles display of \".spoiler-span\" class. On click with no parameters or on demand when called with a parameter\r\n * @param {string} param \"hide\", \"show\" or none (optional)\r\n */\n\n\nfunction CheckboxSpoilersToggle() {\n var param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"none\";\n var checkboxId = document.getElementById(\"checkbox-spoilers\");\n var allClassElements = document.querySelectorAll(\".spoiler-span\");\n var length = allClassElements.length;\n\n switch (param) {\n case \"hide\":\n for (var i = 0; i < length; i++) {\n allClassElements[i].classList.add(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-off\";\n checkboxId.checked = false; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"unchecked\");\n }\n\n break;\n\n case \"show\":\n for (var _i = 0; _i < length; _i++) {\n allClassElements[_i].classList.remove(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-on\";\n checkboxId.checked = true; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"checked\");\n }\n\n break;\n\n default:\n // This runs when the checkbox is not checked\n if (checkboxId.checked === false) {\n for (var _i2 = 0; _i2 < length; _i2++) {\n allClassElements[_i2].classList.add(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-off\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"unchecked\");\n }\n\n break;\n } // This runs when the checkbox is checked\n else {\n for (var _i3 = 0; _i3 < length; _i3++) {\n allClassElements[_i3].classList.remove(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-on\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"checked\");\n }\n }\n\n }\n}\n/**\r\n * Detects whether Storage is both supported and available.\r\n * MDN WebDocs https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage\r\n * @param {Storage} type type of storage. Ex. \"localStorage\" or \"sessionStorage\"\r\n * @returns {Boolean}\r\n */\n\n\nfunction StorageAvailable(type) {\n var storage;\n\n try {\n storage = window[type];\n var x = '__storage_test__';\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return e instanceof DOMException && ( // everything except Firefox\n e.code === 22 || // Firefox\n e.code === 1014 || // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' || // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && // acknowledge QuotaExceededError only if there's something already stored\n storage && storage.length !== 0;\n }\n}\n/* ----------------------- Event Listeners -------------------------- */\n\n\ndocument.addEventListener(\"scroll\", function () {\n TogglePageScrollElement(\n /* the document element root () */\n ROOT,\n /* Which element to toggle visibility */\n SCROLL_BUTTON,\n /* How far the user has to scroll to show the element */\n 0.1);\n});\nSCROLL_BUTTON.addEventListener(\"click\", function () {\n ScrollToElement(ROOT);\n}); // Checkboxes functions\n\ndocument.getElementById(\"checkbox-hints\").addEventListener(\"click\", CheckboxHintsToggle, false);\ndocument.getElementById(\"checkbox-spoilers\").addEventListener(\"click\", CheckboxSpoilersToggle, false);\n/* ------------------------- Exports ------------------------------- */\n\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/page-functions.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"PrefillHTML\": () => /* binding */ PrefillHTML,\n/* harmony export */ \"CheckboxHintsToggle\": () => /* binding */ CheckboxHintsToggle,\n/* harmony export */ \"CheckboxSpoilersToggle\": () => /* binding */ CheckboxSpoilersToggle,\n/* harmony export */ \"StorageAvailable\": () => /* binding */ StorageAvailable\n/* harmony export */ });\nvar ROOT = document.documentElement;\nvar SCROLL_BUTTON = document.querySelector(\".scroll-up-button\");\n\nfunction ScrollToElement(element) {\n /* Scroll to the element top */\n element.scrollTo({\n top: 0,\n behavior: \"smooth\"\n });\n}\n\nfunction ShowElement(element) {\n element.classList.add(\"visible-block\");\n element.classList.add(\"opacity-full\");\n element.classList.remove(\"hidden\");\n}\n\nfunction HideElement(element) {\n element.classList.remove(\"visible-block\");\n element.classList.remove(\"opacity-full\");\n element.classList.add(\"hidden\");\n}\n\nfunction TogglePageScrollElement(root, element, ratio) {\n /* Maximum number of pixels that can be scrolled by the user */\n var scrollTotal = root.scrollHeight - root.clientHeight;\n\n if (root.scrollTop / scrollTotal > ratio) {\n /* Show button */\n ShowElement(element);\n } else {\n /* Hide button */\n HideElement(element);\n }\n}\n/**\r\n * Cleans \"generated\" and fills all HTML elements of ids from a given list. Creates only div with id, and h2 with title inside it.\r\n * @param {object} jsObj Object with HTML data to fill\r\n */\n\n\nfunction PrefillHTML(jsObj) {\n var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"generated\";\n var domElement = document.getElementById(element);\n var sFillText = \"\"; // Clean \"generated\" div\n\n domElement.innerHTML = \"\";\n var id = \"\";\n var h2 = \"\";\n var h2id = \"\";\n var mp = \"\"; // max Percent\n\n var cl = \"\"; // class\n\n for (var i in jsObj) {\n id = jsObj[i].id;\n h2 = jsObj[i].h2;\n h2id = \"h2-\" + jsObj[i].id;\n mp = \"
\".concat(i === \"intro\" ? 0 : jsObj[i].maxPercent, \"%
\");\n if (!jsObj[i].hasOwnProperty(\"maxPercent\")) mp = \"\";\n sFillText += \"\\n
\\n

\").concat(h2).concat(mp, \"

\\n
\\n \");\n /* document.getElementById(\"generated\").innerHTML += \"
\" + \"
\";\r\n document.getElementById(id).innerHTML += `

${h2}${mp}

`; */\n }\n\n domElement.innerHTML = sFillText;\n}\n/**\r\n * Toggles display of \"hk-hints\". On click with no parameters or on demand when called with a parameter\r\n * @param {string} param \"hide\", \"show\" or none (optional)\r\n */\n\n\nfunction CheckboxHintsToggle() {\n var param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"none\";\n var checkboxId = document.getElementById(\"checkbox-hints\");\n\n switch (param) {\n case \"hide\":\n document.getElementById(\"hk-hints\").classList.add(\"hidden\");\n checkboxId.value = \"hints-off\";\n checkboxId.checked = false; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"unchecked\");\n }\n\n break;\n\n case \"show\":\n document.getElementById(\"hk-hints\").classList.remove(\"hidden\");\n checkboxId.value = \"hints-on\";\n checkboxId.checked = true; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"checked\");\n }\n\n break;\n\n default:\n // This runs when the checkbox is not checked\n if (checkboxId.checked === false) {\n document.getElementById(\"hk-hints\").classList.add(\"hidden\");\n checkboxId.value = \"hints-off\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"unchecked\");\n }\n } // This runs when the checkbox is checked\n else {\n document.getElementById(\"hk-hints\").classList.remove(\"hidden\");\n checkboxId.value = \"hints-on\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxHints\", \"checked\");\n }\n }\n\n }\n}\n/**\r\n * Toggles display of \".spoiler-span\" class. On click with no parameters or on demand when called with a parameter\r\n * @param {string} param \"hide\", \"show\" or none (optional)\r\n */\n\n\nfunction CheckboxSpoilersToggle() {\n var param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : \"none\";\n var checkboxId = document.getElementById(\"checkbox-spoilers\");\n var allClassElements = document.querySelectorAll(\".spoiler-span\");\n var length = allClassElements.length;\n\n switch (param) {\n case \"hide\":\n for (var i = 0; i < length; i++) {\n allClassElements[i].classList.add(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-off\";\n checkboxId.checked = false; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"unchecked\");\n }\n\n break;\n\n case \"show\":\n for (var _i = 0; _i < length; _i++) {\n allClassElements[_i].classList.remove(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-on\";\n checkboxId.checked = true; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"checked\");\n }\n\n break;\n\n default:\n // This runs when the checkbox is not checked\n if (checkboxId.checked === false) {\n for (var _i2 = 0; _i2 < length; _i2++) {\n allClassElements[_i2].classList.add(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-off\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"unchecked\");\n }\n\n break;\n } // This runs when the checkbox is checked\n else {\n for (var _i3 = 0; _i3 < length; _i3++) {\n allClassElements[_i3].classList.remove(\"hidden\");\n }\n\n checkboxId.value = \"spoilers-on\"; // remember this choice for subsequent page visits and browser restarts\n\n if (StorageAvailable('localStorage')) {\n localStorage.setItem(\"hkCheckboxSpoilers\", \"checked\");\n }\n }\n\n }\n}\n/**\r\n * Detects whether Storage is both supported and available.\r\n * MDN WebDocs https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage\r\n * @param {Storage} type type of storage. Ex. \"localStorage\" or \"sessionStorage\"\r\n * @returns {Boolean}\r\n */\n\n\nfunction StorageAvailable(type) {\n var storage;\n\n try {\n storage = window[type];\n var x = '__storage_test__';\n storage.setItem(x, x);\n storage.removeItem(x);\n return true;\n } catch (e) {\n return e instanceof DOMException && ( // everything except Firefox\n e.code === 22 || // Firefox\n e.code === 1014 || // test name field too, because code might not be present\n // everything except Firefox\n e.name === 'QuotaExceededError' || // Firefox\n e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && // acknowledge QuotaExceededError only if there's something already stored\n storage && storage.length !== 0;\n }\n}\n/* ----------------------- Event Listeners -------------------------- */\n\n\ndocument.addEventListener(\"scroll\", function () {\n TogglePageScrollElement(\n /* the document element root () */\n ROOT,\n /* Which element to toggle visibility */\n SCROLL_BUTTON,\n /* How far the user has to scroll to show the element */\n 0.1);\n});\nSCROLL_BUTTON.addEventListener(\"click\", function () {\n ScrollToElement(ROOT);\n}); // Checkboxes functions\n\ndocument.getElementById(\"checkbox-hints\").addEventListener(\"click\", CheckboxHintsToggle, false);\ndocument.getElementById(\"checkbox-spoilers\").addEventListener(\"click\", CheckboxSpoilersToggle, false);\n/* ------------------------- Exports ------------------------------- */\n\n\n\n//# sourceURL=webpack://hollow-knight-completion-check/./src/js/page-functions.js?"); /***/ }), diff --git a/src/js/HKCheckCompletion.js b/src/js/HKCheckCompletion.js index 9645e0f..a280e9a 100644 --- a/src/js/HKCheckCompletion.js +++ b/src/js/HKCheckCompletion.js @@ -1,20 +1,21 @@ /* eslint-disable no-prototype-builtins */ -// ---------------- Load main Hollow Knight database files ----------------- // +/* ---------------- Load main Hollow Knight database files ----------------- */ import HK from "./hk-database.js"; -import MAP from "./hk-dictionary.js"; /* ----------------- Helper functions --------------------------------------- */ import { + PrefillHTML, CheckboxHintsToggle, CheckboxSpoilersToggle, StorageAvailable } from "./page-functions.js"; import { - ObjectLength + ObjectLength, + TranslateMapName } from "./hk-functions.js"; // ---------------- Load image files (necessary for Webpack) ----------------- // @@ -58,7 +59,7 @@ let pSpan = ""; let benchHKCCBegin, benchHKCCEnd; -// ---------------- Functions ----------------- // +/* -------------------------- Functions ----------------------------- */ /** * Main Function. Checks Hollow Knight game completion by analyzing the save file @@ -241,34 +242,6 @@ function HKCheckCompletion(jsonObject) { return true; } -/** - * Cleans "generated" and fills all HTML elements of ids from a given list. Creates only div with id, and h2 with title inside it. - * @param {object} jsObj Object with HTML data to fill - */ -function PrefillHTML(jsObj) { - // Clean "generated" div - document.getElementById("generated").innerHTML = ""; - - let id = ""; - let h2 = ""; - let h2id = ""; - let mp = ""; // max Percent - let cl = ""; // class - - for (let i in jsObj) { - id = jsObj[i].id; - h2 = jsObj[i].h2; - h2id = "h2-" + jsObj[i].id; - - mp = `
${(i === "intro") ? 0: jsObj[i].maxPercent}%
`; - if (!jsObj[i].hasOwnProperty("maxPercent")) mp = ""; - - document.getElementById("generated").innerHTML += "
" + "
"; - // document.getElementById(id).innerHTML += "

" + h2 + mp + "

"; - document.getElementById(id).innerHTML += `

${h2}${mp}

`; - } -} - /** * Replaces the h2 titles with a current percent/max percent values as read from the save file * @param {object} jsObj Object with HTML data to fill @@ -1409,18 +1382,7 @@ function FillInnerHTML(elementId, textFill) { element.innerHTML = textFill; } -/** - * Returns a translated map location name string. - * @param {string} mapCode Code of the Hollow Knight map location the game developers use - * @param {object} dictionary Main data source for translation - */ -function TranslateMapName(mapCode, dictionary = MAP) { - - let translation = mapCode; - if (dictionary.hasOwnProperty(mapCode)) translation = dictionary[mapCode]; - - return translation; -} +/* ----------------------- Event Listeners -------------------------- */ // Populate HTML at load (before img and css) document.addEventListener("DOMContentLoaded", () => { diff --git a/src/js/hk-functions.js b/src/js/hk-functions.js index c15439f..c66436a 100644 --- a/src/js/hk-functions.js +++ b/src/js/hk-functions.js @@ -1,3 +1,9 @@ +/* ---------------- Load main Hollow Knight database files ----------------- */ + +import MAP from "./hk-dictionary.js"; + +/* -------------------------- Functions ----------------------------- */ + /** * Checks the length of a JavaScript Object like Array.length * @param {object} object JavaScript Object @@ -13,8 +19,22 @@ function ObjectLength(object) { return length; } +/** + * Returns a translated map location name string. + * @param {string} mapCode Code of the Hollow Knight map location the game developers use + * @param {object} dictionary Main data source for translation + */ +function TranslateMapName(mapCode, dictionary = MAP) { + + let translation = mapCode; + if (dictionary.hasOwnProperty(mapCode)) translation = dictionary[mapCode]; + + return translation; +} + /* ------------------------- Exports ------------------------------- */ export { - ObjectLength + ObjectLength, + TranslateMapName }; \ No newline at end of file diff --git a/src/js/page-functions.js b/src/js/page-functions.js index 8596674..705d189 100644 --- a/src/js/page-functions.js +++ b/src/js/page-functions.js @@ -38,6 +38,41 @@ function TogglePageScrollElement(root, element, ratio) { } } +/** + * Cleans "generated" and fills all HTML elements of ids from a given list. Creates only div with id, and h2 with title inside it. + * @param {object} jsObj Object with HTML data to fill + */ +function PrefillHTML(jsObj, element = "generated") { + + let domElement = document.getElementById(element); + let sFillText = ""; + // Clean "generated" div + domElement.innerHTML = ""; + + let id = ""; + let h2 = ""; + let h2id = ""; + let mp = ""; // max Percent + let cl = ""; // class + + for (let i in jsObj) { + id = jsObj[i].id; + h2 = jsObj[i].h2; + h2id = "h2-" + jsObj[i].id; + + mp = `
${(i === "intro") ? 0: jsObj[i].maxPercent}%
`; + if (!jsObj[i].hasOwnProperty("maxPercent")) mp = ""; + + sFillText += ` +
+

${h2}${mp}

+
+ `; + } + + domElement.innerHTML = sFillText; +} + /** * Toggles display of "hk-hints". On click with no parameters or on demand when called with a parameter * @param {string} param "hide", "show" or none (optional) @@ -206,6 +241,7 @@ document.getElementById("checkbox-spoilers").addEventListener("click", CheckboxS /* ------------------------- Exports ------------------------------- */ export { + PrefillHTML, CheckboxHintsToggle, CheckboxSpoilersToggle, StorageAvailable