IQRPG Battle Stats

Tracks various battle stats over multiple battles.

当前为 2021-12-08 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         IQRPG Battle Stats
// @namespace    https://www.iqrpg.com/
// @version      0.2
// @description  Tracks various battle stats over multiple battles.
// @author       Coastis
// @match        http://iqrpg.com/game.php
// @match        https://iqrpg.com/game.php
// @match        http://www.iqrpg.com/game.php
// @match        https://www.iqrpg.com/game.php
// @match        http://test.iqrpg.com/game.php
// @match        https://test.iqrpg.com/game.php
// @require      http://code.jquery.com/jquery-latest.js
// @grant        GM_addStyle
// ==/UserScript==

//TODO add persistant storage between browser sessions
//TODO const track_abyss_battles = false; // to track abyss battles or not - Abyssal

///////////////////////////////////
/////////// config ////////////////
///////////////////////////////////

const track_boss_battles = false; // true or false
const track_clan_battles = false; // true or false

//////////////////////////////////////////////////////////////////
/////////// Don't change anything below this line ////////////////
//////////////////////////////////////////////////////////////////

/* globals jQuery, $ */

// init
var player_stats = { dmg:0, hits:0, misses:0 }; //TODO update from local storage
var enemy_stats = { dmg:0, hits:0, misses:0, dodges:0 }; //TODO update from local storage
var player_cache = '';
var enemy_cache = '';

// run every xxx ms updating stuffs
setInterval(iqrpgbs_loop, 100);

// main loop
function iqrpgbs_loop() {

    var we_battling = false;
    var display_needs_update = false;

    // check we're on the battle page
    if(document.getElementsByClassName("battle-container").length > 0) we_battling = true;

    // and not in a boss battle - Boss Tokens
    if(track_boss_battles!==true) {
        if($("div.game-grid > div.main-game-section > div.main-section__body:contains('Boss Tokens')").length > 0) {
            //console.log("skipping boss fight");
            return false;
        }
    }

    // and not in a dragon battle or clan battle - Clan Exp
    if(track_clan_battles!==true) {
        if($("div.game-grid > div.main-game-section > div.main-section__body:contains('Clan Exp')").length > 0) {
            //console.log("skipping clan fight");
            return false;
        }
    }

    // and not in a dungeon - Dungeoneering Exp
    if($("div.game-grid > div.main-game-section > div.main-section__body:contains('Dungeoneering Exp')").length > 0) {
        return false;
    }

    // all good
    if(we_battling === true) {

        // Add the battle stat panel to dom, if not already there
        if(!document.getElementById("iqrpgbs_bs_panel")) {
            var iqrpg_body = $( "div.game-grid > div.main-game-section > div.main-section__body" );
            iqrpg_body[0].children[0].children[0].insertAdjacentHTML('beforeend', render_battle_stats_panel() );
            document.getElementById('igrpg_bs_reset').addEventListener('click', iqrpg_bs_reset_stats, false);
        }

        // get the players stat line & compare it to previous stored stats
        var player_sl = $("div.game-grid > div.main-game-section > div.main-section__body > div > div > div > div:nth-child(2)");
        if(player_sl.prop('innerHTML') !== player_cache) {
            player_cache = player_sl.prop('innerHTML');
            parse_player_stat_line(player_sl);
            display_needs_update = true;
        }

        // get the mobs stat line & compare it to previous stored stats
        var mobs_sl = $("div.game-grid > div.main-game-section > div.main-section__body > div > div > div > div:nth-child(3)");
        if(mobs_sl.prop('innerHTML') !== enemy_cache) {
            enemy_cache = mobs_sl.prop('innerHTML');
            parse_enemy_stat_line(mobs_sl);
            display_needs_update = true;
        }

        // update displayed values
        if(display_needs_update === true) {
            update_display();
        }

    }
}

function parse_player_stat_line(player_sl) {
    var hits = player_sl.find("p:nth-child(1) > span:nth-child(2)");
    if(hits.length > 0) {
        var actual_hits = hits.prop('innerHTML').replaceAll(" time(s)", "");
        player_stats.hits += parseInt(actual_hits);
    }
    var dmg = player_sl.find("p:nth-child(1) > span:nth-child(3)");
    if(dmg.length > 0 && hits.length > 0) {
        var actual_dmg = dmg.prop('innerHTML').replaceAll(" damage", "").replaceAll(",", "");
        player_stats.dmg += parseInt(actual_dmg) * parseInt(actual_hits);
    }
    var misses = player_sl.find("p:nth-child(2) > span:nth-child(1)");
    if(misses.length > 0) {
        var actual_misses = misses.prop('innerHTML').replaceAll(" time(s)", "");
        player_stats.misses += parseInt(actual_misses);
    }
}

function parse_enemy_stat_line(stat_line) {
    var hits = stat_line.find("p:nth-child(1) > span:nth-child(2)");
    if(hits.length > 0) {
        var actual_hits = hits.prop('innerHTML').replaceAll(" time(s)", "");
        enemy_stats.hits += parseInt(actual_hits);
    }
    var dmg = stat_line.find("p:nth-child(1) > span:nth-child(3)");
    if(dmg.length > 0 && hits.length > 0) {
        var actual_dmg = dmg.prop('innerHTML').replaceAll(" damage", "").replaceAll(",", "");
        enemy_stats.dmg += parseInt(actual_dmg) * parseInt(actual_hits);
    }
    var misses = stat_line.find("p:nth-child(2) > span:nth-child(2)");
    if(misses.length > 0) {
        var actual_misses = misses.prop('innerHTML').replaceAll(" time(s)", "");
        enemy_stats.misses += parseInt(actual_misses);
    }
    var dodges = stat_line.find("p:nth-child(2) > span:nth-child(3)");
    if(dodges.length > 0) {
        var actual_dodges = dodges.prop('innerHTML').replaceAll(" attack(s)", "");
        enemy_stats.dodges += parseInt(actual_dodges);
    }
    //console.log("hits :: "+hits);
    //console.log("misses :: "+actual_misses);
    //console.log(actual_dodges);
}

function iqrpg_bs_reset_stats() {
    player_stats.dmg = 0;
    player_stats.hits = 0;
    player_stats.misses = 0;
    enemy_stats.dmg = 0;
    enemy_stats.hits = 0;
    enemy_stats.misses = 0;
    enemy_stats.dodges = 0;
    update_display();
}

function update_display() {
    // players
    $("#iqrpgbs_pl_dmg").html(new Intl.NumberFormat().format(player_stats.dmg));
    $("#iqrpgbs_pl_hits").html(new Intl.NumberFormat().format(player_stats.hits));
    var avg = Math.round(player_stats.dmg / player_stats.hits);
    if(isNaN(avg)) avg = 0;
    $("#iqrpgbs_pl_avg").html(new Intl.NumberFormat().format(avg));
    var acc = (player_stats.hits / (player_stats.hits + player_stats.misses))*100;
    if(isNaN(acc)) acc = 0;
    $("#iqrpgbs_pl_acc").html(new Intl.NumberFormat().format(acc.toFixed(2)));
    // enemy
    var enemy_avg = Math.round(enemy_stats.dmg / enemy_stats.hits);
    if(isNaN(enemy_avg)) enemy_avg = 0;
    $("#iqrpgbs_enmy_avg").html(new Intl.NumberFormat().format(enemy_avg));
    var enemy_acc = ( (enemy_stats.hits + enemy_stats.dodges) / (enemy_stats.hits + enemy_stats.misses + enemy_stats.dodges))*100;
    if(isNaN(enemy_acc)) enemy_acc = 0;
    $("#iqrpgbs_enmy_acc").html(new Intl.NumberFormat().format(enemy_acc.toFixed(2)));
    var enemy_dodges = (enemy_stats.dodges / (enemy_stats.hits /*+ enemy_stats.misses*/ + enemy_stats.dodges))*100;
    if(isNaN(enemy_dodges)) enemy_dodges = 0;
    $("#iqrpgbs_enmy_dodges").html(new Intl.NumberFormat().format(enemy_dodges.toFixed(2)));
}

function render_battle_stats_panel() {
    var content = `
<div id="iqrpgbs_bs_panel" class="margin-top-large">
<div>Battle Stats <span>by Coastis</span></div>
<div>You dealt a total of <span id="iqrpgbs_pl_dmg">0</span> damage in <span id="iqrpgbs_pl_hits">0</span> hits,
with an average of <span id="iqrpgbs_pl_avg">0</span> per hit and <span id="iqrpgbs_pl_acc">0</span>% accuracy</div>
<div>Enemy dealt an average of <span id="iqrpgbs_enmy_avg">0</span> per hit
with an accuracy of <span id="iqrpgbs_enmy_acc">0</span>%, and you dodged <span id="iqrpgbs_enmy_dodges">0</span>% of attacks</div>
<div>[<a href=#" id="igrpg_bs_reset">Reset Battle Stats</a>]</div>
</div>
`;
    return content;
}

GM_addStyle ( `
    div#iqrpgbs_bs_panel div { text-align:center;padding:1px;}
    div#iqrpgbs_bs_panel div:nth-child(1) { font-weight:bold;}
    div#iqrpgbs_bs_panel div:nth-child(1) span { font-size:8px;font-weight:normal;}
` );