diff --git a/plugins/ap-list.user.js b/plugins/ap-list.user.js
index 7de36dee..7185b3cf 100644
--- a/plugins/ap-list.user.js
+++ b/plugins/ap-list.user.js
@@ -68,9 +68,12 @@ window.plugin.apList.updatePortalTable = function(side) {
+ '">'
+ (portal ? plugin.apList.getPortalLink(portal) : ' ')
+ ''
- + '
'
+ + ' | '
+ (portal ? plugin.apList.getPortalApText(portal) : ' ')
+ ' | '
+ + ''
+ + (portal ? plugin.apList.getPortalEffectiveLvText(portal) : ' ')
+ + ' | '
+ '';
}
content += "";
@@ -141,6 +144,18 @@ window.plugin.apList.getPortalApTitle = function(portal) {
return t;
}
+window.plugin.apList.getPortalEffectiveLvText = function(portal) {
+ var title = plugin.apList.getPortalEffectiveLvTitle(portal);
+ return '' + portal.effectiveLevel.effectiveLevel + '
';
+}
+
+window.plugin.apList.getPortalEffectiveLvTitle = function(portal) {
+ var t = 'Effective energy:\t' + portal.effectiveLevel.effectiveEnergy + '\n'
+ + 'Effect of Shields:\t' + portal.effectiveLevel.effectOfShields + '\n'
+ + 'Effect of resos dist:\t' + portal.effectiveLevel.effectOfResoDistance + '\n';
+ return t;
+}
+
// portal link - single click: select portal
// double click: zoom to and select portal
// hover: show address
@@ -195,6 +210,7 @@ window.plugin.apList.updateSortedPortals = function() {
var getApGainFunc = plugin.apList.playerApGainFunc[side];
// Assign playerApGain and guid to cachedPortal
cachedPortal.playerApGain = getApGainFunc(portal);
+ cachedPortal.effectiveLevel = plugin.apList.getEffectiveLevel(portal);
cachedPortal.guid = value.options.guid;
}
plugin.apList.cachedPortals[key] = cachedPortal;
@@ -408,6 +424,83 @@ window.plugin.apList.getAttackApGain = function(d) {
}
}
+window.plugin.apList.getEffectiveLevel = function(portal) {
+ var effectiveEnergy = 0;
+ var effectiveLevel = 0;
+
+ var resosStats = plugin.apList.getResonatorsStats(portal);
+ var shieldsMitigation = plugin.apList.getShieldsMitigation(portal);
+
+ // Calculate effective energy
+
+ // Portal damage = Damage output * (1 - shieldsMitigation / 100)
+ // Reverse it and we get
+ // Damage output = Portal damage * (100 / (100 - shieldsMitigation))
+ var effectOfShields = 100 / (100 - shieldsMitigation);
+ // If avgResoDistance is 0, 8 resonators in the same place and can be treated as 1 resonator.
+ // So the minimum effect of resonator distance is 1/8
+ var effectOfResoDistance = (1 + (resosStats.avgResoDistance / HACK_RANGE) * 7 ) / 8;
+
+ effectiveEnergy = resosStats.currentEnergy * effectOfShields * effectOfResoDistance;
+
+ // Calculate effective level
+ for(var i = MAX_PORTAL_LEVEL; i >= 0; i--) {
+ var baseLevel = i;
+ var baseLevelEnergy = RESO_NRG[baseLevel] * 8;
+ if(effectiveEnergy >= baseLevelEnergy) {
+ var energyToNextLevel = baseLevel === MAX_PORTAL_LEVEL
+ ? baseLevelEnergy - RESO_NRG[MAX_PORTAL_LEVEL - 1] * 8 // Extrapolate
+ : RESO_NRG[baseLevel + 1] * 8 - baseLevelEnergy; // Interpolate
+
+ var additionalLevel = (effectiveEnergy - baseLevelEnergy) / energyToNextLevel;
+ effectiveLevel = baseLevel + additionalLevel;
+ break;
+ }
+ }
+
+ // Account for damage do to player by portal
+ var portalLevel = parseInt(getPortalLevel(portal));
+ if(effectiveLevel < portalLevel) {
+ var energyPect = resosStats.currentEnergy / resosStats.totalEnergy;
+ effectiveLevel = effectiveLevel * (1-energyPect) + portalLevel * energyPect;
+ }
+
+ return {
+ effectiveLevel: effectiveLevel.toFixed(1),
+ effectiveEnergy: parseInt(effectiveEnergy),
+ effectOfShields: effectOfShields.toFixed(2),
+ effectOfResoDistance: effectOfResoDistance.toFixed(2)
+ };
+}
+
+window.plugin.apList.getResonatorsStats = function(portal) {
+ var totalEnergy = 0;
+ var currentEnergy = 0;
+ var avgResoDistance = 0;
+
+ $.each(portal.resonatorArray.resonators, function(ind, reso) {
+ if (!reso)
+ return true;
+ totalEnergy += RESO_NRG[reso.level];
+ currentEnergy += reso.energyTotal;
+ avgResoDistance += (reso.distanceToPortal / 8);
+ });
+ return {
+ totalEnergy: totalEnergy,
+ currentEnergy: currentEnergy,
+ avgResoDistance: avgResoDistance};
+}
+
+window.plugin.apList.getShieldsMitigation = function(portal) {
+ var shieldsMitigation = 0;
+ $.each(portal.portalV2.linkedModArray, function(ind, mod) {
+ if(!mod)
+ return true;
+ shieldsMitigation += parseInt(mod.stats.MITIGATION);
+ });
+ return shieldsMitigation;
+}
+
window.plugin.apList.selectPortal = function(guid) {
renderPortalDetails(guid);
plugin.apList.setPortalLocationIndicator(guid);