Collect hit chance data for eternity tower
// ==UserScript==
// @name ET Hit Collection
// @version 0.2
// @description Collect hit chance data for eternity tower
// @author Jimborinot
// @match http*://*.eternitytower.net/*
// @grant none
// @namespace https://greasyfork.org/users/156118
// ==/UserScript==
/* jshint esversion: 6 */
(function() {
'use strict';
var battleHitData = {};
var battleState = null;
// wait some time for meteor to be ready
setTimeout(init, 3000);
function init() {
console.log("ET Hit Collection initialized");
if(isInBattle()) {
if(localStorage.getItem("hitData")) {
battleHitData = JSON.parse(localStorage.getItem("hitData"));
}
}
createListener();
}
function createListener() {
Meteor.connection._stream.on("message", json => {
let message = JSON.parse(json);
if(message.msg == "changed" && message.collection == "redis") {
battleState = JSON.parse(message.fields.value);
if(battleState.units.concat(battleState.deadUnits).length > 1) return;
var tick = battleState.tick;
let livingEntities = battleState.units.concat(battleState.enemies);
livingEntities.forEach(entity => {
let tickOffset = entity.tickOffset;
let attackSpeedTicks = entity.stats.attackSpeedTicks;
// autoattack will occur this tick
if((tick - tickOffset - 1) % attackSpeedTicks === 0) {
let target = entity.hasOwnProperty("target") ? getEntityById(entity.target) : battleState.enemies[0];
if(target === undefined) {
target = battleState.deadEnemies[battleState.deadEnemies.length - 1];
}
if(entityIsInvulnerable(target))
return;
if(!battleHitData.hasOwnProperty(entity.stats.accuracy)) {
battleHitData[entity.stats.accuracy] = {};
battleHitData[entity.stats.accuracy][target.stats.defense] = { total: 0, misses: 0 };
} else if(!battleHitData[entity.stats.accuracy].hasOwnProperty(target.stats.defense)) {
battleHitData[entity.stats.accuracy][target.stats.defense] = { total: 0, misses: 0 };
}
battleHitData[entity.stats.accuracy][target.stats.defense].total++;
}
});
battleState.tickEvents.forEach(event => {
if(event.eventType !== "damage") return;
let from = getEntityById(event.from);
let to = getEntityById(event.to);
// any 0.0 hitEvent is an autoattack as long as target doesn't have an evasion buff
if(event.label == "0.0" && !entityIsInvulnerable(to)) {
if(!battleHitData.hasOwnProperty(from.stats.accuracy)) {
battleHitData[from.stats.accuracy] = {};
battleHitData[from.stats.accuracy][to.stats.defense] = { total: 0, misses: 0 };
} else if(!battleHitData[from.stats.accuracy].hasOwnProperty(to.stats.defense)) {
battleHitData[from.stats.accuracy][to.stats.defense] = { total: 0, misses: 0 };
}
battleHitData[from.stats.accuracy][to.stats.defense].misses++;
}
});
}
if(message.msg == "removed" && message.collection == "redis") {
localStorage.setItem("hitData", JSON.stringify(battleHitData));
battleHitData = {};
}
if(message.msg == "added" && message.collection == "redis") {
if(localStorage.getItem("hitData")) {
battleHitData = JSON.parse(localStorage.getItem("hitData"));
}
}
})
}
function getEntityById(id) {
let allEntities = battleState.units.concat(battleState.enemies, battleState.deadUnits, battleState.deadEnemies);
return allEntities.find(entity => entity.id == id);
}
function entityIsInvulnerable(entity) {
return entity.buffs.find(buff => {
// used by both ninja and spirit, as well as players
if(buff.id == "evasive_maneuvers") return true;
});
}
function isInBattle() {
let battlesList = Meteor.connection._mongo_livedata_collections.battlesList.find().fetch();
return battlesList.length > 0;
}
})();