From 1de5dd27dd44cd52acb0565349dbbac562fa32d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?=
<13665637+DanielNoord@users.noreply.github.com>
Date: Thu, 11 Feb 2021 23:08:52 +0100
Subject: [PATCH 1/3] Fix #563
---
CookieMonster.js | 5 +++--
src/Data.js | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/CookieMonster.js b/CookieMonster.js
index 10ed971..a381bb1 100644
--- a/CookieMonster.js
+++ b/CookieMonster.js
@@ -950,6 +950,7 @@ CM.ConfigGroups = {
}
CM.ConfigGroupsNotification = {
+ NotificationGeneral: "General Notifications",
NotificationGC: "Golden Cookie",
NotificationFC: "Fortune Cookie",
NotificationSea: "Season Special",
@@ -1006,6 +1007,7 @@ CM.ConfigData.AvgClicksHist = {type: 'bool', group: 'Calculation', label: ['Aver
CM.ConfigData.ToolWarnBon = {type: 'bool', group: 'Calculation', label: ['Calculate Tooltip Warning With Bonus CPS OFF', 'Calculate Tooltip Warning With Bonus CPS ON'], desc: 'Calculate the warning with or without the bonus CPS you get from buying', toggle: true};
// Notification
+CM.ConfigData.Title = {type: 'bool', group: 'NotificationGeneral', label: ['Title OFF', 'Title ON', 'Title Pinned Tab Highlight'], desc: 'Update title with Golden Cookie/Season Popup timers; pinned tab highlight only changes the title when a Golden Cookie/Season Popup spawns', toggle: true};
CM.ConfigData.GCNotification = {type: 'bool', group: 'NotificationGC', label: ['Notification OFF', 'Notification ON'], desc: 'Create a notification when Golden Cookie spawns', toggle: true, func: function () {CM.Config.CheckNotificationPermissions(CM.Options.GCNotification);}};
CM.ConfigData.GCFlash = {type: 'bool', group: 'NotificationGC', label: ['Flash OFF', 'Flash ON'], desc: 'Flash screen on Golden Cookie', toggle: true};
CM.ConfigData.GCSound = {type: 'bool', group: 'NotificationGC', label: ['Sound OFF', 'Sound ON'], desc: 'Play a sound on Golden Cookie', toggle: true};
@@ -1061,7 +1063,6 @@ for (var i = 0; i < 101; i++) {
CM.ConfigData.WrinklerMaxVolume.label[i] = i + '%';
}
CM.ConfigData.WrinklerMaxSoundURL = {type: 'url', group: 'NotificationWrinkMax', label: 'Sound URL:', desc: 'URL of the sound to be played when the maximum amount of Wrinklers has appeared'};
-CM.ConfigData.Title = {type: 'bool', group: 'Notification', label: ['Title OFF', 'Title ON', 'Title Pinned Tab Highlight'], desc: 'Update title with Golden Cookie/Season Popup timers; pinned tab highlight only changes the title when a Golden Cookie/Season Popup spawns', toggle: true};
// Tooltip
CM.ConfigData.TooltipInfo = {type: 'bool', group: 'Tooltip', label: ['Extra Tooltip Information OFF', 'Extra Tooltip Information ON'], desc: 'Extra information in tooltips', toggle: true};
@@ -1178,7 +1179,7 @@ CM.Data.ConfigDefault = {
GCTimer: 1,
Favicon: 1,
WrinklerButtons: 1,
- Header: {BarsColors: 1, Calculation: 1, Notification: 1, NotificationGC: 1, NotificationFC: 1, NotificationSea: 1, NotificationGard: 1, NotificationMagi: 1, NotificationWrink: 1, NotificationWrinkMax: 1, Tooltip: 1, Statistics: 1, Notation: 1, Miscellaneous: 1, Lucky: 1, Spells: 1, Chain: 1, Prestige: 1, Wrink: 1, Sea: 1, Misc: 1},
+ Header: {BarsColors: 1, Calculation: 1, Notification: 1, NotificationGeneral: 1, NotificationGC: 1, NotificationFC: 1, NotificationSea: 1, NotificationGard: 1, NotificationMagi: 1, NotificationWrink: 1, NotificationWrinkMax: 1, Tooltip: 1, Statistics: 1, Notation: 1, Miscellaneous: 1, Lucky: 1, Spells: 1, Chain: 1, Prestige: 1, Wrink: 1, Sea: 1, Misc: 1},
};
/********
diff --git a/src/Data.js b/src/Data.js
index 63dc624..0a3f381 100644
--- a/src/Data.js
+++ b/src/Data.js
@@ -66,6 +66,7 @@ CM.ConfigGroups = {
}
CM.ConfigGroupsNotification = {
+ NotificationGeneral: "General Notifications",
NotificationGC: "Golden Cookie",
NotificationFC: "Fortune Cookie",
NotificationSea: "Season Special",
@@ -122,6 +123,7 @@ CM.ConfigData.AvgClicksHist = {type: 'bool', group: 'Calculation', label: ['Aver
CM.ConfigData.ToolWarnBon = {type: 'bool', group: 'Calculation', label: ['Calculate Tooltip Warning With Bonus CPS OFF', 'Calculate Tooltip Warning With Bonus CPS ON'], desc: 'Calculate the warning with or without the bonus CPS you get from buying', toggle: true};
// Notification
+CM.ConfigData.Title = {type: 'bool', group: 'NotificationGeneral', label: ['Title OFF', 'Title ON', 'Title Pinned Tab Highlight'], desc: 'Update title with Golden Cookie/Season Popup timers; pinned tab highlight only changes the title when a Golden Cookie/Season Popup spawns', toggle: true};
CM.ConfigData.GCNotification = {type: 'bool', group: 'NotificationGC', label: ['Notification OFF', 'Notification ON'], desc: 'Create a notification when Golden Cookie spawns', toggle: true, func: function () {CM.Config.CheckNotificationPermissions(CM.Options.GCNotification);}};
CM.ConfigData.GCFlash = {type: 'bool', group: 'NotificationGC', label: ['Flash OFF', 'Flash ON'], desc: 'Flash screen on Golden Cookie', toggle: true};
CM.ConfigData.GCSound = {type: 'bool', group: 'NotificationGC', label: ['Sound OFF', 'Sound ON'], desc: 'Play a sound on Golden Cookie', toggle: true};
@@ -177,7 +179,6 @@ for (var i = 0; i < 101; i++) {
CM.ConfigData.WrinklerMaxVolume.label[i] = i + '%';
}
CM.ConfigData.WrinklerMaxSoundURL = {type: 'url', group: 'NotificationWrinkMax', label: 'Sound URL:', desc: 'URL of the sound to be played when the maximum amount of Wrinklers has appeared'};
-CM.ConfigData.Title = {type: 'bool', group: 'Notification', label: ['Title OFF', 'Title ON', 'Title Pinned Tab Highlight'], desc: 'Update title with Golden Cookie/Season Popup timers; pinned tab highlight only changes the title when a Golden Cookie/Season Popup spawns', toggle: true};
// Tooltip
CM.ConfigData.TooltipInfo = {type: 'bool', group: 'Tooltip', label: ['Extra Tooltip Information OFF', 'Extra Tooltip Information ON'], desc: 'Extra information in tooltips', toggle: true};
@@ -294,6 +295,6 @@ CM.Data.ConfigDefault = {
GCTimer: 1,
Favicon: 1,
WrinklerButtons: 1,
- Header: {BarsColors: 1, Calculation: 1, Notification: 1, NotificationGC: 1, NotificationFC: 1, NotificationSea: 1, NotificationGard: 1, NotificationMagi: 1, NotificationWrink: 1, NotificationWrinkMax: 1, Tooltip: 1, Statistics: 1, Notation: 1, Miscellaneous: 1, Lucky: 1, Spells: 1, Chain: 1, Prestige: 1, Wrink: 1, Sea: 1, Misc: 1},
+ Header: {BarsColors: 1, Calculation: 1, Notification: 1, NotificationGeneral: 1, NotificationGC: 1, NotificationFC: 1, NotificationSea: 1, NotificationGard: 1, NotificationMagi: 1, NotificationWrink: 1, NotificationWrinkMax: 1, Tooltip: 1, Statistics: 1, Notation: 1, Miscellaneous: 1, Lucky: 1, Spells: 1, Chain: 1, Prestige: 1, Wrink: 1, Sea: 1, Misc: 1},
};
From 9357e16dec865d36244c862f16a0983e8aec94c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?=
<13665637+DanielNoord@users.noreply.github.com>
Date: Wed, 17 Feb 2021 22:45:39 +0100
Subject: [PATCH 2/3] Fix crash with no upgrades #528
---
CookieMonster.js | 93 +++++++++++++++++++++++++-----------------------
src/Disp.js | 93 +++++++++++++++++++++++++-----------------------
2 files changed, 96 insertions(+), 90 deletions(-)
diff --git a/CookieMonster.js b/CookieMonster.js
index a381bb1..ed206d0 100644
--- a/CookieMonster.js
+++ b/CookieMonster.js
@@ -3886,52 +3886,55 @@ CM.Disp.CreateStatsPrestigeSection = function() {
* It is called by CM.Disp.AddMenuStats() when CM.Options.MissingUpgrades is set
*/
CM.Disp.AddMissingUpgrades = function() {
- if (CM.Cache.MissingUpgradesPrestige) {
- var prestigeUpgradesOwned = Game.PrestigeUpgrades.length - l('menu').children[5].children[3].children.length;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesPrestigeTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing Prestige upgrades: '+ prestigeUpgradesOwned + '/' + Game.PrestigeUpgrades.length + ' (' + Math.floor((prestigeUpgradesOwned / Game.PrestigeUpgrades.length) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[5].appendChild(title)
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgradesPrestige;
- l('menu').children[5].appendChild(upgrades)
+ for (let menuSection of (l('menu').children)) {
+ if (menuSection.children[0]) {
+ if (menuSection.children[0].innerHTML === "Prestige" && CM.Cache.MissingUpgradesPrestige) {
+ let prestigeUpgradesMissing = CM.Cache.MissingUpgradesPrestige.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesPrestigeTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing Prestige upgrades: '+ prestigeUpgradesMissing + '/' + Game.PrestigeUpgrades.length + ' (' + Math.floor((prestigeUpgradesMissing / Game.PrestigeUpgrades.length) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.appendChild(title);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgradesPrestige;
+ menuSection.appendChild(upgrades);
+ }
+ else if (menuSection.children[0].innerHTML === "Upgrades") {
+ if (CM.Cache.MissingUpgrades) {
+ let normalUpgradesMissing = CM.Cache.MissingUpgrades.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesMissing + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length) + ' (' + Math.floor((normalUpgradesMissing / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length)) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.insertBefore(title, l('menu').children[6].childNodes[3]);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgrades;
+ menuSection.insertBefore(upgrades, document.getElementById("CMMissingUpgradesTitle").nextSibling);
+ }
+ if (CM.Cache.MissingUpgradesCookies) {
+ let cookieUpgradesMissing = CM.Cache.MissingUpgradesCookies.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesCookiesTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing Cookie upgrades: '+ cookieUpgradesMissing + '/' + Game.UpgradesByPool.cookie.length + ' (' + Math.floor((cookieUpgradesMissing / Game.UpgradesByPool.cookie.length) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.appendChild(title);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgradesCookies;
+ menuSection.appendChild(upgrades);
+ }
+ }
+ }
}
- if (CM.Cache.MissingUpgrades) {
- if (Game.UpgradesOwned) {
- var normalUpgradesOwned = Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length - l('menu').children[6].childNodes[2].children.length;
- } else var normalUpgradesOwned = 0;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesOwned + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length) + ' (' + Math.floor((normalUpgradesOwned / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length)) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[6].insertBefore(title, l('menu').children[6].childNodes[3])
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgrades;
- l('menu').children[6].insertBefore(upgrades, document.getElementById("CMMissingUpgradesTitle").nextSibling)
- }
- if (CM.Cache.MissingUpgradesCookies) {
- var cookieUpgradesOwned = Game.UpgradesByPool["cookie"].length - l('menu').children[6].lastChild.children.length;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesCookiesTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing Cookie upgrades: '+ cookieUpgradesOwned + '/' + Game.UpgradesByPool["cookie"].length + ' (' + Math.floor((cookieUpgradesOwned / Game.UpgradesByPool["cookie"].length) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[6].appendChild(title)
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgradesCookies;
- l('menu').children[6].appendChild(upgrades)
-
- }
-}
+};
/**
* This function returns the "crates" (icons) for missing upgrades in the stats sections
diff --git a/src/Disp.js b/src/Disp.js
index 8ccb49a..333ba20 100644
--- a/src/Disp.js
+++ b/src/Disp.js
@@ -2702,52 +2702,55 @@ CM.Disp.CreateStatsPrestigeSection = function() {
* It is called by CM.Disp.AddMenuStats() when CM.Options.MissingUpgrades is set
*/
CM.Disp.AddMissingUpgrades = function() {
- if (CM.Cache.MissingUpgradesPrestige) {
- var prestigeUpgradesOwned = Game.PrestigeUpgrades.length - l('menu').children[5].children[3].children.length;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesPrestigeTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing Prestige upgrades: '+ prestigeUpgradesOwned + '/' + Game.PrestigeUpgrades.length + ' (' + Math.floor((prestigeUpgradesOwned / Game.PrestigeUpgrades.length) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[5].appendChild(title)
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgradesPrestige;
- l('menu').children[5].appendChild(upgrades)
+ for (let menuSection of (l('menu').children)) {
+ if (menuSection.children[0]) {
+ if (menuSection.children[0].innerHTML === "Prestige" && CM.Cache.MissingUpgradesPrestige) {
+ let prestigeUpgradesMissing = CM.Cache.MissingUpgradesPrestige.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesPrestigeTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing Prestige upgrades: '+ prestigeUpgradesMissing + '/' + Game.PrestigeUpgrades.length + ' (' + Math.floor((prestigeUpgradesMissing / Game.PrestigeUpgrades.length) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.appendChild(title);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgradesPrestige;
+ menuSection.appendChild(upgrades);
+ }
+ else if (menuSection.children[0].innerHTML === "Upgrades") {
+ if (CM.Cache.MissingUpgrades) {
+ let normalUpgradesMissing = CM.Cache.MissingUpgrades.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesMissing + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length) + ' (' + Math.floor((normalUpgradesMissing / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length)) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.insertBefore(title, l('menu').children[6].childNodes[3]);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgrades;
+ menuSection.insertBefore(upgrades, document.getElementById("CMMissingUpgradesTitle").nextSibling);
+ }
+ if (CM.Cache.MissingUpgradesCookies) {
+ let cookieUpgradesMissing = CM.Cache.MissingUpgradesCookies.match(new RegExp("div", "g") || []).length / 2;
+ let title = document.createElement('div');
+ title.id = "CMMissingUpgradesCookiesTitle";
+ title.className = "listing";
+ let titlefrag = document.createElement('div');
+ titlefrag.innerHTML = 'Missing Cookie upgrades: '+ cookieUpgradesMissing + '/' + Game.UpgradesByPool.cookie.length + ' (' + Math.floor((cookieUpgradesMissing / Game.UpgradesByPool.cookie.length) * 100) + '%)';
+ title.appendChild(titlefrag);
+ menuSection.appendChild(title);
+ let upgrades = document.createElement('div');
+ upgrades.className = "listing crateBox";
+ upgrades.innerHTML = CM.Cache.MissingUpgradesCookies;
+ menuSection.appendChild(upgrades);
+ }
+ }
+ }
}
- if (CM.Cache.MissingUpgrades) {
- if (Game.UpgradesOwned) {
- var normalUpgradesOwned = Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length - l('menu').children[6].childNodes[2].children.length;
- } else var normalUpgradesOwned = 0;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesOwned + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length) + ' (' + Math.floor((normalUpgradesOwned / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool["tech"].length)) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[6].insertBefore(title, l('menu').children[6].childNodes[3])
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgrades;
- l('menu').children[6].insertBefore(upgrades, document.getElementById("CMMissingUpgradesTitle").nextSibling)
- }
- if (CM.Cache.MissingUpgradesCookies) {
- var cookieUpgradesOwned = Game.UpgradesByPool["cookie"].length - l('menu').children[6].lastChild.children.length;
- var title = document.createElement('div');
- title.id = "CMMissingUpgradesCookiesTitle";
- title.className = "listing";
- titlefrag = document.createElement('div');
- titlefrag.innerHTML = 'Missing Cookie upgrades: '+ cookieUpgradesOwned + '/' + Game.UpgradesByPool["cookie"].length + ' (' + Math.floor((cookieUpgradesOwned / Game.UpgradesByPool["cookie"].length) * 100) + '%)';
- title.appendChild(titlefrag)
- l('menu').children[6].appendChild(title)
- upgrades = document.createElement('div');
- upgrades.className = "listing crateBox";
- upgrades.innerHTML = CM.Cache.MissingUpgradesCookies;
- l('menu').children[6].appendChild(upgrades)
-
- }
-}
+};
/**
* This function returns the "crates" (icons) for missing upgrades in the stats sections
From c4c95eaa31b2cebee482d31ab74166a4c3e42d96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?=
<13665637+DanielNoord@users.noreply.github.com>
Date: Thu, 18 Feb 2021 21:29:14 +0100
Subject: [PATCH 3/3] Fix missing upgrades display #574
---
CookieMonster.js | 2 +-
src/Disp.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/CookieMonster.js b/CookieMonster.js
index ed206d0..9172f34 100644
--- a/CookieMonster.js
+++ b/CookieMonster.js
@@ -3911,7 +3911,7 @@ CM.Disp.AddMissingUpgrades = function() {
let titlefrag = document.createElement('div');
titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesMissing + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length) + ' (' + Math.floor((normalUpgradesMissing / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length)) * 100) + '%)';
title.appendChild(titlefrag);
- menuSection.insertBefore(title, l('menu').children[6].childNodes[3]);
+ menuSection.insertBefore(title, menuSection.childNodes[3]);
let upgrades = document.createElement('div');
upgrades.className = "listing crateBox";
upgrades.innerHTML = CM.Cache.MissingUpgrades;
diff --git a/src/Disp.js b/src/Disp.js
index 333ba20..4937770 100644
--- a/src/Disp.js
+++ b/src/Disp.js
@@ -2727,7 +2727,7 @@ CM.Disp.AddMissingUpgrades = function() {
let titlefrag = document.createElement('div');
titlefrag.innerHTML = 'Missing normal upgrades: '+ normalUpgradesMissing + '/' + (Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length) + ' (' + Math.floor((normalUpgradesMissing / ( Game.UpgradesByPool[""].length + Game.UpgradesByPool.tech.length)) * 100) + '%)';
title.appendChild(titlefrag);
- menuSection.insertBefore(title, l('menu').children[6].childNodes[3]);
+ menuSection.insertBefore(title, menuSection.childNodes[3]);
let upgrades = document.createElement('div');
upgrades.className = "listing crateBox";
upgrades.innerHTML = CM.Cache.MissingUpgrades;