Stat Mod

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

目前为 2023-04-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Stat Mod
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2
  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 = ["1OaKpHvEDineSW5OEtVlTc-8fZchgnlqRYjkUHPomjiM", "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.className = "bold textprestige"
  45. dps.style.color = "cyan"
  46. let dpsValue = document.createElement("span")
  47. dpsValue.id = "dpsValueAdded"
  48. dpsValue.className = "statnumber textprimary"
  49. 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))
  50. dpsValue.textContent = dpsn
  51. //---------------------------
  52. let burst = document.createElement("span")
  53. burst.textContent = "Burst"
  54. burst.className = "bold textprestige"
  55. burst.id = "burstTextAdded"
  56. burst.style.color = "cyan"
  57. let burstValue = document.createElement("span")
  58. burstValue.className = "statnumber textprimary"
  59. burstValue.id = "burstValueAdded"
  60. 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))
  61. burstValue.textContent = burstn
  62. //----------------------------
  63. let ehp = document.createElement("span")
  64. ehp.textContent = "Effective HP"
  65. ehp.className = "bold textprestige"
  66. ehp.style.color = "cyan"
  67. ehp.id = "ehpTextAdded"
  68. let ehpValue = document.createElement("span")
  69. ehpValue.className = "statnumber textprimary"
  70. ehpValue.id = "ehpValueAdded"
  71. 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))))
  72. ehpValue.textContent = ehpn
  73. //------------------------------
  74. let bs = document.createElement("span")
  75. bs.textContent = "Build Score"
  76. bs.className = "bold textprestige"
  77. bs.style.color = "cyan"
  78. bs.id = "bsTextAdded"
  79. let bsValue = document.createElement("span")
  80. bsValue.className = "statnumber textprimary"
  81. bsValue.id = "bsValueAdded"
  82. let bsn = buildScore()
  83. bsValue.textContent = bsn
  84. statColumns[4].insertBefore(burstValue, statColumns[4].childNodes[0])
  85. statColumns[4].insertBefore(burst, statColumns[4].childNodes[0])
  86. statColumns[4].insertBefore(dpsValue, statColumns[4].childNodes[0])
  87. statColumns[4].insertBefore(dps, statColumns[4].childNodes[0])
  88. statColumns[4].insertBefore(ehpValue, statColumns[4].childNodes[0])
  89. statColumns[4].insertBefore(ehp, statColumns[4].childNodes[0])
  90. statColumns[4].append(bs, bsValue)
  91. update = setInterval(function(){
  92. if(statColumns.length == 0){
  93. clearInterval(update)
  94. }
  95. 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))
  96. 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))
  97. 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)))
  98. let bsn = buildScore()
  99. document.getElementById("dpsValueAdded").textContent = dpsn
  100. document.getElementById("burstValueAdded").textContent = burstn
  101. document.getElementById("ehpValueAdded").textContent = ehpn
  102. document.getElementById("bsValueAdded").textContent = bsn
  103. }, 100)
  104. });
  105. } else if (statColumns.length == 0 && entered){
  106. entered = false;
  107. clearInterval(update)
  108. }
  109. }, 1)
  110. });
  111. function buildScore(){
  112. let statColumns = document.getElementsByClassName("statcol panel-black svelte-ggsnc")
  113. let cclass = document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].getElementsByTagName("span")[5].textContent
  114. 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])
  115. let damageBonus = (prestige < 48000 ? 10 : 0) + (prestige < 16000 ? 10 : 0)
  116. 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))
  117. 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))
  118. 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)))
  119. let damage
  120. let hybrid
  121. let tank
  122. let haste
  123. let mit
  124. let health
  125. switch (cclass){
  126. case " Mage":
  127. damage = l((dps + burst)/2,2)
  128. hybrid = (l(ehp,5) + l(burst, 5) + l(dps, 4))/3
  129. tank = (l(ehp,2.5) + l(burst, 6) + l(dps, 6))/3
  130. rank(((damage/3)+tank+hybrid)*225/3, 1)
  131. return Math.round(((damage/3)+tank+hybrid)*225/3 * 100) / 100
  132. case " Archer":
  133. damage = (l(dps,2) + l(burst,2))/2
  134. hybrid = (l(ehp,5) + l(burst, 5) + l(dps, 4))/3
  135. tank = (l(ehp,2.5) + l(burst, 6) + l(dps, 6))/3
  136. rank(((damage/3)+tank+hybrid)*226/3, 2)
  137. return Math.round(((damage/3)+tank+hybrid)*226/3 * 100) / 100
  138. case " Warrior":
  139. 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))
  140. haste = parseFloat(document.getElementsByClassName("statcol panel-black svelte-ggsnc")[3].childNodes[9].textContent) + (prestige < 40000 ? 3 : 0)
  141. damage = (l(ehp, 5) + l(dps, 2) + l(burst, 2))/3
  142. tank = (l(ehp,2) + l(mit*100, 2) + l(haste, 6))/3
  143. hybrid = (l(ehp,5) + l(dps, 4) + l(burst, 5) + l(mit*100, 5))/4
  144. rank((damage+(tank/3)+hybrid)*210/3, 0)
  145. return Math.round((damage+(tank/3)+hybrid)*210/3 * 100) / 100
  146. case " Shaman":
  147. haste = parseFloat(statColumns[3].childNodes[9].textContent + (prestige < 40000 ? 3 : 0));
  148. health = parseFloat(statColumns[2].childNodes[1].textContent) + (prestige < 44000 ? 30 : 0) + (prestige < 28000 ? 30 : 0);
  149. damage = (l(dps, 2) + l(burst, 2) + l(ehp, 10))/3;
  150. tank = (l(dps, 10) + l(burst, 11) + l(ehp, 2) + l(ehp/health*60, 7) + l(haste*8, 16))/5;
  151. hybrid = (l(dps, 3) + l(burst, 4) + l(ehp, 6) + l(ehp/health*50, 10) + l(haste*8, 9))/5;
  152. rank(((damage/1.75)+(tank)+hybrid)*235/3, 3)
  153. return Math.round(((damage/1.75)+(tank)+hybrid)*235/3 * 100) / 100;
  154. }
  155. return "-"
  156. }
  157.  
  158. function rank(bs, pclass){
  159. let rankValue
  160. if(document.getElementById("rank") == null){
  161. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].childNodes[12].remove()
  162. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].childNodes[12].remove()
  163. let rankText = document.createElement("span")
  164. rankText.textContent = "Rank"
  165. rankText.style.color = "cyan"
  166. rankValue = document.createElement("span")
  167. rankValue.id = "rank"
  168. document.getElementsByClassName("statcol panel-black svelte-ggsnc")[0].append(rankText, rankValue)
  169. } else {
  170. rankValue = document.querySelector("#rank")
  171. }
  172. for(let i = 1; i < rankMetrics.length; i++){
  173. if(rankMetrics[i][0] > bs){
  174. rankValue.textContent = ranks[i - 1]
  175. rankValue.style = "color:" + rankColors[15 - i]
  176. return
  177. }
  178. }
  179. rankValue.textContent = "SS"
  180. rankValue.style = "color:#c646a0"
  181. }
  182.  
  183. function l(y, x) {
  184. return Math.log(y) / Math.log(x);
  185. }