diff --git a/plugins/portal-defense.user.js b/plugins/portal-defense.user.js
new file mode 100644
index 00000000..091baf3d
--- /dev/null
+++ b/plugins/portal-defense.user.js
@@ -0,0 +1,192 @@
+// ==UserScript==
+// @id iitc-plugin-defense@gluckies
+// @name IITC plugin: portal defense
+// @category Layer
+// @version 0.2.0.@@DATETIMEVERSION@@
+// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
+// @updateURL @@UPDATEURL@@
+// @downloadURL @@DOWNLOADURL@@
+// @description [@@BUILDNAME@@-@@BUILDDATE@@] Shows the defense values of every portal
+// @include https://www.ingress.com/intel*
+// @include http://www.ingress.com/intel*
+// @match https://www.ingress.com/intel*
+// @match http://www.ingress.com/intel*
+// ==/UserScript==
+
+@@PLUGINSTART@@
+
+// PLUGIN START ////////////////////////////////////////////////////////
+
+// use own namespace for plugin
+window.plugin.portalDefense = function() {};
+
+window.plugin.portalDefense.MIN_MAP_ZOOM = 15;
+window.plugin.portalDefense.DETAIL_MAP_ZOOM = 17;
+window.plugin.portalDefense.DisplayEnum = {
+ OFF : 0,
+ SIMPLE : 1,
+ DETAIL : 2
+};
+
+window.plugin.portalDefense.regionLayers = {};
+
+// Use portal add and remove event to control render of regions
+window.plugin.portalDefense.portalAdded = function(data) {
+ data.portal.on('add', function() {
+ plugin.portalDefense.renderAttackRegion(this);
+ });
+
+ data.portal.on('remove', function() {
+ plugin.portalDefense.removeAttackRegion(this);
+ });
+}
+
+window.plugin.portalDefense.getDisplay = function() {
+ if (map.getZoom() >= window.plugin.portalDefense.DETAIL_MAP_ZOOM) {
+ return window.plugin.portalDefense.DisplayEnum.DETAIL;
+ } else if (map.getZoom() >= window.plugin.portalDefense.MIN_MAP_ZOOM) {
+ return window.plugin.portalDefense.DisplayEnum.SIMPLE;
+ }
+ return window.plugin.portalDefense.DisplayEnum.OFF;
+}
+
+window.plugin.portalDefense.computeDef = function(portal) {
+ var m = portal.options.details.portalV2.linkedModArray;
+ var ret = {};
+ ret.mod = 0;
+ ret.links = 0;
+ var display = "";
+ $.each(m, function(ind, mod) {
+ if (!mod) return true;
+ if(!mod.stats.MITIGATION)
+ return true;
+ ret.mod += parseInt(mod.stats.MITIGATION);
+ });
+ var link = 0;
+ $(portal.options.details.portalV2.linkedEdges).each(function () {
+ link++;
+ });
+ if (link > 0) {
+ ret.links = Math.round(400/9*Math.atan(link/Math.E));
+ }
+ ret.total = Math.min(95, ret.mod + ret.links);
+
+ return ret;
+}
+
+window.plugin.portalDefense.renderAttackRegion = function(portal) {
+ plugin.portalDefense.removeAttackRegion(portal);
+ if (window.plugin.portalDefense.currentDisplay == window.plugin.portalDefense.DisplayEnum.OFF) return;
+
+ plugin.portalDefense.regionLayers[portal.options.guid] = [];
+ var defense = window.plugin.portalDefense.computeDef(portal);
+ if (defense.total) {
+ var display = defense.total;
+ if (window.plugin.portalDefense.currentDisplay == window.plugin.portalDefense.DisplayEnum.DETAIL) {
+ if (defense.mod) {
+ display += "
"+"\u2297"+defense.mod;
+ }
+ if(defense.links) {
+ display += "
"+"\u21b1"+defense.links;
+ }
+ }
+ var region = L.marker(portal.getLatLng(), {
+ icon: L.divIcon({
+ className: 'plugin-iic-defense',
+ clickable: false,
+ iconAnchor: [-10,10],
+ html: "