hwmAdvancedPlayerInfo

Добавляет в инфу персов и на домашнюю: ХП армии, очки и загрузку навыков, баланс рулетки и таверны, сумму умений, день рождения персонажа

当前为 2024-01-31 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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: `&nbsp;&raquo;&nbsp;<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", `&nbsp;»&nbsp;<b>${isEn ? "Total HP" : "Общее HP"}:&nbsp;</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>&nbsp;&nbsp;${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 = `&nbsp;&nbsp;${isEn ? 'Balance:' : 'Баланс:'}`;
    totalRow.childNodes[1].innerHTML = `<b>${(wins - fails).toLocaleString()}</b>`;
    totalRow.childNodes[2].innerHTML = "&nbsp;";
    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: `&nbsp;&raquo;&nbsp;<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", `&nbsp;&raquo;&nbsp;<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(/&nbsp;/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);
        }
    }
}