Stat Mod

This mod allows you to see tierlist values of your character such as DPS, Burst, eHP, Build Score and Rank

  1. // ==UserScript==
  2. // @name Stat Mod
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2.1.1
  5. // @description This mod allows you to see tierlist values of your character such as DPS, Burst, eHP, Build Score and Rank
  6. // @author Daria
  7. // @license MIT
  8. // @match https://hordes.io/play
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=hordes.io
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. const ranks = ["F", "E", "D-", "D", "D+", "C-", "C", "C+", "B-", "B", "B+", "A-", "A", "A+", "S", "SS"]
  14. const rankColors = ["#9f46c6", "#5a46c6", "#467bc6", "#46c0c6", "#46c695", "#46c661", "#81c646", "#b8c646", "#c6ba46", "#c69346", "#c67546", "#c66446", "#c65746", "#740000", "#910c0c"]
  15. const sheetIDs = ["1ZltP6iegg8ON6ypbim7KbayYB35NvmWQqU0RlitTjE0", "1k3nb7xaTJmh4zxYRH_45JoWtnh5H0fkOiqdbiklPYPg", "1z7JHoIZdOPrj_VYSGLxoJVw1RA1Nfptj8AClcUXc6O0", "1LibjJwlpYdnHlRZV8ns_m_y2VeZaZHFZF8cpSr3jY7A"]
  16. let rankMetrics = []
  17. const classes = [" Warrior", " Mage", " Archer", " Shaman"]
  18.  
  19.  
  20. window.addEventListener('load', function() {
  21. 'use strict';
  22. let entered = false
  23. let interval = setInterval(function() {
  24. let statColumns = document.getElementsByClassName("statcol panel-black svelte-ggsnc")
  25. let update
  26. if (statColumns.length > 0 && !entered) {
  27. entered = true;
  28. let column = "X"
  29. if(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent == " Warrior"){
  30. column = "AG"
  31. }
  32. const url = `https://sheets.googleapis.com/v4/spreadsheets/${sheetIDs[classes.indexOf(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent)]}/values/data!${column}6:${column}21?key=AIzaSyDiSyzf40CaBHAKOrzDd5Ut193MuSlpW_Y`;
  33. fetch(url).then(data => data.json()).then(data => {
  34. rankMetrics = data.values
  35. statColumns[4].removeChild(statColumns[4].childNodes[0])
  36. statColumns[4].removeChild(statColumns[4].childNodes[0])
  37. statColumns[4].removeChild(statColumns[4].childNodes[0])
  38. statColumns[4].removeChild(statColumns[4].childNodes[0])
  39. statColumns[4].removeChild(statColumns[4].childNodes[4])
  40. statColumns[4].removeChild(statColumns[4].childNodes[4])
  41. let dps = document.createElement("span")
  42. dps.textContent = "DPS"
  43. dps.id = "dpsTextAdded"
  44. dps.style.color = "cyan"
  45. let dpsValue = document.createElement("span")
  46. dpsValue.id = "dpsValueAdded"
  47. dpsValue.className = "statnumber textprimary"
  48. let dpsn = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent)) / 2 * (1 + parseFloat(statColumns[3].childNodes[7].textContent) / 100) * (1 + parseFloat(statColumns[3].childNodes[9].textContent) / 100))
  49. dpsValue.textContent = dpsn
  50. //---------------------------
  51. let burst = document.createElement("span")
  52. burst.textContent = "Burst"
  53. burst.id = "burstTextAdded"
  54. burst.style.color = "cyan"
  55. let burstValue = document.createElement("span")
  56. burstValue.className = "statnumber textprimary"
  57. burstValue.id = "burstValueAdded"
  58. let burstn = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent)) / 2 * (1 + parseFloat(statColumns[3].childNodes[7].textContent) / 100))
  59. burstValue.textContent = burstn
  60. //----------------------------
  61. let ehp = document.createElement("span")
  62. ehp.textContent = "Effective HP"
  63. ehp.style.color = "cyan"
  64. ehp.id = "ehpTextAdded"
  65. let ehpValue = document.createElement("span")
  66. ehpValue.className = "statnumber textprimary"
  67. ehpValue.id = "ehpValueAdded"
  68. let ehpn = Math.round(parseFloat(statColumns[2].childNodes[1].textContent) * 100 / ((100 - 87 * (1 - Math.pow(Math.E, -1 * parseFloat(statColumns[2].childNodes[9].textContent) * 0.0022)))) * 125 / (125 - parseFloat(statColumns[2].childNodes[11].textContent.substring(0, statColumns[2].childNodes[11].textContent.length - 1))))
  69. ehpValue.textContent = ehpn
  70. //------------------------------
  71. let bs = document.createElement("span")
  72. bs.textContent = "Build Score"
  73. bs.style.color = "cyan"
  74. bs.id = "bsTextAdded"
  75. let bsValue = document.createElement("span")
  76. bsValue.className = "statnumber textprimary"
  77. bsValue.id = "bsValueAdded"
  78. let bsn = buildScore()
  79. bsValue.textContent = bsn
  80. statColumns[4].insertBefore(burstValue, statColumns[4].childNodes[0])
  81. statColumns[4].insertBefore(burst, statColumns[4].childNodes[0])
  82. statColumns[4].insertBefore(dpsValue, statColumns[4].childNodes[0])
  83. statColumns[4].insertBefore(dps, statColumns[4].childNodes[0])
  84. statColumns[4].insertBefore(ehpValue, statColumns[4].childNodes[0])
  85. statColumns[4].insertBefore(ehp, statColumns[4].childNodes[0])
  86. statColumns[4].append(bs, bsValue)
  87. update = setInterval(function(){
  88. if(statColumns.length == 0){
  89. clearInterval(update)
  90. }
  91. let dpsn = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent)) / 2 * (1 + parseFloat(statColumns[3].childNodes[7].textContent) / 100) * (1 + parseFloat(statColumns[3].childNodes[9].textContent) / 100))
  92. let burstn = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent)) / 2 * (1 + parseFloat(statColumns[3].childNodes[7].textContent) / 100))
  93. let ehpn = Math.round(parseFloat(statColumns[2].childNodes[1].textContent) * 100 / ((100 - 87 * (1 - Math.pow(Math.E, -1 * parseFloat(statColumns[2].childNodes[9].textContent) * 0.0022)))) / (1 - parseFloat(statColumns[2].childNodes[11].textContent.substring(0, statColumns[2].childNodes[11].textContent.length - 1)) / 100 * (document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent == " Warrior" ? 0.6 : 0.45)))
  94. let bsn = buildScore()
  95. document.getElementById("dpsValueAdded").textContent = dpsn
  96. document.getElementById("burstValueAdded").textContent = burstn
  97. document.getElementById("ehpValueAdded").textContent = ehpn
  98. document.getElementById("bsValueAdded").textContent = bsn
  99. }, 100)
  100. });
  101. } else if (statColumns.length == 0 && entered){
  102. entered = false;
  103. clearInterval(update)
  104. }
  105. }, 1)
  106. });
  107. function buildScore(){
  108. let statColumns = document.getElementsByClassName("statcol panel-black svelte-ggsnc")
  109. let cclass = document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent
  110. let prestige = document.querySelector(".textprestige").textContent.split(" ")[1].split(",").length == 1 ? parseInt(document.querySelector(".textprestige").textContent.split(" ")[1].split(",")[0]) : parseInt(document.querySelector(".textprestige").textContent.split(" ")[1].split(",")[0]) * 1000 + parseInt(document.querySelector(".textprestige").textContent.split(" ")[1].split(",")[1])
  111. let damageBonus = (prestige < 48000 ? 10 : 0) + (prestige < 16000 ? 10 : 0)
  112. let dps = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent) + damageBonus) / 2 * (1 + (parseFloat(statColumns[3].childNodes[7].textContent) + (prestige < 36000 ? 5 : 0)) / 100) * (1 + (parseFloat(statColumns[3].childNodes[9].textContent) + (prestige < 40000 ? 3 : 0)) / 100))
  113. let burst = Math.round((parseFloat(statColumns[3].childNodes[1].textContent) + parseFloat(statColumns[3].childNodes[3].textContent) + damageBonus) / 2 * (1 + (parseFloat(statColumns[3].childNodes[7].textContent) + (prestige < 36000 ? 5 : 0)) / 100))
  114. let ehp = Math.round((parseFloat(statColumns[2].childNodes[1].textContent) + (prestige < 28000 ? 30 : 0) + (prestige < 44000 ? 30 : 0)) * 100 / ((100 - 87 * (1 - Math.pow(Math.E, -1 * parseFloat(statColumns[2].childNodes[9].textContent) * 0.0022)))) / (1 - parseFloat(statColumns[2].childNodes[11].textContent.substring(0, statColumns[2].childNodes[11].textContent.length - 1)) / 100 * (document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent == " Warrior" ? 0.6 : 0.45)))
  115. let damage
  116. let hybrid
  117. let tank
  118. let haste
  119. let mit
  120. let health
  121. switch (cclass){
  122. case " Mage":
  123. damage = l((dps + burst)/2,2)
  124. hybrid = (l(ehp,5) + l(burst, 5) + l(dps, 4))/3
  125. tank = (l(ehp,2.5) + l(burst, 6) + l(dps, 6))/3
  126. rank(((damage/3)+tank+hybrid)*225/3, 1)
  127. return Math.round(((damage/3)+tank+hybrid)*225/3 * 100) / 100
  128. case " Archer":
  129. damage = (l(dps,2) + l(burst,2))/2
  130. hybrid = (l(ehp,5) + l(burst, 5) + l(dps, 4))/3
  131. tank = (l(ehp,2.5) + l(burst, 6) + l(dps, 6))/3
  132. rank(((damage/3)+tank+hybrid)*226/3, 2)
  133. return Math.round(((damage/3)+tank+hybrid)*226/3 * 100) / 100
  134. case " Warrior":
  135. mit = (1-Math.exp(-parseFloat(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[2].childNodes[9].textContent)*0.0022))*0.87 + (((parseFloat(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[2].childNodes[11].textContent)/100)*0.6))
  136. haste = parseFloat(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[3].childNodes[9].textContent) + (prestige < 40000 ? 3 : 0)
  137. damage = (l(ehp, 5) + l(dps, 2) + l(burst, 2))/3
  138. tank = (l(ehp,2) + l(mit*100, 2) + l(haste, 6))/3
  139. hybrid = (l(ehp,5) + l(dps, 4) + l(burst, 5) + l(mit*100, 5))/4
  140. rank((damage+(tank/3)+hybrid)*210/3, 0)
  141. return Math.round((damage+(tank/3)+hybrid)*210/3 * 100) / 100
  142. case " Shaman":
  143. haste = parseFloat(statColumns[3].childNodes[9].textContent + (prestige < 40000 ? 3 : 0));
  144. health = parseFloat(statColumns[2].childNodes[1].textContent) + (prestige < 44000 ? 30 : 0) + (prestige < 28000 ? 30 : 0);
  145. damage = (l(dps, 2) + l(burst, 2) + l(ehp, 10))/3;
  146. tank = (l(dps, 10) + l(burst, 11) + l(ehp, 2) + l(ehp/health*60, 7) + l(haste*8, 16))/5;
  147. hybrid = (l(dps, 3) + l(burst, 4) + l(ehp, 6) + l(ehp/health*50, 10) + l(haste*8, 9))/5;
  148. rank(((damage/1.75)+(tank)+hybrid)*235/3, 3)
  149. return Math.round(((damage/1.75)+(tank)+hybrid)*235/3 * 100) / 100;
  150. }
  151. return "-"
  152. }
  153.  
  154. function rank(bs, pclass){
  155. let rankValue
  156. if(document.getElementById("rank") == null){
  157. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].childNodes[12].remove()
  158. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].childNodes[12].remove()
  159. let rankText = document.createElement("span")
  160. rankText.textContent = "Rank"
  161. rankText.style.color = "cyan"
  162. rankValue = document.createElement("span")
  163. rankValue.id = "rank"
  164. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].append(rankText, rankValue)
  165. } else {
  166. rankValue = document.querySelector("#rank")
  167. }
  168. for(let i = 1; i < rankMetrics.length; i++){
  169. if(rankMetrics[i][0] > bs){
  170. rankValue.textContent = ranks[i - 1]
  171. rankValue.style = "color:" + rankColors[15 - i]
  172. return
  173. }
  174. }
  175. rankValue.textContent = "SS"
  176. rankValue.style = "color:#c646a0"
  177. }
  178.  
  179. function l(y, x) {
  180. return Math.log(y) / Math.log(x);
  181. }