Mage Example Script - lordachoo/adventureland GitHub Wiki

Mage Example Code Description

  • Has attack_mode default crap + move_mode, debug mode
    • Move mode will force bot to be stationary so they don't go wandering off
    • debug toggles console.log messages
  • Basic potion function use_potions() - set potionHealAmount and potionManaAmount so extra potion capacity isn't wasted.
  • Basic functionality, looks for targets - checks if it can cast burst - casts it if it can.
  • Has the party code for LordAchoo, LordAsneeze, LordApriest to always create/maintain group
  • Has the UI Trackers on for DPS, Gold/H, EXP/s Etc

Code

var attack_mode=true
var move_mode=false

async function use_potions() {
	var potionHealAmount=200
	var potionManaAmount=300
if (character.hp < character.max_hp - potionHealAmount || character.mp < character.max_mp - potionManaAmount) {
				set_message("Using Potion");
                use_hp_or_mp();
            }   
}

setInterval(function(){

	use_potions();
	loot();

	if(!attack_mode || character.rip || is_moving(character)) return;

	var target=get_targeted_monster();
	if(!target)
	{
		target=get_nearest_monster({min_xp:100,max_att:120});
		if(target) change_target(target);
		else
		{
			set_message("No Monsters");
			return;
		}
	}
	
	if(!is_in_range(target))
	{
		if(move_mode) {
		set_message("MOVING...");
		move(
			character.x+(target.x-character.x)/2,
			character.y+(target.y-character.y)/2
			);
		}
		// Walk half the distance - IF move_mode == true
	}
	else if(can_attack(target))
	{
		set_message("Attacking");
		attack(target);
		
		if(!is_on_cooldown("burst") && character.mp > 499)
		{
		set_message("BURST, 500");
		use_skill("burst");
		}
		
	}

},1000/4); // Loops every 1/4 seconds.

/////////////////////////////////////////////
/*
* UI ELEMENTS (CROWN)
*/

var startTime = new Date();
var sumGold = 0;
var largestGoldDrop = 0;
setInterval(function() {
	update_goldmeter();
}, 400);

function init_goldmeter() {
  let $ = parent.$;
  let brc = $('#bottomrightcorner');
  brc.find('#goldtimer').remove();
  let xpt_container = $('<div id="goldtimer"></div>').css({
    fontSize: '25px',
    color: 'white',
    textAlign: 'center',
    display: 'table',
    overflow: 'hidden',
    marginBottom: '-5px',
	width: "100%"
  });
  //vertical centering in css is fun
  let xptimer = $('<div id="goldtimercontent"></div>')
    .css({
      display: 'table-cell',
      verticalAlign: 'middle'
    })
    .html("")
    .appendTo(xpt_container);
  brc.children().first().after(xpt_container);
}

function updateGoldTimerList(){
	let $ = parent.$;
	var gold = getGold();
	var goldString = "<div>" + gold.toLocaleString('en') + " Gold/Hr" + "</div>"; 
	goldString += "<div>" + largestGoldDrop.toLocaleString('en') + " Largest Gold Drop</div>";
	$('#' + "goldtimercontent").html(goldString).css({
    background: 'black',
	backgroundColor: 'rgba(0, 0, 0, 0.7)', // Add a background color
    border: 'solid gray',
    borderWidth: '5px 5px',
    height: '50px',
    lineHeight: '25px',
    fontSize: '25px',
    color: '#FFD700',
    textAlign: 'center',
  });
}

function update_goldmeter() {
	updateGoldTimerList();
}

init_goldmeter();

function getGold(){
	var elapsed = new Date() - startTime;
	var goldPerSecond = parseFloat(Math.round((sumGold/(elapsed/1000)) * 100) / 100);
	return parseInt(goldPerSecond * 60 * 60);
}

function trackLargestGoldDrop(gold) {
  if (gold > largestGoldDrop) {
    largestGoldDrop = gold;
  }
}

//Clean out any pre-existing listeners
if (parent.prev_handlersgoldmeter) {
    for (let [event, handler] of parent.prev_handlersgoldmeter) {
      parent.socket.removeListener(event, handler);
    }
}
parent.prev_handlersgoldmeter = [];

function register_goldmeterhandler(event, handler) {
    parent.prev_handlersgoldmeter.push([event, handler]);
    parent.socket.on(event, handler);
};

function goldMeterGameResponseHandler(event){
	if(event.response == "gold_received"){
		var gold = event.gold;
		sumGold += gold;
		trackLargestGoldDrop(gold);
	}
}

function goldMeterGameLogHandler(event){
	if(event.color == "gold"){
		var gold = parseInt(event.message.replace(" gold", "").replace(",", ""));
		sumGold += gold;
		trackLargestGoldDrop(gold);
	}
}

register_goldmeterhandler("game_log", goldMeterGameLogHandler);
register_goldmeterhandler("game_response", goldMeterGameResponseHandler);

////////////////////////////////////////////////////////////////////

// Initialize the DPS meter
function initDPSMeter(minref) {
    let $ = parent.$;
    let brc = $('#bottomrightcorner');

    // Remove any existing DPS meter
    brc.find('#dpsmeter').remove();

    // Create a container for the DPS meter with styling
    let dpsmeter_container = $('<div id="dpsmeter"></div>').css({
        fontSize: '20px',
        color: 'white',
        textAlign: 'center',
        display: 'table',
        overflow: 'hidden',
        marginBottom: '-3px',
        width: '100%',
        backgroundColor: 'rgba(0, 0, 0, 0.5)', // Add a background color
    });

    // Create a div for vertical centering in CSS
    let xptimer = $('<div id="dpsmetercontent"></div>')
        .css({
            display: 'table-cell',
            verticalAlign: 'middle',
            backgroundColor: 'rgba(0, 0, 0, 0.5)', // Add a background color
            padding: '5px', // Add padding for better visibility
            border: '5px solid grey', // Add a border for better visibility
        })
        .html("")
        .appendTo(dpsmeter_container);

    // Insert the DPS meter container after the first child of bottomrightcorner
    brc.children().first().after(dpsmeter_container);
}

// Initialize your variables
var damage = 0;
var burnDamage = 0;
var blastDamage = 0;
var baseDamage = 0;
var baseHeal = 0;
var METER_START = performance.now(); // Record the start time for DPS calculation

// Damage tracking object for party members
var partyDamageSums = {};

// Function to format DPS with commas for better readability
function getFormattedDPS(dps) {
    try {
        return dps.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    } catch (error) {
        console.error('An error occurred while formatting DPS:', error);
        return 'N/A';
    }
}

// Register the hit event handler
parent.socket.on("hit", function (data) {
    try {
        if (data.hid) {
            // Update DPS data for the character and party members
            let targetId = data.hid;

            // Check if the target is in the party
            if (parent.party_list && Array.isArray(parent.party_list) && parent.party_list.includes(targetId)) {
                let entry = partyDamageSums[targetId] || {
                    startTime: performance.now(),
                    sumDamage: 0,
                    sumHeal: 0,
                    sumBurnDamage: 0,
                    sumBlastDamage: 0,
                    sumBaseDamage: 0,
                };

                if (targetId == character.id) {
                    // Update the character's damage values
                    entry.sumDamage += data.damage || 0;
                    entry.sumHeal += data.heal || 0;

                    if (data.source == "burn") {
                        entry.sumBurnDamage += data.damage;
                    } else if (data.splash) {
                        entry.sumBlastDamage += data.damage;
                    } else {
                        entry.sumBaseDamage += data.damage || 0;
                    }
                } else {
                    // Update party member's damage values
                    entry.sumDamage += data.damage || 0;
                    entry.sumHeal += data.heal || 0;

                    if (data.source == "burn") {
                        entry.sumBurnDamage += data.damage;
                    } else if (data.splash) {
                        entry.sumBlastDamage += data.damage;
                    } else {
                        entry.sumBaseDamage += data.damage || 0;
                    }
                }

                partyDamageSums[targetId] = entry;
            }
        }
    } catch (error) {
        console.error('An error occurred in the hit event handler:', error);
    }
});

// Update the DPS meter display
// Update the DPS meter display
function updateDPSMeterUI() {
    try {
        // Calculate elapsed time since DPS meter start
        let ELAPSED = performance.now() - METER_START;

        // Calculate DPS for different damage types
        let dps = Math.floor((damage * 1000) / ELAPSED);
        let burnDps = Math.floor((burnDamage * 1000) / ELAPSED);
        let blastDps = Math.floor((blastDamage * 1000) / ELAPSED);
        let baseDps = Math.floor((baseDamage * 1000) / ELAPSED);
        let hps = Math.floor((baseHeal * 1000) / ELAPSED);

        let $ = parent.$;
        let dpsDisplay = $('#dpsmetercontent');

        // Check if the DPS display element exists
        if (dpsDisplay.length === 0) {
            console.warn('DPS display element not found.');
            return;
        }

        let listString = '<div>Crowns Damage Meter</div>';
        listString += '<table border="1" style="width:100%">';

        // Header row start with damage types horizontally
        listString += '<tr><th></th>';
        for (const type of ["Base", "Blast", "Burn", "HPS", "DPS"]) {
            listString += `<th>${type}</th>`;
        }
        listString += '</tr>';

        // Rows for each player with character names vertically
        for (let id in partyDamageSums) {
            const player = get_player(id);
            if (player) {
                listString += '<tr>';
                listString += `<td>${player.name}</td>`;
                
                for (const type of ["Base", "Blast", "Burn", "HPS", "DPS"]) {
                    const entry = partyDamageSums[id];
                    const value = getTypeValue(type, entry);
                    listString += `<td>${getFormattedDPS(value)}</td>`;
                }

                listString += '</tr>';
            }
        }

        // Add a row for Total DPS with colspan
        listString += '<tr><td>Total DPS</td>';
        for (const type of ["Base", "Blast", "Burn", "HPS", "DPS"]) {
            let typeTotalDPS = 0;

            for (let id in partyDamageSums) {
                const entry = partyDamageSums[id];
                const value = getTypeValue(type, entry);
                typeTotalDPS += value;
            }

            if (type === "DPS") {
                listString += `<td colspan="${Object.keys(partyDamageSums).length}">${getFormattedDPS(typeTotalDPS)}</td>`;
            } else {
                listString += `<td>${getFormattedDPS(typeTotalDPS)}</td>`;
            }
        }
        listString += '</tr>';

        listString += '</table>'; // Table end

        // Update the existing content instead of creating new content
        dpsDisplay.html(listString);
    } catch (error) {
        console.error('An error occurred while updating the DPS meter UI:', error);
    }
}

// Function to get the value for a specific damage type
function getTypeValue(type, entry) {
    switch (type) {
        case "DPS":
            return calculateDPSForPartyMember(entry);
        case "Burn":
            return entry ? Math.floor((entry.sumBurnDamage * 1000) / (performance.now() - entry.startTime)) : 0;
        case "Blast":
            return entry ? Math.floor((entry.sumBlastDamage * 1000) / (performance.now() - entry.startTime)) : 0;
        case "Base":
            return entry ? Math.floor((entry.sumBaseDamage * 1000) / (performance.now() - entry.startTime)) : 0;
        case "HPS":
            return entry ? Math.floor((entry.sumHeal * 1000) / (performance.now() - entry.startTime)) : 0;
        default:
            return 0;
    }
}

// Calculate DPS for a specific party member
function calculateDPSForPartyMember(entry) {
    try {
        const elapsedTime = performance.now() - (entry && entry.startTime || performance.now());
        const totalDamage = entry && entry.sumDamage || 0;
        return Math.floor((totalDamage * 1000) / elapsedTime);
    } catch (error) {
        console.error('An error occurred while calculating DPS for a party member:', error);
        return 0;
    }
}

// Initialize the DPS meter
initDPSMeter();

// Function to be called at regular intervals for updating the DPS meter UI
function updateDPSMeterInterval() {
    try {
        // Update the DPS meter UI
        updateDPSMeterUI();
    } catch (error) {
        console.error('An error occurred while updating the DPS meter at the interval:', error);
    }
}

// Start updating the DPS meter UI at regular intervals
setInterval(updateDPSMeterInterval, 250);

//////////////////////////////////////////////////////

setInterval(function () {
  update_xptimer();
}, 1000 / 4);

var minute_refresh;

function init_xptimer(minref) {
  minute_refresh = minref || 1;
  parent.add_log(minute_refresh.toString() + ' min until tracker refresh!', 0x00FFFF);
  let $ = parent.$;
  let brc = $('#bottomrightcorner');
  brc.find('#xptimer').remove();
  let xpt_container = $('<div id="xptimer"></div>').css({
    background: 'black',
    border: 'solid gray',
    borderWidth: '5px 5px',
    width: '320px',
    height: '66px',
    fontSize: '25px',
    color: '#00FF00',
    textAlign: 'center',
    display: 'table',
    overflow: 'hidden',
    marginBottom: '-5px',
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
  });
  let xptimer = $('<div id="xptimercontent"></div>')
    .css({
      display: 'table-cell',
      verticalAlign: 'middle'
    })
    .html('Estimated time until level up:<br><span id="xpcounter" style="font-size: 30px !important; line-height: 25px">Loading...</span><br><span id="xprate">(Kill something!)</span>')
    .appendTo(xpt_container);
  brc.children().first().after(xpt_container);
}

var last_minutes_checked = new Date();
var last_xp_checked_minutes = character.xp;
var last_xp_checked_kill = character.xp;
let xpRateType = 'second'; // Default to XP/s

function toggleXPDisplay() {
  if (xpRateType === 'second') {
    xpRateType = 'minute';
  } else if (xpRateType === 'minute') {
    xpRateType = 'hour';
  } else {
    xpRateType = 'second';
  }
  update_xptimer(); // Update the display when toggling
}

function update_xptimer() {
  if (character.xp == last_xp_checked_kill) return;
  let $ = parent.$;
  let now = new Date();
  let time = Math.round((now.getTime() - last_minutes_checked.getTime()) / 1000);
  if (time < 1) return;
  let xp_rate = Math.round((character.xp - last_xp_checked_minutes) / time);

  let xp_per_hour = Math.round(xp_rate * 3600);
  let xp_per_minute = Math.round(xp_rate * 60);

  if (time > 60 * minute_refresh) {
    last_minutes_checked = new Date();
    last_xp_checked_minutes = character.xp;
  }
  last_xp_checked_kill = character.xp;
  let xp_missing = parent.G.levels[character.level] - character.xp;
  let seconds = Math.round(xp_missing / xp_rate);
  let minutes = Math.round(seconds / 60);
  let hours = Math.round(minutes / 60);
  let days = Math.floor(hours / 24);

  let remainingHours = hours % 24;
  let remainingMinutes = minutes % 60;

  let counter = `${days}d ${remainingHours}h ${remainingMinutes}min`;
  $('#xpcounter').css('color', '#87CEEB').text(counter); // Sky Blue color for the time until level up

  let xpRateDisplay = $('#xpRateDisplay');
  xpRateDisplay.empty(); // Clear previous values

  let xpButton = $('<div class="gamebutton clickable"></div>')
    .css({
      'font-size': '20px', // Adjusted font size
      'width': '30px', // Adjusted width
      'height': '5px', // Adjusted height
      'line-height': '5px', // Adjusted line height
      'background': 'none',
      'color': xpRateType === 'second' ? '#00FF00' : xpRateType === 'minute' ? '#FFA500' : '#FF0000',
      'margin-right': '50px',
      'borderWidth': '3px', // Adjusted border size
    })
    .text(`XP/${xpRateType.charAt(0).toUpperCase()}`)
    .on('click', toggleXPDisplay);

  let xprateContainer = $('<div class="xprate-container"></div>')
    .css({
      'display': 'flex',
      'align-items': 'center'
    });

  xprateContainer.append(xpButton);
  xprateContainer.append('<br>');
  xprateContainer.append(`<span id="xpRateDisplay">${xpRateType === 'second' ? ncomma(xp_rate) + ' XP/s' : xpRateType === 'minute' ? ncomma(xp_per_minute) + ' XP/min' : ncomma(xp_per_hour) + ' XP/h'}</span>`);

  $('#xprate').empty().append(xprateContainer);
}

function ncomma(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

init_xptimer(5);

/*
* END UI CODE
*/

/*
* PARTY CODE
*/

var group = ["LordAchoo", "LordAsneeze", "LordApriest"];

setInterval(function () {
	if(parent.party_list.length < 3 ){
    if (character.name == group[0]) {
        for (let i = 1; i < group.length; i++) {
            let name = group[i];
            send_party_invite(name);
        }
    } else {
        if (character.party) {
            if (character.party != group[0]) {
                parent.socket.emit("party", {event: "leave"})
            }
        } else {
            send_party_request(group[0]);
            }  
        }
    }
}, 1000 * 10);

function on_party_request(name) {
    console.log("Party Request");
    if (group.indexOf(name) != -1) {
        accept_party_request(name);
    }
}
function on_party_invite(name) {
    console.log("Party Invite");
    if (group.indexOf(name) != -1) {
        accept_party_invite(name);
    }
}
⚠️ **GitHub.com Fallback** ⚠️