ET Battle CD Tracker

Displays each player's cooldowns during battle. Settings available in console via window.et_battleCd

目前為 2017-10-25 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ET Battle CD Tracker
// @namespace    http://tampermonkey.net/
// @version      0.6
// @description  Displays each player's cooldowns during battle. Settings available in console via window.et_battleCd
// @author       Aes Sedai
// @match        http*://*.eternitytower.net/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    $("<style type='text/css'> .cd-container > div { display: flex; align-items: center; } .cd-container > div > p { padding-left: 8px; margin-bottom: 0;} </style>").appendTo("head");

    // Default settings, use window.et_battleCd in console to change settings
    window.et_battleCd = {
        hideOwnCds: true,
        hideReadyCds: true,
    };

    if(localStorage.getItem('et_battleCd')) window.et_battleCd = Object.assign({}, window.et_battleCd, JSON.parse(localStorage.getItem('et_battleCd')));

    $(window).on("beforeunload", function() {
        localStorage.setItem('et_battleCd', JSON.stringify(window.et_battleCd));
    });

    var userId = Meteor.userId();

    function getAbilityName(ability) {
        if(ability.id === "attack_up") return "attack";
        if(ability.id === "accuracy_up") return "accuracy";
        if(ability.id === "defense_up") return "defense";
        if(ability.id === "health_up") return "health";
        return ability.id.split("_").map(function(s, idx) {
            if(idx > 0) {
                return s.charAt(0).toUpperCase() + s.slice(1);
            } else return s;
        }).join('');
    }

    function isPassiveAbility(ability) {
        if(ability.id === "attack_up") return true;
        if(ability.id === "accuracy_up") return true;
        if(ability.id === "defense_up") return true;
        if(ability.id === "health_up") return true;
        if(ability.id === "poisoned_blade") return true;
        if(ability.id === "thirsty_fangs") return true;
        if(ability.id === "phantom_strikes") return true;
        return false;
    }

    function addAbilityContainer(unit, ability) {
        if($("[data-"+ability.id+"='"+unit.id+"']").length === 0) {
            var abilityContainer = document.createElement("div");
            abilityContainer.dataset[ability.id] = unit.id;
            var abilityImg = document.createElement("img");
            abilityImg.src = "/icons/"+getAbilityName(ability)+".svg";
            abilityImg.className = "small-icon icon-box";
            abilityContainer.append(abilityImg);
            abilityContainer.append(document.createElement("p"));
            var cdContainer = $("[data-cd-container="+unit.id+"]");
            cdContainer.append(abilityContainer);
        }
    }

    function addUnitCds(unit) {
        if(unit.id === userId && window.et_battleCd.hideOwnCds) return;

        // ensure unit exists first
        var interval = setInterval(function() {
            if ($('img#' + unit.id).length > 0) {
                var unitElem = $('img#' + unit.id);
                if($("[data-cd-container='"+ unit.id +"']").length === 0) {
                    var cdContainer = document.createElement("div");
                    cdContainer.className = "cd-container";
                    cdContainer.dataset.cdContainer = unit.id;
                    var parentElem = unitElem.closest(".flex-column").parent();
                    parentElem.append(cdContainer);
                    unit.abilities.forEach(function(ability) {
                        if(!isPassiveAbility(ability)) addAbilityContainer(unit, ability);
                    });
                }
                clearInterval(interval); // here interval is undefined, but when we call this function it will be defined in this context
            }
        }, 50);
    }

    function updateUnitCds(unit) {
        if(unit.id === userId && window.et_battleCd.hideOwnCds) return;

        unit.abilities.forEach(function(ability) {
            var abilityContainer = $("[data-"+ability.id+"='"+unit.id+"']");
            if(abilityContainer.length > 0) {
                if(window.et_battleCd.hideReadyCds && ability.currentCooldown <= 0) {
                    abilityContainer.remove();
                } else {
                    var abilityCd = abilityContainer.find("p");
                    abilityCd.html(ability.currentCooldown < 0 ? "0 s" : ability.currentCooldown.toString().split('.')[0] + " s");
                }
            } else {
                if(ability.currentCooldown > 0 && !isPassiveAbility(ability)) addAbilityContainer(unit, ability);
            }
        });
    }

    function removeUnitCds(unit) {
        var cdContainer = $("[data-cd-container='"+unit.id+"']");
        cdContainer.remove();
    }

    Meteor.connection._stream.on("message", function(json) {
        var message = JSON.parse(json);
        if(message.msg == "changed" && message.collection == "redis" &&  message.id.includes("battles-")) {
            // per-tick updates
            var battleState = JSON.parse(message.fields.value);
            battleState.units.forEach(function(unit) {
                addUnitCds(unit);
                updateUnitCds(unit);
            });
            battleState.deadUnits.forEach(function(unit) {
                removeUnitCds(unit);
            });
        } else if(message.msg == "removed" && message.collection == "redis" &&  message.id.includes("battles-")) {
            // cleanup
            // $(".cd-container").remove();
        }
    });
})();