您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Добавляет в инфу персов и на домашнюю: ХП армии, очки и загрузку навыков, баланс рулетки и таверны, сумму умений, день рождения персонажа
当前为
// ==UserScript== // @name hwmAdvancedPlayerInfo // @author alex_kocharin 2008-2012, Demin 2013-2015, Tamozhnya1 2024 // @namespace Tamozhnya1 // @version 17.4 // @description Добавляет в инфу персов и на домашнюю: ХП армии, очки и загрузку навыков, баланс рулетки и таверны, сумму умений, день рождения персонажа // @include /^https{0,1}:\/\/(www|my)\.(heroeswm|lordswm)\.(ru|com)\/(home|pl_info)\.php/ // @grant GM_deleteValue // @grant GM_getValue // @grant GM_setValue // @grant GM.xmlHttpRequest // @license MIT // ==/UserScript== if(typeof GM_deleteValue != 'function') { this.GM_getValue = function(key, def) { return localStorage[key] || def; }; this.GM_setValue = function(key, value) { localStorage[key] = value; }; this.GM_deleteValue = function(key) { return delete localStorage[key]; }; } const playerIdMatch = document.cookie.match(/pl_id=(\d+)/); if(playerIdMatch) { var PlayerId = playerIdMatch[1]; } const windowObject = window.wrappedJSObject || unsafeWindow; const lang = document.documentElement.lang || (location.hostname == "www.lordswm.com" ? "en" : "ru"); const isEn = lang == "en"; let playerFraction; if(location.pathname == '/home.php') { // for new home page let currentFractionIconContainer = document.querySelector("div.home_css_pl_fract.show_hint"); if(!currentFractionIconContainer) { currentFractionIconContainer = document.querySelector("a[href^='castle.php?change_faction_dialog']"); } if(currentFractionIconContainer) { const currentFractionIconImg = currentFractionIconContainer.querySelector("img"); playerFraction = currentFractionIconImg.src.split("i/f/r")[1].split(".png")[0]; } } else { const playerFractionExec = /\/i\/f\/r(\d+)\.png/.exec(document.querySelector("body").innerHTML); //console.log(playerFractionExec); if(!playerFractionExec) { console.log("Unknown player fraction"); return; }; playerFraction = playerFractionExec[1]; //console.log(playerFraction); } const isNewPersonPage = document.querySelector("div#hwm_no_zoom") ? true : false; let playerLevel; if(isNewPersonPage) { const levelInfoCell = Array.from(document.querySelectorAll("div.home_pers_info")).find(x => x.innerHTML.includes(isEn ? "Combat level" : "Боевой уровень")); playerLevel = parseInt(levelInfoCell.querySelector("div[id=bartext] > span").innerText); } else { playerLevel = parseInt(new RegExp(`<b>${isEn ? "Combat level" : "Боевой уровень"}: (\\d+?)<\\/b>`).exec(document.documentElement.innerHTML)[1]) || 0; } const artsInfo = { '2year_amul_lords': [2], '3arrows': [5], '3year_amul': [2], '3year_art': [3], '4year_klever': [3], '5years_star': [5], a_mallet: [1], amf_body: [8], amf_boot: [7], amf_cl: [8], amf_helm: [6], amf_scroll: [8], amf_weap: [11], antifire_cape: [3], barb_armor: [6], barb_boots: [6], barb_club: [7], barb_helm: [4], barb_shield: [6], bfly: [5], blacksword: [10], blacksword1: [10], bludgeon: [9], bril_pendant: [6], bril_ring: [5], brush_2010y: [15], brush_2011y: [15], brush_2012y: [15], bunt_medal1: [11], bunt_medal2: [6], bunt_medal3: [4], bwar1: [15], bwar2: [12], bwar3: [10], bwar4: [8], bwar5: [7], bwar6: [6], bwar7: [5], bwar_splo: [8], bwar_stoj: [8], bwar_takt: [8], centaurbow: [5], d_spray: [4], darkelfboots: [7], darkelfciras: [7], darkelfcloack: [6], darkelfcloak: [6], darkelfkaska: [6], darkelfpendant: [9], darkelfstaff: [10], defender_dagger: [2], dem_amulet: [9], dem_armor: [6], dem_axe: [10], dem_bootshields: [6], dem_dmech: [6], dem_dtopor: [11], dem_helmet: [6], dem_kosa: [9], dem_shield: [6], demwar1: [14], demwar2: [11], demwar3: [9], demwar4: [7], demwar5: [5], demwar6: [4], druid_amulet: [11], druid_armor: [8], druid_boots: [7], druid_cloack: [8], druid_staff: [11], dubina: [11], elfamulet: [9], elfboots: [7], elfbow: [8], elfshirt: [7], elfwar1: [13], elfwar2: [11], elfwar3: [8], elfwar4: [7], elfwar5: [6], elfwar6: [4], finecl: [6], flower_heart: [1], flowers1: [1], flowers2: [1], flowers3: [4], flowers4: [5], flowers5: [5], gdubina: [7], gm_3arrows: [5], gm_abow: [6], gm_amul: [5], gm_arm: [5], gm_defence: [5], gm_hat: [4], gm_kastet: [8], gm_protect: [6], gm_rring: [2], gm_spdb: [2], gm_sring: [2], gm_sword: [8], gmage_armor: [8], gmage_boots: [7], gmage_cloack: [8], gmage_crown: [6], gmage_scroll: [8], gmage_staff: [11], gnome_hammer: [2], gnomearmor: [6], gnomeboots: [5], gnomehammer: [9], gnomehelmet: [5], gnomem_amulet: [11], gnomem_armor: [8], gnomem_boots: [7], gnomem_hammer: [10], gnomem_helmet: [6], gnomem_shield: [7], gnomeshield: [6], gnomewar1: [15], gnomewar2: [12], gnomewar3: [10], gnomewar4: [8], gnomewar5: [7], gnomewar6: [6], gnomewar7: [5], gnomewar_splo: [8], gnomewar_stoj: [8], gnomewar_takt: [8], goldciras: [4], half_heart_m: [2], half_heart_w: [2], hunter_amulet1: [3], hunter_armor1: [3], hunter_arrows1: [3], hunter_boots1: [1], hunter_boots2: [2], hunter_boots3: [2], hunter_bow1: [2], hunter_bow2: [3], hunter_gloves1: [1], hunter_hat1: [1], hunter_helm: [2], hunter_jacket1: [1], hunter_mask1: [3], hunter_pendant1: [1], hunter_ring1: [2], hunter_ring2: [3], hunter_roga1: [2], hunter_shield1: [2], hunter_sword1: [1], hunterboots: [1], hunterdagger: [2], hunterdsword: [4], huntershield2: [3], huntersword2: [4], inq_body: [9], inq_boot: [7], inq_cl: [8], inq_helm: [6], inq_weap: [12], kn_body: [6], kn_helm: [5], kn_shield: [6], kn_weap: [9], knightarmor: [6], knightboots: [5], knighthelmet: [5], knightshield: [6], knightsword: [9], koltsou: [6], kopie: [9], kwar1: [15], kwar2: [12], kwar3: [10], kwar4: [8], kwar5: [7], kwar6: [6], kwar7: [5], kwar_splo: [8], kwar_stoj: [8], kwar_takt: [8], lizard_armor: [2], lizard_boots: [2], lizard_helm: [2], mage_boots: [7], mage_cape: [6], mage_hat: [6], mage_robe: [7], mage_scroll: [8], mage_staff: [11], magewar1: [12], magewar2: [9], magewar3: [7], magewar4: [5], magewar5: [4], mart8_flowers1: [4], mart8_ring1: [5], merc_armor: [6], merc_boots: [6], merc_dagger: [6], merc_sword: [8], meshok: [2], meshok2: [2], molot_tan: [12], necr_amulet: [5], necr_helm: [5], necr_robe: [5], necr_staff: [6], necrwar1st: [14], necrwar2st: [10], necrwar3st: [6], necrwar4st: [4], necrwar5st: [2], nv_body: [7], nv_boot: [6], nv_helm: [6], nv_shield: [7], nv_weap: [10], ny_bag: [3], ny_beard: [2], ny_bell: [5], ny_candle: [4], ny_cap: [4], ny_dfur: [5], ny_fir: [7], ny_flaps: [3], ny_fur: [5], ny_furcap: [6], ny_gloves: [3], ny_horns: [3], ny_icicle: [4], ny_muff: [3], ny_rat: [4], ny_ring: [7], ny_sbag: [5], ny_sock: [4], ny_staff: [4], ny_star: [4], ny_toy: [4], paladin_armor: [8], paladin_boots: [7], paladin_bow: [8], paladin_helmet: [6], paladin_shield: [7], paladin_sword: [11], pen: [9], pen_2010y: [15], pen_2011y_clan: [15], pen_2012y: [15], pika: [9], protazan: [2], ring_of_thief: [5], rog_demon: [10], roses: [9], round_shiled: [1], ru_statue: [10], sea_trident: [7], sh_4arrows: [7], sh_amulet2: [7], sh_armor: [7], sh_boots: [4], sh_bow: [8], sh_cloak: [8], sh_helmet: [6], sh_ring1: [6], sh_ring2: [4], sh_shield: [7], sh_spear: [10], sh_sword: [10], shpaga: [10], slayersword: [11], snowflake_1: [4], snowflake_2: [6], soul_cape: [2], staff2010: [1], sword5: [5], sunart1: [7], sunart2: [9], sunart3: [11], sunart4: [12], sv_arb: [8], sv_body: [8], sv_boot: [7], sv_helm: [6], sv_shield: [7], sv_weap: [11], tact1w1_wamulet: [10], tact765_bow: [7], tactaz_axe: [11], tactcv1_armor: [9], tactdff_shield: [8], tacthapp_helmet: [8], tactmag_staff: [10], tactms1_mamulet: [10], tactpow_cloack: [9], tactsm0_dagger: [8], tactspw_mring: [7], tactwww_wring: [7], tactzl4_boots: [9], testring: [6], thief_arb: [9], thief_cape: [5], thief_fastboots: [6], thief_goodarmor: [6], thief_ml_dagger: [7], thief_msk: [5], thief_neckl: [8], thief_premiumring1: [8], thief_premiumring2: [7], thief_premiumring3: [6], thief_unique_secretops: [3], tl_medal1: [9], tl_medal2: [4], tl_medal3: [3], tm_amulet: [11], tm_arb: [12], tm_armor: [10], tm_boots: [8], tm_cape: [7], tm_knife: [11], tm_mring: [8], tm_msk: [8], tm_wring: [8], topor_skelet: [7], tunnel_kirka: [7], v_1armor: [9], ve_helm: [8], venok: [2], verb11_sword: [11], verbboots: [9], vrb_shild: [8], warmor: [6], warthief_medal1: [7], warthief_medal2: [6], warthief_medal3: [5], warthief_medal4: [4], warthief_medal5: [3], wboots: [6], welfarmor: [6], welfboots: [5], welfbow: [6], welfhelmet: [5], welfshield: [6], welfsword: [9], whelmet: [6], wolfjacket: [2], zub: [10], r_bigsword: [13], r_magy_staff: [13], r_dagger: [8], r_goodscroll: [9], r_bootsmb: [10], r_zarmor: [10], r_clck: [11], r_bow: [7], r_warriorsamulet: [11], r_m_amulet: [11], r_warring: [7], r_magicsring: [7], r_helmb: [10], tj_helmet3: [7], tj_helmet2: [9], tj_helmet1: [12], tjarmor3: [7], tjarmor2: [10], tjarmor1: [12], tj_vboots3: [7], tj_vboots2: [9], tj_vboots1: [12], necrohelm3: [9], necrohelm2: [8], necrohelm1: [4], '6ring': [5], goblin_bow: [8], orc_axe: [12], ogre_bum: [14], ogre_helm: [12], orc_hat: [8], ring2013: [3], sharik: [4], meshok_2014: [3], meshok2_2014: [3], snowjinka: [4], sosulka: [4], 'tj-shield3': [7], 'tj-shield2': [9], 'tj-shield1': [10], '7ka': [7], tjam3: [7], tjam2: [9], tjam1: [12], n_sword: [1], n_helmet: [1], n_armor: [1], n_boots: [1], n_shield: [1], n_amul: [2], n_ringd: [1], n_ringa: [1], n_clk: [1], gargoshield: [8], battlem_cape: [11], magneticarmor: [14], 'v-ring3': [5], 'v-ring2': [6], 'v-ring1': [8], wshield: [6], trinitypendant: [7], quest_pendant1: [1], dragon_crown: [5], blackring: [4], dudka: [5], windsword: [10], pegaskop: [14], elfdagger: [12], sniperbow: [8], vtjcloak3: [5], vtjcloak2: [7], vtjcloak1: [8], coldring_n: [6 + Math.floor(playerLevel / 4)], cold_sword2014: [4 + Math.floor(playerLevel / 2)], sun_armor: [1 + Math.floor(playerLevel / 2)], cold_shieldn: [5 + Math.floor(playerLevel / 4)], piratehat3: [7], piratehat2: [9], piratehat1: [12], ttring: [4], '8amul_inf': [8], vbow3: [5], vbow2: [6], vbow1: [8], pir_armor3: [7], pir_armor2: [9], pir_armor1: [12], vbolt3: [5], vbolt2: [6], vbolt1: [8], neut_amulet: [10], bshield3: [7], bshield2: [9], bshield1: [10], compass: [7], lbow: [7], ankh1: [7], obereg: [4], runkam: [4], sandglass: [3], rdagger1: [9], trogloditkop: [10], dagger_dex: [4], dagger_myf: [6], dagger16: [7], dagger20: [8], super_dagger: [7], clover_amul: [11], pn_ring1: [13], sun_ring: [6], imp_helmet: [14], imp_amul: [19], imp_ring: [17], imp_armor: [14], imp_cloak: [11], imp_crossbow: [10], imp_sword: [17], imp_boots: [15], imp_shield: [15], imp_dagger: [14], wood_sword: [1, 20.00], gnome_hammer: [2, 12.00], steel_blade: [2, 15.83], dagger: [1, 32.00], def_sword: [3, 32.98], shortbow: [1, 17.45], staff: [6, 64.50], requital_sword: [5, 64.50], broad_sword: [6, 80.33], long_bow: [4, 129.00], sor_staff: [8, 124.92], power_sword: [8, 124.76], mstaff8: [8, 98.27], ssword8: [8, 97.95], mif_staff: [9, 239.03], mif_sword: [9, 247.34], mstaff10: [9, 113.71], ssword10: [9, 110.13], energy_scroll: [6, 131.91], composite_bow: [5, 153.07], mm_staff: [10, 247.76], mm_sword: [10, 250.81], mstaff13: [10, 122.45], ssword13: [10, 122.22], bow14: [6, 156.23], ffstaff15: [11, 257.87], firsword15: [11, 257.74], smstaff16: [11, 134.73], ssword16: [11, 134.30], bow17: [7, 163.69], staff18: [12, 266.86], scroll18: [9, 155.00], sword18: [12, 267.00], leatherhat: [1, 15.00], leather_helm: [1, 21.33], knowledge_hat: [2, 39.96], chain_coif: [2, 39.27], wizard_cap: [2, 46.54], mage_helm: [4, 66.92], steel_helmet: [3, 53.61], shelm8: [3, 40.73], mif_lhelmet: [5, 76.49], mif_hhelmet: [5, 91.87], shelm12: [5, 67.90], mhelmetzh13: [6, 93.11], zxhelmet13: [6, 93.11], myhelmet15: [7, 96.03], xymhelmet15: [7, 96.44], shelm16: [7, 70.80], helmet17: [8, 108.86], mhelmet17: [8, 108.86], bravery_medal: [2, 22.88], amulet_of_luck: [2, 39.16], power_pendant: [7, 125.60], samul8: [7, 115.40], warrior_pendant: [8, 164.30], magic_amulet: [7, 171.10], wzzamulet13: [9, 169.75], mmzamulet13: [9, 169.75], smamul14: [9, 148.73], samul14: [9, 148.73], bafamulet15: [9, 169.82], mmzamulet16: [10, 172.35], wzzamulet16: [10, 172.35], samul17: [10, 154.00], smamul17: [10, 154.00], mamulet19: [11, 178.77], amulet19: [11, 178.77], leather_shiled: [1, 15.06], leatherplate: [2, 46.23], hauberk: [3, 58.42], ciras: [4, 64.99], mage_armor: [5, 91.18], mif_light: [5, 91.17], sarmor9: [5, 63.27], full_plate: [6, 125.84], wiz_robe: [7, 136.76], miff_plate: [7, 133.99], sarmor13: [7, 88.26], robewz15: [8, 135.80], armor15: [8, 135.80], sarmor16: [8, 100.95], marmor17: [9, 140.00], armor17: [9, 142.71], scoutcloack: [1, 15.50], soul_cape: [2, 40.73], antiair_cape: [3, 49.78], powercape: [4, 136.28], scloack8: [4, 69.83], antimagic_cape: [5, 101.06], wiz_cape: [7, 148.23], cloackwz15: [8, 151.02], scloack16: [8, 108.63], cloack17: [9, 161.54], round_shiled: [1, 15.71], s_shield: [2, 18.07], defender_shield: [3, 28.85], sshield5: [4, 73.70], dragon_shield: [5, 128.03], large_shield: [6, 139.67], sshield11: [6, 98.92], shield13: [7, 148.40], sshield14: [7, 105.42], shield16: [8, 150.20], sshield17: [8, 120.86], shield19: [9, 157.43], leatherboots: [1, 14.50], hunter_boots: [1, 31.03], boots2: [2, 29.91], shoe_of_initiative: [3, 60.85], steel_boots: [4, 84.39], mif_lboots: [6, 132.80], sboots9: [5, 72.73], mif_hboots: [6, 121.77], sboots12: [6, 87.29], wiz_boots: [6, 125.80], boots13: [7, 124.01], mboots14: [8, 128.73], boots15: [8, 124.84], sboots16: [8, 110.23], boots17: [9, 130.57], mboots17: [9, 130.57], i_ring: [1, 17.40], sring4: [2, 39.40], doubt_ring: [2, 90.50], verve_ring: [2, 89.44], rashness_ring: [2, 65.63], circ_ring: [4, 132.88], powerring: [4, 132.40], smring10: [5, 100.33], sring10: [5, 97.30], warriorring: [5, 170.95], darkring: [5, 171.10], magring13: [6, 174.92], warring13: [6, 174.92], bring14: [6, 176.53], wwwring16: [6, 176.54], mmmring16: [6, 176.54], smring17: [6, 102.00], sring17: [6, 98.93], ring19: [7, 183.08], mring19: [7, 184.46], flowers1: [1, 35.00], flowers2: [1, 35.00], venok: [2, 35.00], defender_dagger: [2, 93.33], flower_heart: [3, 87.50], flowers3: [4, 233.33], half_heart_m: [2, 210.00], half_heart_w: [2, 210.00], bril_pendant: [6, 490.00], bril_ring: [5, 875.00], d_spray: [5, 233.33], flowers4: [5, 210.00], flowers5: [5, 210.00], protazan: [2, 218.75], wboots: [6, 350.00], roses: [9, 218.75], goldciras: [4, 280.00], warmor: [6, 350.00], whelmet: [6, 350.00], shpaga: [10, 466.67], bfly: [5, 1050.00], koltsou: [6, 612.50], dagger_dex: [4, 121], dagger_myf: [6, 151.33], dagger16: [7, 160], dagger20: [8, 163], dring5: [4, 92], dring9: [6, 211.2], dring12: [6, 216.31], dring15: [8, 218.57], dring18: [9, 222.86], dring21: [10, 227.14] }; const unitsHealth = { peasant: [1, 4], conscript: [1, 6], archer: [1, 7], marksman: [1, 10], footman: [1, 16], squire: [1, 26], griffon: [1, 30], impergriffin: [1, 35], priest: [1, 54], inquisitor: [1, 80], cavalier: [1, 90], paladin: [1, 100], angel: [1, 180], archangel: [1, 220], brute: [101, 8], crossman: [101, 8], vindicator: [101, 23], battlegriffon: [101, 52], zealot: [101, 80], champion: [101, 100], seraph2: [101, 220], skeleton: [2, 4], skeletonarcher: [2, 4], zombie: [2, 17], plaguezombie: [2, 17], ghost: [2, 8], spectre: [2, 19], vampire: [2, 30], vampirelord: [2, 35], lich: [2, 50], archlich: [2, 55], wight: [2, 95], wraith: [2, 100], bonedragon: [2, 150], spectraldragon: [2, 160], sceletonwar: [102, 5], rotzombie: [102, 23], poltergeist: [102, 20], vampireprince: [102, 40], masterlich: [102, 55], banshee: [102, 110], ghostdragon: [102, 150], gremlin: [3, 5], mastergremlin: [3, 6], stone_gargoyle: [3, 15], obsgargoyle: [3, 20], iron_golem: [3, 18], steelgolem: [3, 24], mage: [3, 18], archmage: [3, 30], djinn: [3, 40], djinn_sultan: [3, 45], rakshasa_rani: [3, 120], rakshasa_raja: [3, 140], colossus: [3, 175], titan: [3, 190], saboteurgremlin: [103, 6], elgargoly: [103, 16], magneticgolem: [103, 28], battlemage: [103, 29], djinn_vizier: [103, 50], rakshasa_kshatra: [103, 135], stormtitan: [103, 190], pixel: [4, 5], sprite: [4, 6], dancer: [4, 12], wardancer: [4, 12], elf: [4, 10], masterhunter: [4, 14], druid: [4, 34], druideld: [4, 38], unicorn: [4, 57], silverunicorn: [4, 77], treant: [4, 175], ancienent: [4, 181], greendragon: [4, 200], emeralddragon: [4, 200], dryad_: [104, 6], winddancer: [104, 14], arcaneelf: [104, 12], ddhigh: [104, 34], pristineunicorn: [104, 80], savageent: [104, 175], crystaldragon: [104, 200], goblin: [5, 3], hobgoblin: [5, 4], wolfrider: [5, 10], wolfraider: [5, 12], orc: [5, 12], orcchief: [5, 18], ogre: [5, 50], ogremagi: [5, 65], rocbird: [5, 55], thunderbird: [5, 65], cyclop: [5, 85], cyclopking: [5, 95], behemoth: [5, 210], ancientbehemoth: [5, 250], goblinarcher: [105, 3], boarrider: [105, 14], orcrubak: [105, 20], ogrebrutal: [105, 70], firebird: [105, 65], cyclopod: [105, 100], dbehemoth: [105, 280], goblinmag: [205, 3], orcshaman: [205, 13], darkbird: [205, 60], hyenarider: [205, 13], ogreshaman: [205, 55], shamancyclop: [205, 105], cursedbehemoth: [205, 250], scout: [6, 10], assassin: [6, 14], stalker: [6, 15], maiden: [6, 16], fury: [6, 16], bloodsister: [6, 24], minotaur: [6, 31], minotaurguard: [6, 35], taskmaster: [6, 40], darkrider: [6, 40], grimrider: [6, 50], briskrider: [6, 50], hydra: [6, 80], deephydra: [6, 125], foulhydra: [6, 125], witch: [6, 80], shadow_witch: [6, 90], mistress: [6, 100], shadowdragon: [6, 200], blackdragon: [6, 240], reddragon: [6, 235], imp: [7, 4], familiar: [7, 6], horneddemon: [7, 13], hornedoverseer: [7, 13], hellhound: [7, 15], cerberus: [7, 15], succubus: [7, 20], succubusmis: [7, 30], hellcharger: [7, 50], stallion: [7, 66], pitfiend: [7, 110], pitlord: [7, 120], devil: [7, 166], archdevil: [7, 199], vermin: [107, 6], jdemon: [107, 13], hotdog: [107, 15], seducer: [107, 26], hellkon: [107, 66], pity: [107, 140], archdemon: [107, 211], defender: [8, 7], shieldguard: [8, 12], spearwielder: [8, 10], skirmesher: [8, 12], bearrider: [8, 25], blackbearrider: [8, 30], brawler: [8, 20], berserker: [8, 25], runepriest: [8, 60], runepatriarch: [8, 70], thane: [8, 100], thunderlord: [8, 120], firedragon: [8, 230], magmadragon: [8, 280], mountaingr: [108, 12], harpooner: [108, 10], whitebearrider: [108, 30], battlerager: [108, 30], runekeeper: [108, 65], flamelord: [108, 120], lavadragon: [108, 275], goblinus: [9, 3], trapper: [9, 4], fcentaur: [9, 6], ncentaur: [9, 9], warrior: [9, 12], mauler: [9, 12], shamaness: [9, 30], sdaughter: [9, 35], slayer: [9, 34], executioner: [9, 40], wyvern: [9, 90], foulwyvern: [9, 105], cyclopus: [9, 220], untamedcyc: [9, 225], goblinshaman: [109, 5], mcentaur: [109, 10], warmong: [109, 20], eadaughter: [109, 35], chieftain: [109, 48], poukai: [109, 120], bloodeyecyc: [109, 235], scorp: [10, 4], scorpup: [10, 5], duneraider: [10, 12], duneraiderup: [10, 12], shakal: [10, 24], shakalup: [10, 30], dromad: [10, 40], dromadup: [10, 45], priestmoon: [10, 50], priestsun: [10, 55], slon: [10, 100], slonup: [10, 110], anubis: [10, 160], anubisup: [10, 200] }; const perkBranchCosts = { 1: { knight_mark: 5, attack: 9, defense: 8, luck: 10, leadership: 7, dark: 8, light: 7 }, 101: { benediction: 7, defense: 10, leadership: 10, enlightenment: 8, light: 6, summon: 10, sorcery: 7 }, 2: { necr_soul: 5, defense: 11, enlightenment: 9, dark: 7, summon: 8, sorcery: 8 }, 102: { powerraise: 6, attack: 11, luck: 12, enlightenment: 8, summon: 6, sorcery: 7 }, 3: { magic_mirror: 7, enlightenment: 9, light: 10, summon: 8, destructive: 10, sorcery: 7 }, 103: { nomagicdamage: 7, attack: 8, luck: 10, leadership: 9, enlightenment: 8, destructive: 9, sorcery: 8 }, 4: { elf_shot: 7, attack: 10, defense: 9, luck: 7, leadership: 10, enlightenment: 10, light: 7, summon: 9 }, 104: { zakarrow: 4, attack: 9, defense: 8, luck: 10, leadership: 8, enlightenment: 12 }, 5: { barb_skill: 7, attack: 7, defense: 9, luck: 9, leadership: 10 }, 105: { save_rage: 6, attack: 7, defense: 8, luck: 7, leadership: 9 }, 205: { dark_blood: 5, defense: 9, luck: 10, leadership: 10, enlightenment: 8, dark: 6, sorcery: 7 }, 6: { dark_power: 7, attack: 8, luck: 9, leadership: 10, enlightenment: 10, dark: 8, destructive: 9, sorcery: 7 }, 106: { cre_master: 5, attack: 8, defense: 11, leadership: 8, luck: 10, enlightenment: 8, dark: 8 }, 7: { hellfire: 6, attack: 7, defense: 9, luck: 10, dark: 8, destructive: 10, sorcery: 8 }, 107: { consumecorpse: 5, defense: 9, enlightenment: 9, dark: 6, sorcery: 7 }, 8: { runeadv: 7, defense: 9, destructive: 11, light: 7, leadership: 9, luck: 10 }, 108: { firelord: 5, attack: 7, defense: 10, leadership: 8, luck: 8, destructive: 6, }, 9: { memoryblood: 6, attack: 7, enlightenment: 9, leadership: 9, luck: 10, defense: 9 }, 10: { dayandnight: 7, attack: 8, defense: 10, leadership: 10, light: 6, dark: 6, sorcery: 9, enlightenment: 9 } }; main(); async function main() { //battleCostAndAmmunitionPoints(); tavernAndRouletteBalances(); countExp(); birthday(); await getTalentsToHome(); if(location.pathname == "/pl_info.php") { talentsStatistics(); } calcArmyHealth(); // После загрузки навыков, если она есть, чтоб обработать навык "vitality" setTimeout(function() { const talentsChanger = document.getElementById("hwmSetsMasterSkillSetSelectedValue"); const armyChanger = document.getElementById("hwmSetsMasterArmySetSelectedValue"); if(talentsChanger) { if(location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) { observe([talentsChanger], talentsStatistics); } if(location.pathname == "/home.php" || location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) { const panels = [armyChanger]; if(location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) { panels.push(talentsChanger); } observe(panels, calcArmyHealth); } } }, 1500); // Здесь ждем загрузки hwmSetsMaster, чтоб подписаться на элемент hwmSetsMasterSkillSetSelectedValue и hwmSetsMasterArmySetSelectedValue } async function getTalentsToHome() { if(playerLevel < 5) { return; } if(location.pathname == '/home.php') { let hwmAdvancedPlayerInfoTalentsContainer = document.getElementById("hwmAdvancedPlayerInfoTalentsContainer"); if(!hwmAdvancedPlayerInfoTalentsContainer) { let homePageTalentsContainer; if(isNewPersonPage) { homePageTalentsContainer = document.querySelector("div.home_friends_block"); } else { homePageTalentsContainer = document.querySelector("body > center > table:nth-child(2) > tbody > tr:nth-child(1) > td:nth-child(1) > table > tbody > tr:nth-child(2) > td:nth-child(1) > table > tbody > tr > td > table > tbody > tr > td"); } addElement("br", homePageTalentsContainer); const ShowTalentsTitleSpan = addElement("span", homePageTalentsContainer, { id: "hwmAdvancedPlayerInfoTalentsCaptionContainer", innerHTML: ` » <b>${isEn ? "Talents" : "Навыки"}:</b><b id="hwmAdvancedPlayerInfoTalentsPointsContainer"></b>`, title: getShowTalentsTitleSpanTitle() }); ShowTalentsTitleSpan.addEventListener("click", function() { setValue("ShowTalents", !getBool("ShowTalents")); this.title = getShowTalentsTitleSpanTitle(); getTalentsToHomeCore(); }, false); addElement("br", homePageTalentsContainer); hwmAdvancedPlayerInfoTalentsContainer = addElement("div", homePageTalentsContainer, { id: "hwmAdvancedPlayerInfoTalentsContainer" }); } await getTalentsToHomeCore(); const talentsChanger = document.getElementById("hwmSetsMasterSkillSetSelectedValue"); if(talentsChanger) { observe([talentsChanger], getTalentsToHomeCore); //setTimeout(function() { observe([talentsChanger], getTalentsToHomeCore); }, 3000); } } } async function getTalentsToHomeCore() { if(location.pathname == '/home.php' && getBool("ShowTalents")) { const doc = await getRequest(`/pl_info.php?id=${PlayerId}`); const perksTable = getParent(doc.querySelector("a[href^='showperkinfo.php']"), "table", 2); if(perksTable) { Array.from(perksTable.querySelectorAll("a[href^='showperkinfo.php'] > img")).forEach(x => { x.style.width = `48px`; x.style.height = "auto"; }); //Array.from(perksTable.querySelectorAll("a[href^='showperkinfo.php'] > img")).forEach(x => { x.setAttribute("title", x.getAttribute("hint")); x.style.width = `48px`; x.style.height = "auto"; }); document.getElementById("hwmAdvancedPlayerInfoTalentsContainer").innerHTML = perksTable.outerHTML; if(typeof windowObject.hwm_hints_init === 'function') windowObject.hwm_hints_init(); talentsStatistics(); calcArmyHealth(); } } } function getShowTalentsTitleSpanTitle() { return isEn ? `Click for ${getBool("ShowTalents") ? "disable" : "enable"} talents loading` : `Нажмите для ${getBool("ShowTalents") ? "выключения" : "включения"} загрузки навыков`; } function battleCostAndAmmunitionPoints() { let left_td; let arts_td; Array.from(document.querySelectorAll('img')).forEach(x => { if(x.src.indexOf('/i/icons/attr_initiative.png') !== -1 && !left_td) { if(Array.from(x.parentNode.parentNode.parentNode.querySelectorAll('img')).length >= 7) { left_td = x.parentNode.parentNode.parentNode; } } else if(x.src.match(/\/i\/transport\/\d+\.png/) || x.src.match(/\/i\/slots_png\/slot0010.png/) || x.src.match(/\/i\/deer/)) { arts_td = x.parentNode.parentNode.parentNode; } }); if(!left_td || !arts_td) { return; } let ammunitionPointsTotal = 0; let craftTotal = 0; const unknownArts = []; let battleCostTotal = 0; let unknown_cost = false; const artsRefs = Array.from(document.querySelectorAll("div[id^=slot] a[href^='art_info.php?id=']")); artsRefs.forEach(x => { const hint = x.querySelector("img[hint]").getAttribute("hint"); const craftExec = /\[(([IDN]\d{1,2})?(E\d{1,2})?(A\d{1,2})?(W\d{1,2})?(F\d{1,2})?)\]/.exec(hint); let craftRate = 1; if(craftExec) { const craftInfo = craftExec[1]; const craftExec2 = craftInfo.match(/\d{1,2}/g); const craftSum = craftExec2.reduce((t, x) => t + parseInt(x), 0); //console.log(craftExec2) craftTotal += craftSum; craftRate += craftSum * 0.02; unknown_cost = true; //console.log(`craftInfo: ${craftInfo}, craftSum: ${craftSum}, craftRate: ${craftRate}`); } const artName = getUrlParamValue(x.href, "id"); const artInfo = artsInfo[artName]; if(artInfo) { ammunitionPointsTotal += Math.floor(artInfo[0] * craftRate); if(artInfo.length > 1) { battleCostTotal += artInfo[1]; } else { unknown_cost = true; } } else { unknownArts.push(artName); unknown_cost = true; } }); left_td.insertAdjacentHTML("beforeend", ` <tr height="23"> <td align="center"> <img title="${isEn ? "AP" : "ОА"}" src="https://dcdn.heroeswm.ru/i/icons/attr_oa.png?v=1" width="24" height="24" /> </td> <td id="unknownArtsCell" align="center"> <b>${ammunitionPointsTotal}</b> </td> </tr>`); const unknownArtsCell = document.getElementById("unknownArtsCell"); if(unknownArts.length > 0) { const text_unknown_art = isEn ? 'Arts not found: %s. Contact developer.' : "Не найдены артефакты: %s. Сообщите разработчику."; const hint = text_unknown_art.replace('%s', unknownArts.join(', ')); unknownArtsCell.insertAdjacentHTML("beforeend", ` (<a href="javascript:alert('${hint}');" title="${hint}">?</a>)`); } if(craftTotal > 0) { left_td.insertAdjacentHTML("beforeend", ` <tr height="23"> <td align="center"> <img title="${isEn ? "Craft" : "Крафт"}" src="/i/mod_common.gif" width="18" height="18" /> </td> <td align="center"> <b>${craftTotal}%</b> </td> </tr>`); } if(battleCostTotal > 0) { left_td.insertAdjacentHTML("beforeend", ` <tr height="23"> <td align="center"> <img title="${isEn ? "Cost per battle" : "Цена за бой"}" src="https://dcdn2.heroeswm.ru/i/r/48/gold.png?v=3.23de65" width="24" height="24" /> </td> <td align="center"> <b>${(Math.round(battleCostTotal) + (unknown_cost ? '+' : ''))}</b> </td> </tr>`); } } function talentsStatistics() { if(playerLevel < 5) { return; } let talentsContainer; let talentsCaptionContainer; let talentsPointsContainer; if(location.pathname == "/home.php") { talentsContainer = document.getElementById("hwmAdvancedPlayerInfoTalentsContainer"); talentsCaptionContainer = document.getElementById("hwmAdvancedPlayerInfoTalentsCaptionContainer"); talentsPointsContainer = document.getElementById("hwmAdvancedPlayerInfoTalentsPointsContainer"); } if(location.pathname == "/pl_info.php") { talentsContainer = getParent(document.querySelector("a[href^='showperkinfo.php?name=']"), "td", 3); const layerTable = getParent(talentsContainer, "table"); talentsCaptionContainer = Array.from(layerTable.rows[0].cells).find(x => x.innerHTML.includes(isEn ? "Talents" : "Навыки")).querySelector("b"); talentsPointsContainer = document.getElementById("hwmAdvancedPlayerInfoTalentsPointsContainer") || addElement("span", talentsCaptionContainer, { id: "hwmAdvancedPlayerInfoTalentsPointsContainer" }); } if(!talentsContainer || !talentsCaptionContainer) { return; } const talentBranchRows = talentsContainer.querySelectorAll(":scope > table > tbody > tr"); const playerTalentBranches = Array.from(talentBranchRows).map(x => Array.from(x.querySelectorAll("a[href^='showperkinfo.php?name=']")).map(y => getUrlParamValue(y.href, "name"))); //console.log(playerTalentBranches); let talentPoints = 0; const playerPerkBranchCosts = perkBranchCosts[playerFraction]; //console.log(playerPerkBranchCosts); for(const playerPerkBranche of playerTalentBranches) { let branchName = playerPerkBranche[0]; let firstPerkPromout = 1; if(["1", "2", "3"].includes(branchName.slice(-1))) { firstPerkPromout = parseInt(branchName.slice(-1)); branchName = branchName.slice(0, -1); } //console.log(`branchName: ${branchName}, branchCost: ${playerPerkBranchCosts[branchName]}, branchePerks: ${playerPerkBranche.length}, firstPerkPromout: ${firstPerkPromout}`); talentPoints += playerPerkBranchCosts[branchName] * (playerPerkBranche.length + firstPerkPromout - 1); } talentsPointsContainer.innerText = ` (${isEn ? "points" : "очки"} ${talentPoints} ${isEn ? "from" : "из"} ${10 + 5 * (playerLevel - 5)})`; } function calcArmyHealth() { let armyContainer; if(location.pathname == "/pl_info.php") { armyContainer = getParent(document.querySelector(".cre_creature72"), "center"); } if(location.pathname == "/home.php") { if(isNewPersonPage) { armyContainer = document.querySelector("div.home_css_creature_list"); } else { armyContainer = getParent(document.querySelector(".cre_creature72"), "center"); } } if(!armyContainer) { return; } const creatures = Array.from(document.querySelectorAll(`div.${isNewPersonPage ? "castle_creature54" : "cre_creature72"}`)).filter(x => x.querySelector("div#add_now_count")).map(x => ({ Name: getUrlParamValue(x.querySelector("a[href^='army_info.php?name=']").href, "name"), Amount: parseInt(x.querySelector("div#add_now_count").innerText) })); const hasVitality = document.querySelector("a[href='showperkinfo.php?name=vitality']") ? true : false; const sum = creatures.reduce((t, x) => { const army = unitsHealth[x.Name]; if(army) { t += x.Amount * (army[1] + (hasVitality ? 2 : 0)); } return t; }, 0); const unknownCreatures = creatures.filter(x => !unitsHealth[x.Name]); let unknownCreaturesMessage = ""; if(unknownCreatures.length > 0) { unknownCreaturesMessage = isEn ? `Creatures not found: ${unknownCreatures.map(x => x.Name).join(', ')}. Please, contact developer.` : `Существа не найдены: ${unknownCreatures.map(x => x.Name).join(', ')}. Пожалуйста, сообщите разработчику.`; } let hwmAdvancedPlayerInfoArmyHealthContainer = document.getElementById("hwmAdvancedPlayerInfoArmyHealthContainer"); if(!hwmAdvancedPlayerInfoArmyHealthContainer) { armyContainer.insertAdjacentHTML("afterend", ` » <b>${isEn ? "Total HP" : "Общее HP"}: </b><span id=hwmAdvancedPlayerInfoArmyHealthContainer>${sum}</span> <a id=hwmAdvancedPlayerInfouUknownCreaturesMessageContainer href="javascript:alert('${unknownCreaturesMessage}');" title="${unknownCreaturesMessage}"> (?)</a>`); hwmAdvancedPlayerInfoArmyHealthContainer = document.getElementById("hwmAdvancedPlayerInfoArmyHealthContainer"); } hwmAdvancedPlayerInfoArmyHealthContainer.innerText = sum; hwmAdvancedPlayerInfoArmyHealthContainer.style.color = hasVitality ? "#ff0000" : ""; const hwmAdvancedPlayerInfouUknownCreaturesMessageContainer = document.getElementById("hwmAdvancedPlayerInfouUknownCreaturesMessageContainer"); hwmAdvancedPlayerInfouUknownCreaturesMessageContainer.style.display = unknownCreaturesMessage ? "" : "none"; hwmAdvancedPlayerInfouUknownCreaturesMessageContainer.title = unknownCreaturesMessage; hwmAdvancedPlayerInfouUknownCreaturesMessageContainer.href = `javascript:alert('${unknownCreaturesMessage}');`; } function tavernAndRouletteBalances() { if(location.pathname != "/pl_info.php") { return; } // Баланс рулетки const rouletteDebitText = findChildrenTextContainsValue("td", isEn ? "Roulette bets total" : "Поставлено в рулетке"); const rouletteCreditText = findChildrenTextContainsValue("td", isEn ? "Roulette winnings total" : "Выиграно в рулетке"); if(rouletteDebitText.length == 1 && rouletteCreditText.length == 1 && rouletteDebitText[0].nextSibling.tagName.toLowerCase() == "b" && rouletteCreditText[0].nextSibling.tagName.toLowerCase() == "b") { const rouletteBalance = rouletteCreditText[0].nextSibling.innerText.replace(/,/g, "") - rouletteDebitText[0].nextSibling.innerText.replace(/,/g, ""); rouletteCreditText[0].nextSibling.insertAdjacentHTML("afterend", `<br> ${isEn ? 'Balance' : 'Баланс'}: <b>${rouletteBalance.toLocaleString()}</b>`); } // Баланс таверны var statisticsSecondCell = getParent(document.querySelector("td.wb > a[href^='pl_transfers.php?id']"), "td").nextSibling; var tavern_parent = statisticsSecondCell.querySelector("tr").parentNode.childNodes[0].childNodes[1].firstChild.firstChild.childNodes; const winsRow = tavern_parent[1]; const failsRow = tavern_parent[2]; tavern_parent[0].childNodes[1].setAttribute('style', 'white-space: nowrap;'); winsRow.childNodes[1].setAttribute('style', 'white-space: nowrap;'); //console.log(winsRow) failsRow.childNodes[1].setAttribute('style', 'white-space: nowrap;'); var tavern_0bal = winsRow.querySelector("tr"); var tavern_1bal = failsRow.querySelector("tr"); if(!tavern_0bal && !tavern_1bal) return; let wins = 0; let fails = 0; if(tavern_0bal) { wins = parseInt(winsRow.cells[1].querySelector("b").innerText.replace(/,/g, "")); tavern_0bal.childNodes[1].setAttribute('style', 'text-align: right; padding-right: 5px;'); tavern_0bal = tavern_0bal.childNodes[1].innerHTML.replace(/,/g, ""); winsRow.childNodes[3].firstChild.width = "100%"; var totalRow = winsRow.cloneNode(true); } else { tavern_0bal = 0; } if(tavern_1bal) { fails = parseInt(failsRow.cells[1].querySelector("b").innerText.replace(/,/g, "")); tavern_1bal.childNodes[1].setAttribute('style', 'text-align: right; padding-right: 5px;'); tavern_1bal = tavern_1bal.childNodes[1].innerHTML.replace(/,/g, ""); failsRow.childNodes[3].firstChild.width = "100%"; var totalRow = totalRow || failsRow.cloneNode(true); } else { tavern_1bal = 0; } var tavern_bal = tavern_0bal - tavern_1bal; totalRow.firstChild.innerHTML = ` ${isEn ? 'Balance:' : 'Баланс:'}`; totalRow.childNodes[1].innerHTML = `<b>${(wins - fails).toLocaleString()}</b>`; totalRow.childNodes[2].innerHTML = " "; totalRow.childNodes[3].innerHTML = ` <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td> <img class="rs" width="24" height="24" src="https://dcdn2.heroeswm.ru/i/r/48/gold.png?v=3.23de65" border="0" title="${isEn ? "Gold" : "Золото"}" alt=""> </td> <td style="text-align: right; padding-right: 5px;"> ${tavern_bal.toLocaleString()} </td> </tr> </tbody> </table>`; failsRow.insertAdjacentElement("afterend", totalRow); } function countExp() { if(location.pathname == '/home.php' || location.pathname == '/pl_info.php') { const cells = Array.from(document.querySelectorAll("td")); const skillInfoCell = cells.find(x => x.innerHTML.includes(isEn ? "Knight:" : "Рыцарь:") && x.innerHTML.includes(isEn ? "Enchanters' guild" : "Гильдия Оружейников") && !x.innerHTML.includes("<td")); if(!skillInfoCell) { return; } let totalSkill = 0; const regex = /\(([\d\.\,]+)\)/g; for(let i = 1; i <= 10; i++) { const skillsData = regex.exec(skillInfoCell.innerHTML); //console.log(skillsData); if(skillsData) { totalSkill += parseFloat(skillsData[1]); } } totalSkill = round00(totalSkill); const levelInfoBold = Array.from(document.querySelectorAll("td > b")).find(x => x.innerHTML.includes(isEn ? "Combat level:" : "Боевой уровень:")); const levelInfoCell = levelInfoBold.parentNode; const expRegex = /\(([\d\.\,]+)\)/g; const expExec = expRegex.exec(levelInfoCell.innerHTML); if(!expExec) { console.log("Parameters hided"); return; } const exp = parseInt(expExec[1].replace(/,/g, "")); const br = levelInfoCell.querySelector("br"); br.parentNode.insertBefore(createElement("span", { innerHTML: ` » <b>${isEn ? "Skills count" : "Сумма умений"}: </b>${totalSkill.toLocaleString()}, ${isEn ? "ratio" : "соотношение"}: <span title="${isEn ? "Expirience points to one skill point" : "Очков опыта на одно очко умения"}">${ Math.round(exp / totalSkill).toLocaleString() }</span>` }), br.nextSibling); } } function birthday() { if(location.pathname == "/pl_info.php") { const playerId = getUrlParamValue(location.href, "id"); let bifthday = GM_getValue(`PlayerBifthday${playerId}`, ""); const districtBold = Array.from(document.querySelectorAll("b")).find(x => x.innerHTML.includes(isEn ? "Location" : "Район")); districtBold.nextElementSibling.nextElementSibling.insertAdjacentHTML("afterend", ` » <b id=hwmAdvancedPlayerInfoBirthdayCaption title="${isEn ? "Click to download birthday" : "Нажмите для загрузки дня рождения"}">${isEn ? "Birthday" : "День рождения"}: </b><span id=hwmAdvancedPlayerInfoBirthday>${bifthday}</span>`); document.getElementById("hwmAdvancedPlayerInfoBirthdayCaption").addEventListener("click", loadBirthday); } } async function loadBirthday() { const playerId = getUrlParamValue(location.href, "id"); const firstProtocolPage = await getRequest(`/pl_transfers.php?id=${playerId}&page=50000`); const lines = firstProtocolPage.querySelector(`div#set_mobile_max_width > div > div`).innerHTML.split("<br>").filter(x => x != ""); bifthday = lines[lines.length - 2]; bifthday = bifthday.replace(/ /g, ""); GM_setValue(`PlayerBifthday${playerId}`, bifthday); document.getElementById("hwmAdvancedPlayerInfoBirthday").innerHTML = bifthday; } // API function getParent(element, parentType, number = 1) { if(!element) { return; } let result = element; let foundNumber = 0; while(result = result.parentNode) { if(result.nodeName.toLowerCase() == parentType.toLowerCase()) { foundNumber++; if(foundNumber == number) { return result; } } } } function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); } function findChildrenTextContainsValue(selector, value) { return Array.from(document.querySelectorAll(selector)).reduce((t, x) => { const match = Array.from(x.childNodes).filter(y => y.nodeName == "#text" && y.textContent.includes(value)); return [...t, ...match]; }, []); } function getValue(key, defaultValue) { return GM_getValue(key, defaultValue); }; function setValue(key, value) { GM_setValue(key, value); }; function deleteValue(key) { return GM_deleteValue(key); }; function getPlayerValue(key, defaultValue) { return getValue(`${key}${PlayerId}`, defaultValue); }; function setPlayerValue(key, value) { setValue(`${key}${PlayerId}`, value); }; function deletePlayerValue(key) { return deleteValue(`${key}${PlayerId}`); }; function getPlayerBool(valueName, defaultValue = false) { return getBool(valueName + PlayerId, defaultValue); } function getBool(valueName, defaultValue = false) { const value = getValue(valueName); //console.log(`valueName: ${valueName}, value: ${value}, ${typeof(value)}`) if(value) { if(typeof(value) == "string") { return value == "true"; } if(typeof(value) == "boolean") { return value; } } return defaultValue; } function round00(value) { return Math.round(value * 100) / 100; } function getParent(element, parentType, number = 1) { if(!element) { return; } let result = element; let foundNumber = 0; while(result = result.parentNode) { if(result.nodeName.toLowerCase() == parentType.toLowerCase()) { foundNumber++; if(foundNumber == number) { return result; } } } } function addElement(type, parent, data) { let el = createElement(type, data); if(parent) { parent.appendChild(el); } return el; } function createElement(type, data) { let el = document.createElement(type); if(data) { for(let key in data) { if(key == "innerText" || key == "innerHTML") { el[key] = data[key]; } else { el.setAttribute(key, data[key]); } } } return el; } function getRequest(url, overrideMimeType) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType || "text/html; charset=windows-1251", onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); }, onerror: function(error) { reject(error); } }); }); } function observe(targets, handler, config = { childList: true, subtree: true }) { targets = Array.isArray(targets) ? targets : [targets]; targets = targets.map(x => { if(typeof x === 'function') { return x(document); } return x; }); // Можем передавать не элементы, а их селекторы const ob = new MutationObserver(async function(mut, observer) { //console.log(`Mutation start`); observer.disconnect(); if(handler.constructor.name === 'AsyncFunction') { await handler(); } else { handler(); } for(const target of targets) { if(target) { observer.observe(target, config); } } }); for(const target of targets) { if(target) { ob.observe(target, config); } } }