您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Displays number of extra stats your armor gives you.
// ==UserScript==// [WoD] Extra Equipment Stats // Version 1.14, 2014-08-08 // Script aimed at players of World Of Dungeons. Displays number of extra stats your armor gives you. // // When you enter your attributes page, a new button will appear at the bottom of page. // Pressing this button will fetch info about equipment your hero is wearing and display // cumulative info (like total attack bonus, total defense bonus, etc...) at the bottom of the page. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Changelog // 1.14 // - fixing english Damage Sensitivity // // 1.13 // - updating german and french set related translations // - "Created with" link added // // 1.12 // - first try at fixing set item boni multiple calculation // // 1.11 // - grant/downloadURL metadata added // // 1.10 // - fixed loading of equipment page related to change of url parameters // // 1.9 // - added german translation // - fix, again :(, for "+hero level" parsing bug // // 1.8 // - fixed attribute bonus parsing for french ("Attribut" -> "Particularité") // // 1.7 // - fix in bonus addition and calculation introduced by modifications for french server // - some fixes to french translations // - internal optimization of some calculations // // 1.6 // - will use local storage instead of GM_g(s)etvalue if local storage is supported // - rounding now executed without eval :) // - now using JSON.parse/stringify (where available) instead of eval/toSource // - items with ' in names now correctly displayed // // 1.5 // - Math.Round() doesn't exist, replaced by Math.round() // - fixed parsing bug due to design changes // - included french translation and allowed all wod sites to use since should not depend on language used. // (clan monument analysis not tested in french) // - fix of HL replace when HL is included in HL_Per. // - added Finargol and taitoune to contributor list, thanks for helping on french version // - added check for existance of GM_ functions so Opera users can use it too (some functionality missing) // - rounding down or to the nearest integer is now language dependent (to accomodate behavior of french server) // // 1.4 // - status message now displays equipment name // - fixed parsing bug due to design changes // - fixed small bug when (z) explanation was not shown in some cases // - first (of many :() trial on including update notifier script // // 1.3 // - saving last calculated result and displaying immediately on page load // - removed "!! " from "reset point required to remove" items // - changed way items are displayed when multiple items contribute to single stat (no more button to press) // // 1.2 // - fix for "+hero level" parsing bug // // 1.1 // - button disabled while equipment info is being fetched/calculated to prevent doing it multiple times simultaneously // - status text moved below button so it doesn't "jump" up/down when status is empty/not empty // - removed usage count from names of consumable items // - changed way how items that can be worn multiple times are displayed, if effect is "only when used with" it will be // displayed only once, if not it will be displayed once but with x2, x3, x4.... appended to item name (and effect multiplied naturally) // I.E. // if 3 song books ballad of evasion are worn it will show only once in bonus for the level of the skill area (with (a) modifier) // if 3 skulls are worn it will show only once as "skull x3" having spell defense bonus equal to 3 // - added calculation of current bonus/malus value based on current hero level // - added clan monument stats into calculations // - fixed problem with bonus for the effect of the skill caused by additional description being added above effect bonus table // // 1.0 // - initial release //----------------------------------------------------------------------------- // ==UserScript== // @name WoD 额外装备信息统计 // @icon http://info.world-of-dungeons.org/wod/css/WOD.gif // @namespace tomy // @description Displays number of extra stats your armor gives you. // @include http*://*.world-of-dungeons.*/wod/spiel/hero/attributes.php* // @author Tomy // @contributor Finargol, taitoune, Mastermage // @copyright 2010+, Tomy // @grant GM_getValue // @grant GM_setValue // @modifier Christophero // @version 2022.11.15.1 // ==/UserScript== var DEBUG = false; var VER = "1.18"; var LOCAL_VAR_NAME = "WOD ARMOR STATS " + location.host; var Equipment = false; var Result = false; var Attribs = false; var Level = false; var Effect = false; var DamageTaken = false; var Defense = false; var Damage = false; var Attack = false; var SetArray = false; var SetCollection = false; var HeroLevel = undefined; var KeyButton = null; String.prototype.endsWith = function (suffix) { return this.indexOf(suffix, this.length - suffix.length) !== -1; }; String.prototype.startsWith = function (prefix) { return this.indexOf(prefix) == 0; }; String.prototype.removeRight = function (suffix) { if (!this.endsWith(suffix)) return String(this); return String(this).substring(0, this.length - suffix.length); }; String.prototype.trim = function () { return this.replace(/^\s+|\s+$/g, ""); }; String.prototype.space_clear = function () { var tmp = this; while (tmp.indexOf(" ") !== -1) tmp = tmp.replace(" ", ""); return tmp; }; function isFunctionDefined(name) { return eval("typeof " + name + " == 'function'"); } function supportsLocalStorage() { try { return "localStorage" in window && window["localStorage"] !== null; } catch (e) { return false; } } function stringify(data) { if (typeof JSON == "object" && typeof JSON.stringify == "function") return JSON.stringify(data); else return data.toSource(); } function parse(data) { if (typeof JSON == "object" && typeof JSON.parse == "function") return JSON.parse(data); else return eval(data); } function getLocalValue(name, defValue) { var ret = defValue; if (supportsLocalStorage()) { try { ret = window.localStorage[name]; } catch (e) {} } if (ret == defValue && isFunctionDefined("GM_getValue")) return GM_getValue(name, defValue); if (ret != defValue) ret = parse(ret); return ret; } function setLocalValue(name, value) { var tmp = stringify(value); if (supportsLocalStorage()) { try { window.localStorage[name] = tmp; return true; } catch (e) {} } if (isFunctionDefined("GM_setValue")) { GM_setValue(name, tmp); return true; } return false; } function DebugMsg(Data) { if (DEBUG) alert(JSON.stringify(Data, null, 4)); } function SetStatus(text, index, max, after) { var tmpText = text; if (max > 0) text = text + " (" + index + "/" + max + ")"; if (after != undefined) text += " - " + after; Result.innerHTML = "<h3>" + text + "<h3>"; } function trim(data) { // Use ECMA-262 Edition 3 String and RegExp features data = data.replace(/[\t\n\r ]+/g, " "); if (data.charAt(0) == " ") data = data.substring(1, data.length); if (data.charAt(data.length - 1) == " ") data = data.substring(0, data.length - 1); return data; } var Contents = { en: { Button_Name: "Calculate additional equipment stats", Title: "<h1>Additional equipment statistics</h1>Last calculated on ", Fetch_Hero: "Fetching hero info", Fetch_Clan: "Fetching clan info", Fetch_Equipment: "Fetching equipment list", Fetch_Info: "Fetching equipment info", Armor_Bonus: "Armor bonus", Attr_Bonus: "Attribute bonus", Level_Bonus: "Bonus for the level of the skill", Effect_Bonus: "Bonus for the effect of the skill", Damage_Taken: "Damage sensitivity", Defense_Bonus: "Defense bonus", Damage_Bonus: "Damage bonus", Damage_BonusR: "Damage Bonus (r)", Attack_Bonus: "Attack bonus", Dungeon_Bonus: "Bonus on loot from Dungeons", Item: "Item", Attribute: "Attribute", Skill: "Skill", Modifier: "Modifier", Value: "Value", Used_With: " (a)", Dmg_With: " (z)", Per: "%", HL_Per: "% of your hero`s level", HL: "hero level", Mult: " x ", Attack_Type: "Attack Type", Dmg_Split: " / ", Damage_Type: "Damage Type", BonusR: "Bonus (r)", Owner_Effect: "Effect on the owner of this item", Race_Name: "race", Level: "Level", Adv_Disadv: "advantages - disadvantages", Monument: "monument", Clan_Has_Monument: "The clan owns the monument", Link: "Link ...", Item_Skill: "the penalty or bonus are active when the item is used with one of the above mentioned skills.", Effect_BonusTalent: "<p>Increase the bonus on the <b>effect</b>, <u>not</u> the <b>level</b> of the skill. The bonuses will be added to the amount of <b>damage</b> (when using that type of attack) or the amount of <b>healing</b> (when healing).</p>", Damage_Added: "additionally - when damage of this type is dealt", Damage_Effect: "is added upon normal / good / critical hits as an additional <i>effect</i> to the weapon used.", Rounding: Math.floor, All_Hits: "by normal / good / critical hits", Details: "details", Set: "Set", Copyright: "Created with Extra Equipment Stats", }, cn: { Button_Name: "Calculate additional equipment stats", Title: "<h1>Additional equipment statistics</h1>Last calculated on ", Fetch_Hero: "Fetching hero info", Fetch_Clan: "Fetching clan info", Fetch_Equipment: "Fetching equipment list", Fetch_Info: "Fetching equipment info", Armor_Bonus: "护甲奖励", Attr_Bonus: "属性奖励", Level_Bonus: "对技能等级的奖励", Effect_Bonus: "对技能效果的奖励", Damage_Taken: "对此种攻击方式,攻击类型伤害的脆弱性", Defense_Bonus: "防御奖励", Damage_Bonus: "伤害奖励", Damage_BonusR: "伤害奖励 (r)", Attack_Bonus: "攻击奖励", Dungeon_Bonus: "地城探险得到的物品掉落奖励", Item: "物品", Attribute: "属性", Skill: "技能", Modifier: "修正", Value: "Value", Used_With: " (a)", Dmg_With: " (z)", Per: "%", HL_Per: "%×英雄等级", HL: "英雄等级", Mult: " x ", Attack_Type: "攻击方式", Dmg_Split: " / ", Damage_Type: "伤害方式", BonusR: "奖励 (r)", Owner_Effect: "作用在物品持有者上的效果", Owner_Effect2: "作用在人物 XXX身上的奖励效果:", Race_Name: "种族", Level: "级别", Adv_Disadv: "职业特性", Monument: "纪念碑", Clan_Has_Monument: "联盟纪念碑", Link: "链接...", Item_Skill: "只有在该物品可以使用的技能下使用此物品时,才会有这些奖惩效果。", Effect_BonusTalent: "奖励技能的效果,不是技能的等级。此奖励会增加到伤害(当使用该种攻击方式时)或者治疗量(当治疗时)。", Damage_Added: "只有当已经形成该攻击方式,该类型的伤害后,所标注的伤害奖励才会附加上去,否则不会附加", Damage_Effect: "当普通/重击/致命时,(伤害)<i>效果</i>附加在使用的武器上。", Rounding: Math.floor, All_Hits: "普通/重击/致命", Details: "详细信息", Set: "套装", Copyright: "Created with Extra Equipment Stats", }, fr: { Button_Name: "Calculer les stats", Title: "<h1>Stats d'équipement supplémentaires.</h1>Derniere mise a jour ", Fetch_Hero: "Recherche du héros", Fetch_Clan: "Recherche du clan", Fetch_Equipment: "Recherche de l'équipement", Fetch_Info: "Recherche des infos", Armor_Bonus: "Bonus d'armure", Attr_Bonus: "Bonus sur les particularités", Level_Bonus: "Bonus sur le rang de talents", Effect_Bonus: "Bonus sur l'effet de talents", Damage_Taken: "Bonus sur la sensibilité aux dégâts", Defense_Bonus: "Bonus sur les parades", Damage_Bonus: "Bonus sur les dégâts", Damage_BonusR: "Bonus de dégâts (r)", Attack_Bonus: "Bonus sur les attaques", Dungeon_Bonus: "Bonus de combat en donjon", Item: "Objet", Attribute: "Particularité", Skill: "Talent", Modifier: "Modificateur", Value: "Valeur", Used_With: " (a)", Dmg_With: " (z)", Per: "%", HL_Per: "% du niveau du héros", HL: "du niveau du héros", Mult: " x ", Attack_Type: "Sorte d'attaque", Dmg_Split: " / ", Damage_Type: "Sorte de dégâts", BonusR: "Bonus (r)", Owner_Effect: "Effets sur le propriétaire de l'objet", Race_Name: "Peuple", Level: "Niveau", Adv_Disadv: "Avantages et inconvénients", Monument: "monument", Clan_Has_Monument: "Le clan possede le monument", Link: "Lien ...", Item_Skill: "uniquement quand l'objet est utilisé en combination avec l'un des talents indiqués ci-dessus", Effect_BonusTalent: "<p>Le bonus sur l'<b>Effet</b> n'augmente pas le <b>Rang</b> du talent. Au lieu de ça, les bonus sont ajoutés aux <b>dommages</b> (pour le type 'Attaques') ou aux <b>soins</b> (pour le type 'Guérison').</p>", Damage_Added: "Supplémentaire - uniquement quand des dégâts de ce genre sont causés", Damage_Effect: "lors de coups normaux / complets / critiques, est ajouté a l'effet de l'arme utilisée.", Rounding: Math.round, All_Hits: "lors de succès normaux / complets / critiques", Details: "Détails", Set: "Set", Copyright: "Créé avec Extra Equipment Stats", }, de: { Button_Name: "Berechne Ausrüstungs-Boni", Title: "<h1>Boni durch Ausrüstung.</h1>Zuletzt aktualisiert am: ", Fetch_Hero: "Durchsuche Helden...", Fetch_Clan: "Durchsuche Clan...", Fetch_Equipment: "Durchsuche Ausrüstung...", Fetch_Info: "Sammle Informationen...", Armor_Bonus: "Boni auf Rüstung", Attr_Bonus: "Boni auf Eigenschaften", Level_Bonus: "Boni auf den Rang von Fertigkeiten", Effect_Bonus: "Boni auf die Wirkung von Fertigkeiten", Damage_Taken: "Boni auf die Anfälligkeit gegen Schäden", //here the correct german text is: "Boni auf die <a href="https://world-of-dungeons.de/ency/Anf%C3%A4lligkeit">Anfälligkeit</a> gegen Schäden" Defense_Bonus: "Boni auf Paraden", Damage_Bonus: "Boni auf Schaden", Damage_BonusR: "Schadensbonus (r)", Attack_Bonus: "Boni auf Angriffe", Dungeon_Bonus: "Boni auf Beute aus Dungeonkämpfen", Item: "Gegenstand", Attribute: "Eigenschaft", Skill: "Fertigkeit", Modifier: "Modifikator", Value: "Wert", //not sure which text is asked for here Used_With: " (a)", Dmg_With: " (z)", Per: "%", HL_Per: "% der Heldenstufe", HL: "Heldenstufe", Mult: " x ", Attack_Type: "Angriffsart", Dmg_Split: " / ", Damage_Type: "Schadensart", BonusR: "Bonus (r)", Owner_Effect: "Auswirkungen auf den Besitzer des Gegenstands", Race_Name: "Volk", Level: "Heldenstufe", Adv_Disadv: "Vor- und Nachteile", Monument: "Monument", Clan_Has_Monument: "Der Clan besitzt das Monument", Link: "Link ...", Item_Skill: "nur, während der Gegenstand mit einer der oben genannten Fertigkeiten angewendet wird", Effect_BonusTalent: 'Boni auf die <b>Wirkung</b> erhöhen <u>nicht</u> den <b>Rang</b> einer Fertigkeit. Stattdessen werden die Boni zur Höhe des <b>Schadens</b> (beim Typ "Angriff") oder der <b>Heilung</b> (beim Typ "Heilung") addiert.', Damage_Added: "zusätzlich - nur wenn schon Schaden dieser Art verursacht wird", Damage_Effect: "wird bei normalen / guten / kritischen Treffern zur <i>Wirkung</i> der benutzten Waffe addiert.", Rounding: Math.floor, All_Hits: "bei normalen / guten / kritischen Treffern", Details: "Details", Set: "Set", Copyright: "Erstellt mit Extra Equipment Stats", }, }; var MandatoryProps = {}; try { Main(); } catch (e) { alert("Main(): " + e); } // FUNCTIONS ////////////////////////////////////////////////////////////////// function Main() { // Language selection if (GetLocalContents() == null) return; MandatoryProps[Contents.Attr_Bonus] = [Contents.Attribute, Contents.Modifier]; MandatoryProps[Contents.Level_Bonus] = [Contents.Skill, Contents.Modifier]; MandatoryProps[Contents.Effect_Bonus] = [Contents.Skill, Contents.Modifier]; MandatoryProps[Contents.Damage_Taken] = [ Contents.Attack_Type, Contents.BonusR, Contents.Damage_Type, ]; MandatoryProps[Contents.Attack_Bonus] = [ Contents.Attack_Type, Contents.Modifier, ]; MandatoryProps[Contents.Damage_Bonus] = [ Contents.Attack_Type, Contents.Damage_BonusR, Contents.Damage_Type, ]; MandatoryProps[Contents.Defense_Bonus] = [ Contents.Attack_Type, Contents.Modifier, ]; MandatoryProps[Contents.Armor_Bonus] = []; MandatoryProps[Contents.Dungeon_Bonus] = []; // Add buttons KeyButton = AddButtonBeforeHints(Contents.Button_Name, OnCountStat); if (KeyButton == null) return; var nHeroId = GetHiddenInfo(document, "session_hero_id", ""); var tmp = getLocalValue(LOCAL_VAR_NAME + nHeroId, undefined); if (tmp != undefined && tmp.version == VER) { Result.innerHTML = tmp.text; } } // It will only add the first eligible button // return: the node of the first eligible disabled button, or null if didn't find anyone function AddButtonBeforeHints(ButtonText, ButtonFunct) { var allInputs = document.getElementsByTagName("div"); for (var i = 0; i < allInputs.length; ++i) { if ( allInputs[i].className == "hints on" || allInputs[i].className == "hints off" ) { var newTable = document.createElement("table"); var newTR = document.createElement("tr"); var newTD = document.createElement("td"); var resTR = document.createElement("tr"); Result = document.createElement("td"); var newButton = document.createElement("input"); newButton.setAttribute("type", "button"); newButton.setAttribute("class", "button"); newButton.setAttribute("value", ButtonText); newButton.addEventListener("click", ButtonFunct, false); newTable.appendChild(newTR); newTR.appendChild(newTD); newTD.appendChild(newButton); newTable.appendChild(resTR); resTR.appendChild(Result); allInputs[i].parentNode.insertBefore(newTable, allInputs[i]); var newP1 = document.createElement("br"); var newP2 = document.createElement("br"); allInputs[i].parentNode.insertBefore(newP1, newTable); allInputs[i].parentNode.insertBefore(newP2, newTable); return newButton; } } return null; } // Choose contents of the corresponding language // Contents: { "lang1": { "Name1": "Value1", ..., "NameN": "ValueN" }, ..., "langN": { ... } ... } // return: Local contents, or null // It will edit the input contents directly, so the returned object is not necessary function GetLocalContents() { function GetLanguage() { var langText = null; var allMetas = document.getElementsByTagName("meta"); for (var i = 0; i < allMetas.length; ++i) { if (allMetas[i].httpEquiv == "Content-Language") { langText = allMetas[i].content; break; } } return langText; } var lang = GetLanguage(); if (lang == null) return null; if (Contents instanceof Object) { Contents = Contents[lang]; return Contents; } else return null; } function Value(abs, per, hlper) { if (!abs) abs = 0; if (!per) per = 0; if (!hlper) hlper = 0; this.abs = abs; this.per = per; this.hlper = hlper; } Value.Parse = function (text) { if (!text || text.trim().length == 0) text = ""; var hl = text.replace(Contents.Mult + Contents.HL, "00" + Contents.HL_Per); hl = hl.replace("+ " + Contents.HL, "+100" + Contents.HL_Per); hl = hl.replace("+" + Contents.HL, "+100" + Contents.HL_Per); hl = hl.replace("- " + Contents.HL, "-100" + Contents.HL_Per); hl = hl.replace("-" + Contents.HL, "-100" + Contents.HL_Per); hl = hl.replace(Contents.HL_Per, "HL"); var abs = 0; var per = 0; var hlper = 0; var arr = hl.split(" "); var txt = ""; for (var j = 0; j < arr.length; ++j) { if (arr[j].endsWith(Contents.Per)) per = arr[j].removeRight(Contents.Per) * 1; else if (arr[j].endsWith("HL")) hlper = arr[j].removeRight("HL") * 1; else abs = arr[j] * 1; } return new Value(abs, per, hlper); }; Value.prototype.Add = function (RightVal) { return new Value( this.abs + RightVal.abs, this.per + RightVal.per, this.hlper + RightVal.hlper ); }; Value.prototype.Mult = function (rhs) { return new Value(this.abs * rhs, this.per * rhs, this.hlper * rhs); }; Value.prototype.Html = function (negative) { var txt = ""; if (negative == undefined) negative = false; var mult = negative ? -1 : 1; if (this.abs != 0) { txt += '<span class="gem_' + (this.abs * mult > 0 ? "bonus" : "malus") + '">' + (this.abs > 0 ? "+" + this.abs : this.abs) + "</span> "; } if (this.per != 0) { txt += '<span class="gem_' + (this.per * mult > 0 ? "bonus" : "malus") + '">' + (this.per > 0 ? "+" + this.per /*.toFixed(2)*/ : this.per) /*.toFixed(2)*/ + Contents.Per + "</span> "; } if (this.hlper != 0) { if (Math.abs(this.hlper) == 100) { txt += '<span class="gem_' + (this.hlper * mult > 0 ? "bonus" : "malus") + '">' + (this.hlper > 0 ? "+" : "-") + Contents.HL + "</span> "; } else if (Math.abs(this.hlper) % 100 == 0) { txt += '<span class="gem_' + (this.hlper * mult > 0 ? "bonus" : "malus") + '">' + (this.hlper > 0 ? "+" : "") + Math.round(this.hlper / 100) + Contents.Mult + Contents.HL + "</span> "; } else { txt += '<span class="gem_' + (this.hlper * mult > 0 ? "bonus" : "malus") + '">' + (this.hlper > 0 ? "+" : "") + this.hlper + Contents.HL_Per + "</span> "; } } if (txt.length == 0) txt = "0"; return txt.trim(); }; Value.prototype.Calc = function (hero_level) { return new Value( Contents.Rounding(this.abs + (hero_level * this.hlper) / 100), this.per, 0 ); }; function Dmg(normal, good, critical) { if (!normal) normal = new Value(); if (!good) good = new Value(); if (!critical) critical = new Value(); this.normal = normal; this.good = good; this.critical = critical; } Dmg.Parse = function (text) { if (!text || text.trim().length == 0) { return new Dmg(); } var arr = text.split(Contents.Dmg_Split); return new Dmg(Value.Parse(arr[0]), Value.Parse(arr[1]), Value.Parse(arr[2])); }; Dmg.prototype.Add = function (RightVal) { return new Dmg( this.normal.Add(RightVal.normal), this.good.Add(RightVal.good), this.critical.Add(RightVal.critical) ); }; Dmg.prototype.Mult = function (rhs) { return new Dmg( this.normal.Mult(rhs), this.good.Mult(rhs), this.critical.Mult(rhs) ); }; Dmg.prototype.Html = function (negative) { return ( this.normal.Html(negative) + Contents.Dmg_Split + this.good.Html(negative) + Contents.Dmg_Split + this.critical.Html(negative) ); }; Dmg.prototype.Calc = function (hero_level) { return new Dmg( this.normal.Calc(hero_level), this.good.Calc(hero_level), this.critical.Calc(hero_level) ); }; function OnCountStat() { try { if (this.className == "button_disabled") return; else this.className = "button_disabled"; Result.innerHTML = ""; Attribs = new Object(); Level = new Object(); Effect = new Object(); DamageTaken = new Object(); Defense = new Object(); Damage = new Object(); Attack = new Object(); Equipment = new Array(); SetArray = new Array(); SetCollection = new Object(); var nHeroId = GetHiddenInfo(document, "session_hero_id", ""); var nPlayerId = GetHiddenInfo(document, "session_player_id", ""); GetHeroInfo(nHeroId, nPlayerId); } catch (e) { alert("OnCountStat(): " + e); } } function GetHeroInfo(heroID, playerID) { var XmlHttp = new XMLHttpRequest(); XmlHttp.onreadystatechange = function () { try { if (XmlHttp.readyState == 4 && XmlHttp.status == 200) { var Page = document.createElement("div"); Page.innerHTML = XmlHttp.responseText; ReadHeroInfo(Page); GetClanInfo(heroID, playerID); } } catch (e) { alert("XMLHttpRequest.onreadystatechange(): " + e); } }; var URL = location.protocol + "//" + location.host + "/wod/spiel/hero/profile.php?id=" + heroID + "&session_hero_id=" + heroID + "&IS_POPUP=1"; SetStatus(Contents.Fetch_Hero, 0, 0); XmlHttp.open("GET", URL, true); XmlHttp.send(null); } function ReadHeroInfo(Document) { var allTD = Document.getElementsByTagName("td"); var url = ""; for (var i = 0; i < allTD.length - 1; ++i) { if (allTD[i].innerHTML == Contents.Race_Name) { var tmpName = allTD[i + 1].textContent.trim().removeRight("*"); var allA = allTD[i + 1].getElementsByTagName("a"); if (allA.length == 1) { var href = allA[0].getAttribute("href"); Equipment.push({ id: 0, name: tmpName, link: href, count: 1, okH2: Contents.Adv_Disadv, }); } else { alert("ReadHeroInfo failed " + allA.length); } } else if (allTD[i].innerHTML == Contents.Level) { HeroLevel = allTD[i + 1].textContent.trim(); } } } function GetClanInfo(heroID, playerID) { var XmlHttp = new XMLHttpRequest(); XmlHttp.onreadystatechange = function () { try { if (XmlHttp.readyState == 4 && XmlHttp.status == 200) { var Page = document.createElement("div"); Page.innerHTML = XmlHttp.responseText; ReadClanInfo(Page); GetEquipment(heroID, playerID); } } catch (e) { alert("XMLHttpRequest.onreadystatechange(): " + e); } }; var URL = location.protocol + "//" + location.host + "/wod/spiel/clan/clan.php?session_hero_id=" + heroID + "&IS_POPUP=1"; SetStatus(Contents.Fetch_Clan, 0, 0); XmlHttp.open("GET", URL, true); XmlHttp.send(null); } function ReadClanInfo(Document) { var allH2 = Document.getElementsByTagName("h2"); for (var j = 0; j < allH2.length; ++j) { if (trim(allH2[j].textContent) != Contents.Monument) continue; var firstSibling = allH2[j].nextSibling; var nextSibling = firstSibling.nextSibling; if ( firstSibling.nodeName == "#text" && nextSibling.nodeName == "A" && trim(firstSibling.textContent) == Contents.Clan_Has_Monument ) { Equipment.push({ id: 0, name: nextSibling.textContent, link: nextSibling.getAttribute("href"), count: 1, okH2: undefined, }); } } } function GetHiddenInfo(Document, InfoName, DefaultValue) { var allInputs = Document.getElementsByTagName("input"); for (var i = 0; i < allInputs.length; ++i) { if ( allInputs[i].getAttribute("type") == "hidden" && allInputs[i].name == InfoName ) return allInputs[i].value; } return DefaultValue; } function GetEquipment(heroID, playerID) { var XmlHttp = new XMLHttpRequest(); XmlHttp.onreadystatechange = function () { try { if (XmlHttp.readyState == 4 && XmlHttp.status == 200) { var Page = document.createElement("div"); Page.innerHTML = XmlHttp.responseText; ReadEquipment(Page, heroID, playerID); GetItem(0, heroID, playerID); } } catch (e) { alert("XMLHttpRequest.onreadystatechange(): " + e); } }; var URL = location.protocol + "//" + location.host + "/wod/spiel/hero/items.php" + "?view=gear" + "&session_hero_id=" + heroID; SetStatus(Contents.Fetch_Equipment, 0, 0); XmlHttp.open("GET", URL, true); XmlHttp.send(null); } function ReadEquipment(Document, heroID, playerID) { var allForms = Document.getElementsByTagName("form"); for (var i = 0; i < allForms.length; ++i) { if (allForms[i].getAttribute("name") == "the_form") { var allTDs = allForms[i].getElementsByTagName("td"); for (var k = 0; k < allTDs.length; ++k) { var allOptions = allTDs[k].getElementsByTagName("option"); var allTable = allTDs[k].getElementsByTagName("table"); if (allTable.length > 0 || allOptions.length == 0) continue; var lastID = undefined; var lastName = undefined; for (var j = 0; j < allOptions.length; ++j) { var tmpId = allOptions[j].getAttribute("value") * -1; if (tmpId > 0) lastID = tmpId; if (tmpId == 0) { var tmpName = allOptions[j].innerHTML; if (tmpName.charAt(tmpName.length - 1) == "!") tmpName = tmpName.substr(0, tmpName.length - 1); lastName = tmpName; } } if (lastID != undefined && lastName != undefined) { if (/[^\(]*\([0-9]*\/[0-9]*\)/.test(lastName)) { lastName = lastName.replace(/\([0-9]*\/[0-9]*\)/g, ""); } if (lastName.startsWith("!! ")) lastName = lastName.substring(3); var found = false; //for (var z = 0; z < Equipment.length; ++z) { // if (Equipment[z].name == lastName) { // Equipment[z].count++; // found = true; // break; // } //} if (!found) Equipment.push({ id: lastID, name: lastName, link: "/wod/spiel/hero/item.php?item_instance_id=" + lastID + "&session_hero_id=" + heroID + "&session_player_id=" + playerID + "&is_popup=1", count: 1, okH2: Contents.Owner_Effect, }); } } } } } function GetItem(index, heroID, playerID) { if (index == Equipment.length) { ReadSet(heroID); //GetSet(0, heroID); return; } var XmlHttp = new XMLHttpRequest(); XmlHttp.onreadystatechange = function () { try { if (XmlHttp.readyState == 4 && XmlHttp.status == 200) { var Page = document.createElement("div"); Page.innerHTML = XmlHttp.responseText; ParseItem(index, Page, false); GetItem(index + 1, heroID, playerID); } } catch (e) { alert("XMLHttpRequest.onreadystatechange(): " + e); } }; var URL = location.protocol + "//" + location.host + Equipment[index].link; SetStatus( Contents.Fetch_Info, index + 1, Equipment.length, Equipment[index].name ); XmlHttp.open("GET", URL, true); XmlHttp.send(null); } function CheckProperties(name, data, props) { var ret = true; for (var j = 0; j > props.length; ++j) { if (!data.hasOwnProperty(props[j])) { alert("Missing field + " + name + " - " + props[j]); ret = false; } } return ret; } function ReadSet(heroID) { var tmp_equipment_length = Equipment.length; // push sets into Equipments for (var j = 0; j < SetArray.length; j++) { Equipment.push({ id: 0, name: SetArray[j], link: "/wod/spiel/hero/set.php" + "?name=" + SetArray[j] + "&simulate_item_count=" + SetCollection[SetArray[j]].count.toString() + "&is_popup=1", count: 1, okH2: Contents.Owner_Effect2, }); } GetSet(tmp_equipment_length, heroID); } function GetSet(index, heroID) { if (index == Equipment.length) { DisplayResult(heroID); return; } var XmlHttp = new XMLHttpRequest(); XmlHttp.onreadystatechange = function () { try { if (XmlHttp.readyState == 4 && XmlHttp.status == 200) { var Page = document.createElement("div"); Page.innerHTML = XmlHttp.responseText; ParseItem(index, Page, true); GetSet(index + 1, heroID); } } catch (e) { alert("XMLHttpRequest.onreadystatechange(): " + e); } }; var URL = location.protocol + "//" + location.host + Equipment[index].link; SetStatus( Contents.Fetch_Info, index + 1, Equipment.length, Equipment[index].name ); XmlHttp.open("GET", URL, true); XmlHttp.send(null); } function CheckProperties(name, data, props) { var ret = true; for (var j = 0; j > props.length; ++j) { if (!data.hasOwnProperty(props[j])) { alert("Missing field + " + name + " - " + props[j]); ret = false; } } return ret; } function DeductSetValue(data, index, names, value, used_with, in_addition) { try { for (var mynamej in names) { //console.log(names[mynamej]); data = data[names[mynamej]]; } } catch (e) { //console.log('extra_error '+SetArray[index] + ' '+ names[0] + ' ' + myname); return; } if (data == undefined) { //console.log('data undefined'); return; } //console.log('extra deduct '+SetArray[index] + ' ' + names[0]); //console.log('extra deduct data len ' + data.length.toString()); // data is now inner most array of {values, item, used_with, set_name} for (var j = 0; j < data.length; ++j) { var tmp_in_addition; if (data[j].hasOwnProperty("in_addition")) { tmp_in_addition = data[j]["in_addition"]; //console.log(tmp_in_addition); } else { tmp_in_addition = false; } if (data[j].hasOwnProperty("used_with")) { tmp_used_with = data[j]["used_with"]; //console.log(tmp_in_addition); } else { tmp_used_with = false; } //console.log('set name '+data[j]['set_name']); //console.log('item name ' + Equipment[data[j]['item']].name); if ( data[j]["set_name"] == Equipment[index].name && tmp_used_with == used_with && tmp_in_addition == in_addition ) { //console.log('extra dect value '+SetArray[index] + '' + name[0]); data[j]["value"] = data[j]["value"].Add(value.Mult(-1)); } } } function PushWithCreateSubarrays(data, names, value) { for (var j = 0; j < names.length; ++j) { if (!data.hasOwnProperty(names[j])) { if (j != names.length - 1) { data[names[j]] = new Object(); } else { data[names[j]] = new Array(); } } data = data[names[j]]; } data.push(value); } function ParseItem(index, Document, spF) { var allChildren = undefined; var okH2 = Equipment[index].okH2; var setName = undefined; var allH2 = Document.getElementsByTagName("h2"); if (allH2 != undefined) { for (var j = 0; j < allH2.length && setName == undefined; ++j) { if (trim(allH2[j].textContent) == Contents.Details) { var allTDs = allH2[j].nextSibling.nextSibling.getElementsByTagName("td"); for (var k = 0; k < allTDs.length - 1 && setName == undefined; ++k) { if (trim(allTDs[k].textContent) == Contents.Set) setName = trim(allTDs[k + 1].textContent); } } } } if (setName != undefined && !spF) { if (SetCollection.hasOwnProperty(setName)) { SetCollection[setName].count++; } else { SetArray.push(setName); SetCollection[setName] = { count: 1 }; } } if (okH2 != undefined) { for (var i = 0; i < allH2.length; ++i) { if (allH2[i].textContent == okH2) { allChildren = allH2[i].parentNode.childNodes; break; } } } else { allChildren = Document.getElementsByTagName("form")[0].childNodes; } if (allChildren != undefined) { var ok = okH2 == undefined; for (var j = 0; j < allChildren.length - 2; ++j) { if (allChildren[j].nodeName == "H2") { var tmpH2 = trim(allChildren[j].textContent); if (tmpH2.length > 0 && okH2 != undefined) { ok = tmpH2 == okH2; } } else if ( ok && allChildren[j].nodeName == "H3" && (allChildren[j + 2].nodeName == "TABLE" || (allChildren[j + 2].nodeName == "P" && allChildren[j + 3].nodeName == "#text" && allChildren[j + 4].nodeName == "TABLE")) ) { var name = trim(allChildren[j].textContent); var parsed = undefined; if (allChildren[j + 2].nodeName == "TABLE") parsed = ParseTable(allChildren[j + 2]); else parsed = ParseTable(allChildren[j + 4]); for (var k = 0; k < parsed.length; ++k) { if ( MandatoryProps.hasOwnProperty(name) && CheckProperties(name, parsed[k], MandatoryProps[name]) ) { var set_name = setName != undefined && parsed[k].IsGem ? setName : undefined; if (name == Contents.Attr_Bonus) { if (parsed[k][Contents.Modifier].endsWith(Contents.Used_With)) { var tmp_names = [parsed[k][Contents.Attribute]]; var tmp_value = Value.Parse( parsed[k][Contents.Modifier].removeRight(Contents.Used_With) ); var tmp_item = index; if (spF) { DeductSetValue( Attribs, tmp_item, tmp_names, tmp_value, true, false ); } PushWithCreateSubarrays(Attribs, tmp_names, { value: tmp_value, item: index, used_with: true, set_name: set_name, }); } } else if (name == Contents.Level_Bonus) { if (parsed[k][Contents.Modifier].endsWith(Contents.Used_With)) { var tmp_names = [parsed[k][Contents.Skill]]; var tmp_value = Value.Parse( parsed[k][Contents.Modifier].removeRight(Contents.Used_With) ); var tmp_item = index; if (spF) { DeductSetValue( Level, tmp_item, tmp_names, tmp_value, true, false ); } PushWithCreateSubarrays(Level, tmp_names, { value: tmp_value, item: index, used_with: true, set_name: set_name, }); } } else if (name == Contents.Effect_Bonus) { var tmp_names = [parsed[k][Contents.Skill]]; var tmp_value = Value.Parse( parsed[k][Contents.Modifier].removeRight(Contents.Used_With) ); var tmp_item = index; var tmp_used_with = parsed[k][Contents.Modifier].endsWith( Contents.Used_With ); if (spF) { DeductSetValue( Effect, tmp_item, tmp_names, tmp_value, tmp_used_with, false ); } PushWithCreateSubarrays(Effect, tmp_names, { value: tmp_value, item: index, used_with: tmp_used_with, set_name: set_name, }); } else if (name == Contents.Damage_Taken) { var tmp_names = [ parsed[k][Contents.Damage_Type], parsed[k][Contents.Attack_Type].removeRight(Contents.Used_With), ]; var tmp_value = Dmg.Parse( parsed[k][Contents.BonusR].removeRight(Contents.Dmg_With) ); var tmp_item = index; var tmp_in_addition = parsed[k][Contents.BonusR].endsWith( Contents.Dmg_With ); var tmp_used_with = parsed[k][Contents.Attack_Type].endsWith( Contents.Used_With ); if (spF) { DeductSetValue( DamageTaken, tmp_item, tmp_names, tmp_value, tmp_used_with, tmp_in_addition ); } PushWithCreateSubarrays(DamageTaken, tmp_names, { value: tmp_value, item: index, in_addition: tmp_in_addition, used_with: tmp_used_with, set_name: set_name, }); } else if (name == Contents.Attack_Bonus) { var tmp_names = [parsed[k][Contents.Attack_Type]]; var tmp_value = Value.Parse( parsed[k][Contents.Modifier].removeRight(Contents.Used_With) ); var tmp_item = index; var tmp_used_with = parsed[k][Contents.Modifier].endsWith( Contents.Used_With ); if (spF) { DeductSetValue( Attack, tmp_item, tmp_names, tmp_value, tmp_used_with, false ); } PushWithCreateSubarrays(Attack, tmp_names, { value: tmp_value, item: index, used_with: tmp_used_with, set_name: set_name, }); } else if (name == Contents.Damage_Bonus) { var tmp_names = [ parsed[k][Contents.Damage_Type], parsed[k][Contents.Attack_Type].removeRight(Contents.Used_With), ]; var tmp_value = Dmg.Parse( parsed[k][Contents.Damage_BonusR].removeRight(Contents.Dmg_With) ); var tmp_item = index; var tmp_in_addition = parsed[k][Contents.Damage_BonusR].endsWith( Contents.Dmg_With ); var tmp_used_with = parsed[k][Contents.Attack_Type].endsWith( Contents.Used_With ); if (spF) { DeductSetValue( Damage, tmp_item, tmp_names, tmp_value, tmp_used_with, tmp_in_addition ); } PushWithCreateSubarrays(Damage, tmp_names, { value: tmp_value, item: index, in_addition: tmp_in_addition, used_with: tmp_used_with, set_name: set_name, }); } else if (name == Contents.Defense_Bonus) { var tmp_names = [parsed[k][Contents.Attack_Type]]; var tmp_value = Value.Parse( parsed[k][Contents.Modifier].removeRight(Contents.Used_With) ); var tmp_item = index; var tmp_used_with = parsed[k][Contents.Modifier].endsWith( Contents.Used_With ); if (spF) { DeductSetValue( Defense, tmp_item, tmp_names, tmp_value, tmp_used_with, false ); } PushWithCreateSubarrays(Defense, tmp_names, { value: tmp_value, item: index, used_with: tmp_used_with, set_name: set_name, }); } } else { if (okH2 != undefined || name != Contents.Link) alert("Unknown stat: " + name); } } j += allChildren[j + 2].nodeName == "TABLE" ? 2 : 4; } } } } function AddTableRow(isHeader, index, data, center) { var td = "td"; if (isHeader) td = "th"; var ret = ""; if (data.length > 0) { ret = '<tr class="' + (isHeader ? "header" : "row" + (index % 2)) + '">'; for (var j = 0; j < data.length; ++j) { var centertxt = ""; if (center != undefined) { if ( (typeof center == "object" && center[j]) || (typeof center == "boolean" && center) ) centertxt = ' align="center"'; } ret += "<" + td + ' class="content_table"' + centertxt + ">" + data[j] + "</" + td + ">"; } ret += "</tr>"; } return ret; } function GetEquipmentName(index, multiples) { return ( Equipment[index].name.replace("'", "'") + (multiples && Equipment[index].count > 1 ? " x" + Equipment[index].count : "") ); } function GetEquipmentHref(index, multiples) { return ( "<a onclick=\"return wo('" + Equipment[index].link + '&IS_POPUP=1\');" target="_blank" class="item_usable" href="' + Equipment[index].link + '&IS_POPUP=1" id="___wodToolTip_UniqueId__1">' + GetEquipmentName(index, multiples) + "</a>" ); } function AddTable(heroID, Where, Data, heading, headers, desc) { var display = false; var txt = "<h3>" + heading + "</h3>"; if (desc != undefined) txt += desc; txt += '<table class="content_table"><tbody>'; txt += AddTableRow(true, 0, headers); var j = 0; var havea = false; for (var k in Data) { var total = new Value(); var disp = '<table style="font-size: 10px;">'; var last_disp = ""; var cnt = 0; var sets = new Array(); for (var i = 0; i < Data[k].length; ++i) { if (Data[k][i].used_with) continue; //if (Data[k][i].set_name != undefined) { // if (sets.indexOf(Data[k][i].set_name) != -1) continue; // sets.push(Data[k][i].set_name); //} total = total.Add( Data[k][i].value.Mult(Equipment[Data[k][i].item].count) ); disp += "<tr><td>" + GetEquipmentHref(Data[k][i].item, true) + "</td><td>" + Data[k][i].value.Mult(Equipment[Data[k][i].item].count).Html() + "</td></tr>"; last_disp = GetEquipmentHref(Data[k][i].item, true); cnt++; } disp += "</table>"; if (cnt > 0) { txt += AddTableRow( false, j, [ k, total.Html(), total.Calc(HeroLevel).Html(), cnt > 1 ? disp : last_disp, ], [false, true, true, false] ); j++; } for (var i = 0; i < Data[k].length; ++i) { if (!Data[k][i].used_with) continue; txt += AddTableRow( false, j, [ k, Data[k][i].value.Html() + "<sup>" + Contents.Used_With + "</sup>", Data[k][i].value.Calc(HeroLevel).Html() + "<sup>" + Contents.Used_With + "</sup>", GetEquipmentHref(Data[k][i].item, false), ], [false, true, true, false] ); j++; havea = true; } } txt += "</tbody></table>"; if (havea) txt += '<font size="-1"><sup>(a)</sup> ' + Contents.Item_Skill + "</font>"; if (j > 0) Where.innerHTML += txt; } function AddTableEx(heroID, Where, Data, heading, headers, negative) { if (negative == undefined) negative = false; var display = false; var txt = "<h3>" + heading + '</h3><table class="content_table"><tbody>'; txt += AddTableRow(true, 0, headers); var j = 0; var havea = false; var havez = false; for (var k in Data) { for (var l in Data[k]) { var total = new Dmg(); var disp = '<table style="font-size: 10px;">'; var last_disp = ""; var cnt = 0; var sets = new Array(); for (var i = 0; i < Data[k][l].length; ++i) { if (Data[k][l][i].used_with || Data[k][l][i].in_addition) continue; //if (Data[k][l][i].set_name != undefined) { // if (sets.indexOf(Data[k][l][i].set_name) != -1) continue; // sets.push(Data[k][l][i].set_name); //} total = total.Add( Data[k][l][i].value.Mult(Equipment[Data[k][l][i].item].count) ); disp += "<tr><td>" + GetEquipmentHref(Data[k][l][i].item, true) + "</td><td>" + Data[k][l][i].value .Mult(Equipment[Data[k][l][i].item].count) .Html(negative) + "</td></tr>"; last_disp = GetEquipmentHref(Data[k][l][i].item, true); cnt++; } disp += "</table>"; if (cnt > 0) { txt += AddTableRow( false, j, [ k, l, total.Html(negative), total.Calc(HeroLevel).Html(negative), cnt > 1 ? disp : last_disp, ], [false, true, true, true, false] ); j++; } total = new Dmg(); disp = '<table style="font-size: 10px;">'; last_disp = ""; cnt = 0; sets = new Array(); for (var i = 0; i < Data[k][l].length; ++i) { if (Data[k][l][i].used_with || !Data[k][l][i].in_addition) continue; if (Data[k][l][i].set_name != undefined) { if (sets.indexOf(Data[k][l][i].set_name) != -1) continue; sets.push(Data[k][l][i].set_name); } total = total.Add( Data[k][l][i].value.Mult(Equipment[Data[k][l][i].item].count) ); disp += "<tr><td>" + GetEquipmentHref(Data[k][l][i].item, true) + "</td><td>" + Data[k][l][i].value .Mult(Equipment[Data[k][l][i].item].count) .Html(negative) + "</td></tr>"; last_disp = GetEquipmentHref(Data[k][l][i].item, true); cnt++; } disp += "</table>"; if (cnt > 0) { txt += AddTableRow( false, j, [ k, l, total.Html(negative) + "<sup>" + Contents.Dmg_With + "</sup>", total.Calc(HeroLevel).Html(negative) + "<sup>" + Contents.Dmg_With + "</sup>", cnt > 1 ? disp : last_disp, ], [false, true, true, true, false] ); j++; havez = true; } for (var i = 0; i < Data[k][l].length; ++i) { if (!Data[k][l][i].used_with) continue; txt += AddTableRow( false, j, [ k, l + "<sup>" + Contents.Used_With + "</sup>", Data[k][l][i].value.Html(negative) + (Data[k][l][i].in_addition ? "<sup>" + Contents.Dmg_With + "</sup>" : ""), Data[k][l][i].value.Calc(HeroLevel).Html(negative) + (Data[k][l][i].in_addition ? "<sup>" + Contents.Dmg_With + "</sup>" : ""), GetEquipmentHref(Data[k][l][i].item, false), ], [false, true, true, true, false] ); j++; havea = true; havez = havez || Data[k][l][i].in_addition; } } } txt += "</tbody></table>"; if (!negative) { txt += '<font size="-1"><sup>(r)</sup> ' + Contents.Damage_Effect + "</font><br>"; if (havea) txt += '<font size="-1"><sup>(a)</sup> ' + Contents.Item_Skill + "</font><br>"; if (havez) txt += '<font size="-1"><sup>(z)</sup> ' + Contents.Damage_Added + "</font>"; } else { txt += '<font size="-1"><sup>(r)</sup> ' + Contents.All_Hits + "</font>"; if (havea) txt += '<font size="-1"><sup>(a)</sup> ' + Contents.Item_Skill + "</font><br>"; if (havez) txt += '<font size="-1"><sup>(z)</sup> ' + Contents.Damage_Added + "</font>"; } if (j > 0) Where.innerHTML += txt; } function DisplayResult(heroID) { Result.innerHTML = Contents.Title + new Date().toLocaleString() + "<br/>" + "<a target='_blank' href='https://raw.githubusercontent.com/tomy2105/wod/master/extra_equipment_stats.user.js'><span style='font-size: 9px;'>" + Contents.Copyright + " v" + VER + "</span></a>"; AddTable( heroID, Result, Attribs, Contents.Attr_Bonus, [Contents.Attribute, Contents.Modifier, Contents.Value, Contents.Item], undefined ); AddTable( heroID, Result, Level, Contents.Level_Bonus, [Contents.Skill, Contents.Modifier, Contents.Value, Contents.Item], undefined ); AddTable( heroID, Result, Effect, Contents.Effect_Bonus, [Contents.Skill, Contents.Modifier, Contents.Value, Contents.Item], Contents.Effect_BonusTalent ); AddTable( heroID, Result, Attack, Contents.Attack_Bonus, [Contents.Attack_Type, Contents.Modifier, Contents.Value, Contents.Item], undefined ); AddTable( heroID, Result, Defense, Contents.Defense_Bonus, [Contents.Attack_Type, Contents.Modifier, Contents.Value, Contents.Item], undefined ); AddTableEx(heroID, Result, Damage, Contents.Damage_Bonus, [ Contents.Damage_Type, Contents.Attack_Type, Contents.Damage_BonusR, Contents.Value, Contents.Item, ]); AddTableEx( heroID, Result, DamageTaken, Contents.Damage_Taken, [ Contents.Damage_Type, Contents.Attack_Type, Contents.BonusR, Contents.Value, Contents.Item, ], true ); if (KeyButton.className == "button_disabled") KeyButton.className = "button"; //setLocalValue(LOCAL_VAR_NAME + heroID, {text:Result.innerHTML, version:VER}); } function ParseTable(Document) { var ret = new Array(); var names = new Array(); var allTRs = Document.getElementsByTagName("tr"); for (var j = 0; j < allTRs.length; ++j) { var tr = allTRs[j]; if ( tr.getAttribute("class") == "content_table_header" || tr.getAttribute("class") == "header" ) { var allTHs = tr.getElementsByTagName("th"); for (var k = 0; k < allTHs.length; ++k) { names.push(allTHs[k].textContent.trim().space_clear()); } } else { var allTDs = tr.getElementsByTagName("td"); var row = new Object(); var isGem = false; for (var k = 0; k < allTDs.length; ++k) { row[names[k]] = allTDs[k].textContent.trim().space_clear(); if (allTDs[k].innerHTML.indexOf('by_gem">') != -1) { isGem = true; } } row["IsGem"] = isGem; ret.push(row); } } return ret; }