hwmAdvancedPlayerInfo

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

目前為 2024-01-31 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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);
        }
    }
}