Macro Combat Compacter

Compacts the divisions shown when using fight macros in KoL, displaying only the last.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name           Macro Combat Compacter
// @namespace      kol.interface.unfinished
// @description    Compacts the divisions shown when using fight macros in KoL, displaying only the last.
// @include        http://*kingdomofloathing.com/fight.php*
// @include        http://127.0.0.1:*/fight.php*
// @version        1.21
// @grant          GM_getValue
// @grant          GM_setValue
// ==/UserScript==

//Version 1.21
// - add @grant
//Version 1.2
// - added round counter and attack/defense notice compaction
//Version 1.1
// - also now shows effect gains/losses
//Version 1.0

function compact() {
    var hrs = document.evaluate( '//hr', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
    var stuff = [];
    var ids = 1;
	extractAdjustments(hrs.snapshotLength);
    // gather contents
    for (var i=hrs.snapshotLength-1;i>=0;i--) {
        var hr2 = hrs.snapshotItem(i);
        var itemids = "";
        stuff[i] = document.createElement('div');
        stuff[i].setAttribute('class','compactDiv');
        while (hr2.previousSibling && hr2.previousSibling.tagName!='HR' && hr2.previousSibling.tagName!='BR') {
            var n = hr2.previousSibling;
            n.parentNode.removeChild(n);
            if (stuff[i].firstChild)
                stuff[i].insertBefore(n,stuff[i].firstChild);
            else
                stuff[i].appendChild(n);
        }
        stuff[i].setAttribute('style','display:none'); 
        hr2.parentNode.insertBefore(stuff[i],hr2);
        hr2.addEventListener('click',expandDivH,true);
        hr2.setAttribute('title','click to display round '+(i+1));
        var r = findAcquires(stuff[i]);
        if (r.length>0) {
            for (var j=0;j<r.length;j++) {
                itemids = itemids + " " + ids;
                r[j].setAttribute('id','compactAcquire_'+ids);
                ids++;
                stuff[i].parentNode.insertBefore(r[j],stuff[i]);
            }
            stuff[i].setAttribute('compactAcquire',itemids);
        }
    }
}

// delete any duplicated item/meat acquisitions
function removeAcquires(alist) {
    var aa = alist.split(' ');
    for (var i=0;i<aa.length;i++) {
        if (aa[i]) {
            var r = document.getElementById('compactAcquire_'+aa[i]);
            if (r) {
                r.parentNode.removeChild(r);
            }
        }
    }
    
}

// expand a single div and delete any item/meat acquisitions
function expandDiv(d) {
    var s = d.getAttribute("style");
    if (s.match(/display\s*:\s*none\s*;?/i)) {
        d.setAttribute("style",s.replace(/display\s*:\s*none\s*;?/i,''));
        var itemlist = d.getAttribute('compactAcquire');
        if (itemlist) {
            removeAcquires(itemlist);
        }
    }
}

// handler for introduced divs
function expandDivH() {
    var d = this.previousSibling;
    if (d && d.tagName=='DIV') {
        expandDiv(d);
    }
    this.removeEventListener('click',expandDivH,true);
}

// expand all divs handler
function expandAllDivs(e) {
    var ds = document.getElementsByClassName('compactDiv');
    if (ds) {
        for (var i=0;i<ds.length;i++) {
            expandDiv(ds[i]);
        }
    }
}

// change the jump to bottom button to an expand all rounds button
function addExpandAll() {
    var b = document.getElementById('jumptobot');
    b.addEventListener('click',expandAllDivs,false);
    b.setAttribute('title','click to expand all rounds');
    b.innerHTML = '(expand rounds)';
}

// return clones of all item/meat acquisitions from the supplied root element
function findAcquires(doc) {
    var r = [];
    var msg = ['.//td[text()="You acquire an item: "]',
               './/td[text()="You acquire an effect: "]',
               './/td[text()="You lose an effect: "]'];

    for (var m=0;m<msg.length;m++) {
        var ps = document.evaluate(msg[m],doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
        if (ps.snapshotLength>0) {
            for (var i=0;i<ps.snapshotLength;i++) {
                var p = ps.snapshotItem(i).parentNode;
                while (p && p.tagName!='CENTER')
                    p = p.parentNode;
                if (p) {
                    r[r.length] = p.cloneNode(true);
                }
            }
        }
    }
    ps = document.evaluate('.//td[contains(text(),"Meat.")]',doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
    if (ps.snapshotLength>0) {
        for (var i=0;i<ps.snapshotLength;i++) {
            var p = ps.snapshotItem(i);
            if (p.innerHTML && p.innerHTML.match(/You gain [0-9]+ Meat./)) {
                p = p.parentNode;
                while (p && p.tagName!='CENTER')
                    p = p.parentNode;
                if (p) {
                    r[r.length] = p.cloneNode(true);
                }
            }
        }
    }
    return r;
}

function accumulateTitle(n,text) {
	if (n.nodeType==3) n = n.parentNode;
    var t = n.getAttribute('title');
    if (t) {
        n.setAttribute('title',t+'  '+text);
    } else
        n.setAttribute('title',text);
}

function hideAtkDef(p) {
	p.parentNode.removeChild(p);
}

function extractAdjustments(extrar) {
    var atk=Number(GM_getValue('atk',0)),def=Number(GM_getValue('def',0));
    var delta=0,deltd=0;
    var r=Number(GM_getValue('round',0))+extrar;
    var psa = document.evaluate('.//td[contains(text(),"Monster attack power reduced by ")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
    for (var ia=0;ia<psa.snapshotLength;ia++) {
        var p = psa.snapshotItem(ia);
        var delt = Number(p.innerHTML.replace(/[^0-9]+/g,''));
        delta += delt;
        p = p.parentNode;
        while (p && p.tagName!='CENTER')
            p = p.parentNode;
        if (p) {
            if (p.previousSibling) 
                accumulateTitle(p.previousSibling,'Monster attack power reduced by '+delt+'.');
			hideAtkDef(p);
        }
    }
    psa = document.evaluate('.//td[contains(text(),"Monster defense reduced by ")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
    for (var ia=0;ia<psa.snapshotLength;ia++) {
        var p = psa.snapshotItem(ia);
        var delt = Number(p.innerHTML.replace(/[^0-9]+/g,''));
        deltd += delt;
        p = p.parentNode;
		while (p && p.tagName!='CENTER')
			p = p.parentNode;
		if (p) {
            if (p.previousSibling) {
                accumulateTitle(p.previousSibling,'Monster defense reduced by '+delt+'.');
			}
			hideAtkDef(p);
		}
    }
    r++;
    GM_setValue('round',r);
    atk += delta;
    def += deltd;
    if (atk!=0 || def!=0 || r>1) {
        var d = document.getElementById('compactatkdef');
        var ps;
        if (!d) {
            ps = document.evaluate('.//td/b[text()="Combat!"]',document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
            if (ps.singleNodeValue) {
                d = document.createElement('div');
                d.setAttribute('style','display:inline;float:left;font-size:small;');
                d.setAttribute('id','compactatkdef');
                ps.singleNodeValue.parentNode.insertBefore(d,ps.singleNodeValue);
            } else
                return;
        }
        GM_setValue('atk',atk);
        GM_setValue('def',def);
        if (delta!=0 || deltd!=0) {
            d.setAttribute('title','Round '+r+':  monster attack reduced by '+delta+' and defense by '+deltd+'.');
        } else {
            d.setAttribute('title','Round '+r+'.');
        }
        var c = (r>1) ? '\u00A0('+r+') ' : '\u00A0';
		if (atk>0) c = c + 'A: -'+atk+' ';
		if (def>0) c = c + 'D: -'+def;
        if (d.firstChild)
            d.replaceChild(document.createTextNode(c),d.firstChild);
        else 
            d.appendChild(document.createTextNode(c));
    }
}

if (window.location.search && window.location.search.indexOf('ireallymeanit')>=0) {
    GM_setValue('atk',0);
    GM_setValue('def',0);
    GM_setValue('round',0);
} else if (document.evaluate('.//p[text()="It gets the jump on you."]',document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue) {
    GM_setValue('atk',0);
    GM_setValue('def',0);
    GM_setValue('round',0);
}

if (document.getElementById('jumptobot')) {
    compact();
    addExpandAll();
} else {
	extractAdjustments(0);
}