@ -12,49 +12,53 @@
|
||||
;(function(){
|
||||
|
||||
var requestParameterMunges = [
|
||||
// obsolete munge sets (they don't have some of the new parameters) deleted
|
||||
// all old munge sets deleted - there's no sign that any old ones will become active again
|
||||
|
||||
// set 10 - 2013-11-27
|
||||
// set 11 - 2013-12-06
|
||||
{
|
||||
'dashboard.getArtifactInfo': 'artifacts', // GET_ARTIFACT_INFO
|
||||
'dashboard.getGameScore': '4oid643d9zc168hs', // GET_GAME_SCORE
|
||||
'dashboard.getPaginatedPlexts': 's1msyywq51ntudpe', // GET_PAGINATED_PLEXTS
|
||||
'dashboard.getThinnedEntities': '4467ff9bgxxe4csa', // GET_THINNED_ENTITIES
|
||||
'dashboard.getPortalDetails': 'c00thnhf1yp3z6mn', // GET_PORTAL_DETAILS
|
||||
'dashboard.redeemReward': '66l9ivg39ygfqqjm', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': 'cgb7hi5hglv0xx8k', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'etn9xq7brd6947kq', // SEND_PLEXT
|
||||
'dashboard.redeemReward': 'ivshfv9zvyfxyqcd', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': '1rsx15vc0m8wwdax', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'tods2imd0xcfsug6', // SEND_PLEXT
|
||||
|
||||
// common parameters
|
||||
method: 'yyngyttbmmbuvdpa',
|
||||
version: 'avz401t36lzrapis',
|
||||
version_parameter: 'c5d0a5d608f729a1232bebdc12fb86ba5fb6c43f',
|
||||
method: '0wvzluo8av4sk17f',
|
||||
version: 'paeh4g353xu06kfg',
|
||||
version_parameter: '4acc1e3230c3fd66be3422c0df8dc637336bbd7c',
|
||||
|
||||
// GET_THINNED_ENTITIES
|
||||
quadKeys: '1mpmxz2yun22rwnn',
|
||||
quadKeys: 'ilgv0w4dlldky1yh',
|
||||
|
||||
// GET_PORTAL_DETAILS
|
||||
guid: '7o8tzmj6oxz1n5w3',
|
||||
|
||||
// REDEEM_REWARD
|
||||
passcode: 'passcode', // no munging on this parameter
|
||||
|
||||
// SEND_INVITE_EMAIL
|
||||
inviteeEmailAddress: 'p4rwszdfovuwfdgp',
|
||||
|
||||
// GET_PAGINATED_PLEXTS
|
||||
desiredNumItems: 'nzd23jqm9k1cnnij',
|
||||
minLatE6: '0dod6onpa1s4fezp',
|
||||
minLngE6: 'soass3t7mm7anneo',
|
||||
maxLatE6: 'cvarmr3o00ngylo1',
|
||||
maxLngE6: 'udzwnlx07hzd3bfo',
|
||||
minTimestampMs: '9iiiks138gkf8xho',
|
||||
maxTimestampMs: '94wm0u3sc3sgzq7x',
|
||||
chatTab: 'tqfj4a3okzn5v5o1',
|
||||
ascendingTimestampOrder: '5jv1m90sq35u6utq',
|
||||
desiredNumItems: 'kxsbuvc90l6f40xn',
|
||||
minLatE6: 'llizye3i5dbapxac',
|
||||
minLngE6: 'w01zpiba1mn5tsab',
|
||||
maxLatE6: 'd5phhqzj2tbsq599',
|
||||
maxLngE6: 'avq5srnvg431aehn',
|
||||
minTimestampMs: 'mhsav5by25wi4s46',
|
||||
maxTimestampMs: 'hpu7l8h7eccwytyt',
|
||||
chatTab: 'q9343nem7hs1v37b',
|
||||
ascendingTimestampOrder: '7pc5c9ggh03pig1b',
|
||||
|
||||
// SEND_PLEXT
|
||||
message: '8exta9k7y8huhqmc',
|
||||
latE6: 'kqek161gza3kjcry',
|
||||
lngE6: '3dlxsqrjj2vcmhbc',
|
||||
// chatTab: 'efaznrayv5n3jxs0', //guessed parameter name - only seen munged
|
||||
latE6: '7ffwyf3zd2yf8xam',
|
||||
lngE6: 'n7ewiach2v22iy20',
|
||||
// chatTab: 'q9343nem7hs1v37b', // duplicate from GET_PAGINATED_PLEXTS
|
||||
|
||||
// GET_PORTAL_DETAILS
|
||||
guid: 'seg6ohxgnqf9xu9w',
|
||||
|
||||
// SEND_INVITE_EMAIL
|
||||
inviteeEmailAddress: '8exta9k7y8huhqmc',
|
||||
},
|
||||
|
||||
];
|
||||
|
BIN
mobile/res/drawable-hdpi/ic_action_place.png
Normal file
After Width: | Height: | Size: 555 B |
Before Width: | Height: | Size: 892 B |
BIN
mobile/res/drawable-mdpi/ic_action_place.png
Normal file
After Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 601 B |
BIN
mobile/res/drawable-xhdpi/ic_action_place.png
Normal file
After Width: | Height: | Size: 712 B |
Before Width: | Height: | Size: 1.2 KiB |
BIN
mobile/res/drawable-xxhdpi/ic_action_place.png
Normal file
After Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 1.7 KiB |
@ -19,20 +19,20 @@
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/layer_chooser">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/reload_button"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:orderInCategory="110"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/reload">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/toggle_fullscreen"
|
||||
android:icon="@drawable/ic_action_full_screen"
|
||||
android:orderInCategory="120"
|
||||
android:orderInCategory="110"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/toggle_fullscreen">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/reload_button"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:orderInCategory="120"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="@string/reload">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/menu_clear_cookies"
|
||||
android:orderInCategory="130"
|
||||
@ -41,7 +41,6 @@
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:icon="@drawable/ic_action_settings"
|
||||
android:orderInCategory="200"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/action_settings">
|
||||
|
@ -150,9 +150,9 @@
|
||||
<string name="msg_copied">Copied to clipboard…</string>
|
||||
<string name="notice_do_not_show_again">Do not show again</string>
|
||||
|
||||
<string name="tab_map">Map</string>
|
||||
<string name="tab_map">Locate</string>
|
||||
<string name="tab_share">Share</string>
|
||||
<string name="tab_browser">Browser</string>
|
||||
<string name="tab_browser">Intel</string>
|
||||
|
||||
<string name="label_highlighter">Highlighter</string>
|
||||
<string name="label_base_layer">Base Layer</string>
|
||||
|
@ -324,6 +324,12 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unregisterReceiver(mBroadcastReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
@ -71,7 +71,15 @@ public class IITC_WebView extends WebView {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isInFullscreen() && (getFullscreenStatus() & (FS_NAVBAR)) != 0) {
|
||||
setSystemUiVisibility(SYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
||||
int systemUiVisibility = SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
// in immersive mode the user can interact with the app while the navbar is hidden
|
||||
// this mode is available since KitKat
|
||||
// you can leave this mode by swiping down from the top of the screen. this does only work
|
||||
// when the app is in total-fullscreen mode
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && (mFullscreenStatus & FS_SYSBAR) != 0) {
|
||||
systemUiVisibility |= SYSTEM_UI_FLAG_IMMERSIVE;
|
||||
}
|
||||
setSystemUiVisibility(systemUiVisibility);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -165,12 +173,7 @@ public class IITC_WebView extends WebView {
|
||||
|
||||
public void loadJS(String js) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
evaluateJavascript(js, new ValueCallback<String>() {
|
||||
@Override
|
||||
public void onReceiveValue(String value) {
|
||||
// maybe we want to add stuff here
|
||||
}
|
||||
});
|
||||
evaluateJavascript(js, null);
|
||||
} else {
|
||||
// if in edit text mode, don't load javascript otherwise the keyboard closes.
|
||||
HitTestResult testResult = getHitTestResult();
|
||||
@ -190,20 +193,22 @@ public class IITC_WebView extends WebView {
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
getHandler().removeCallbacks(mNavHider);
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
getHandler().postDelayed(mNavHider, 3000);
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemUiVisibility(int visibility) {
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
if ((visibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
|
||||
getHandler().postDelayed(mNavHider, 3000);
|
||||
}
|
||||
super.setSystemUiVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
if (hasWindowFocus) {
|
||||
getHandler().postDelayed(mNavHider, 2000);
|
||||
getHandler().postDelayed(mNavHider, 3000);
|
||||
} else {
|
||||
getHandler().removeCallbacks(mNavHider);
|
||||
}
|
||||
@ -225,7 +230,7 @@ public class IITC_WebView extends WebView {
|
||||
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
}
|
||||
if ((mFullscreenStatus & FS_NAVBAR) != 0) {
|
||||
setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
||||
getHandler().post(mNavHider);
|
||||
}
|
||||
if ((mFullscreenStatus & FS_STATUSBAR) != 0) {
|
||||
loadUrl("javascript: $('#updatestatus').hide();");
|
||||
|
@ -9,6 +9,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -37,6 +38,10 @@ public class IntentListView extends ListView {
|
||||
}
|
||||
|
||||
private class IntentAdapter extends ArrayAdapter<ResolveInfo> {
|
||||
|
||||
// actually the mdpi pixel size is 48, but this looks ugly...so scale icons down for listView
|
||||
private static final int MDPI_PX = 36;
|
||||
|
||||
private IntentAdapter() {
|
||||
super(IntentListView.this.getContext(), android.R.layout.simple_list_item_1);
|
||||
}
|
||||
@ -48,11 +53,19 @@ public class IntentListView extends ListView {
|
||||
|
||||
ActivityInfo info = getItem(position).activityInfo;
|
||||
CharSequence label = info.loadLabel(mPackageManager);
|
||||
|
||||
// get icon and scale it manually to ensure that all have the same size
|
||||
Drawable icon = info.loadIcon(mPackageManager);
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||
float densityScale = dm.density;
|
||||
float scaledWidth = MDPI_PX * densityScale;
|
||||
float scaledHeight = MDPI_PX * densityScale;
|
||||
icon.setBounds(0,0,Math.round(scaledWidth),Math.round(scaledHeight));
|
||||
|
||||
view.setText(label);
|
||||
view.setCompoundDrawablePadding((int) getResources().getDimension(R.dimen.icon_margin));
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
|
||||
view.setCompoundDrawables(icon, null, null, null);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
String geoUri = "geo:" + mLl;
|
||||
Intent geoIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(geoUri));
|
||||
intents.add(geoIntent);
|
||||
addTab(intents, R.string.tab_map, R.drawable.ic_action_map);
|
||||
addTab(intents, R.string.tab_map, R.drawable.ic_action_place);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl()));
|
||||
addTab(intent, R.string.tab_browser, R.drawable.ic_action_web_site);
|
||||
@ -122,6 +122,9 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
|
||||
setupShareIntent(intent.getStringExtra("shareString"));
|
||||
}
|
||||
|
||||
// show portal name as action bar title, if available
|
||||
if (mTitle != getString(R.string.app_name)) actionBar.setTitle(mTitle);
|
||||
|
||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
||||
mViewPager.setAdapter(mFragmentAdapter);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-bing-maps
|
||||
// @name IITC plugin: Bing maps
|
||||
// @category Map Tiles
|
||||
// @version 0.1.1.@@DATETIMEVERSION@@
|
||||
// @version 0.1.2.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -23,7 +23,7 @@ window.plugin.mapBing = function() {};
|
||||
window.plugin.mapBing.setupBingLeaflet = function() {
|
||||
@@INCLUDERAW:external/Bing.js@@
|
||||
}
|
||||
|
||||
|
||||
|
||||
window.plugin.mapBing.setup = function() {
|
||||
window.plugin.mapBing.setupBingLeaflet();
|
||||
@ -37,12 +37,35 @@ window.plugin.mapBing.setup = function() {
|
||||
'AerialWithLabels': "Aerial with labels",
|
||||
};
|
||||
|
||||
// bing maps has an annual usage limit, which will likely be hit in 6 months at this time.
|
||||
// it seems that the usage is counted on initialising the L.BingLayer, when the metadata is retrieved.
|
||||
// so, we'll create some dummy layers and add those to the map, then, the first time a layer is added,
|
||||
// create the L.BingLayer. This will eliminate all usage for users who install but don't use the map,
|
||||
// and only create usage for the map layers actually selected in use
|
||||
|
||||
var bingMapContainers = [];
|
||||
|
||||
for (type in bingTypes) {
|
||||
var name = bingTypes[type];
|
||||
var bingMap = new L.BingLayer(bingApiKey, {type: type, maxZoom:20});
|
||||
layerChooser.addBaseLayer(bingMap, 'Bing '+name);
|
||||
|
||||
bingMapContainers[type] = new L.LayerGroup();
|
||||
layerChooser.addBaseLayer(bingMapContainers[type], 'Bing '+name);
|
||||
}
|
||||
|
||||
// now a leaflet event to catch base layer changes and create a L.BingLayer when needed
|
||||
map.on('baselayerchange', function(e) {
|
||||
for (type in bingMapContainers) {
|
||||
if (e.layer == bingMapContainers[type]) {
|
||||
if (bingMapContainers[type].getLayers().length == 0) {
|
||||
// dummy layer group is empty - create the bing layer
|
||||
console.log('basemap-bing: creating '+type+' layer');
|
||||
var bingMap = new L.BingLayer (bingApiKey, {type: type, maxZoom:20});
|
||||
bingMapContainers[type].addLayer(bingMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var setup = window.plugin.mapBing.setup;
|
||||
|
@ -1,811 +0,0 @@
|
||||
// ==UserScript==
|
||||
// @id iitc-plugin-draw-resonators@xelio
|
||||
// @name IITC plugin: Draw resonators
|
||||
// @category Layer
|
||||
// @version 0.4.0.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Draw resonators on map. With stylers to highlight resonators with specific criteria.
|
||||
// @include https://www.ingress.com/intel*
|
||||
// @include http://www.ingress.com/intel*
|
||||
// @match https://www.ingress.com/intel*
|
||||
// @match http://www.ingress.com/intel*
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
@@PLUGINSTART@@
|
||||
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
|
||||
// use own namespace for plugin
|
||||
window.plugin.drawResonators = function() {};
|
||||
|
||||
|
||||
window.plugin.drawResonators.options;
|
||||
window.plugin.drawResonators.render;
|
||||
|
||||
|
||||
|
||||
//////// Render for handling render of resonators ////////
|
||||
|
||||
// As long as 'window.Render.prototype.createPortalEntity' delete and recreate portal
|
||||
// on any change of data, this resonator render should make resonator create and remove
|
||||
// with portal correctly.
|
||||
//
|
||||
// Resonators will create when
|
||||
// 1.Portal added to map
|
||||
// 2.Zooming in to enable zoom level
|
||||
//
|
||||
// Resonators will remove when
|
||||
// 1.Portal removed from map
|
||||
// 2.Zooming out beyond enable zoom level
|
||||
|
||||
window.plugin.drawResonators.Render = function(options) {
|
||||
this.enableZoomLevel = options['enableZoomLevel'];
|
||||
this.useStyler = '';
|
||||
|
||||
this.stylers = {};
|
||||
this.resonators = {};
|
||||
this.resonatorLayerGroup = new L.LayerGroup();
|
||||
this.addStyler(new window.plugin.drawResonators.Styler());
|
||||
this.beforeZoomLevel = map.getZoom();
|
||||
|
||||
this.portalAdded = this.portalAdded.bind(this);
|
||||
this.createResonatorEntities = this.createResonatorEntities.bind(this);
|
||||
this.deleteResonatorEntities = this.deleteResonatorEntities.bind(this);
|
||||
this.handleResonatorEntitiesBeforeZoom = this.handleResonatorEntitiesBeforeZoom.bind(this);
|
||||
this.handleResonatorEntitiesAfterZoom = this.handleResonatorEntitiesAfterZoom.bind(this);
|
||||
this.handleEnableZoomLevelChange = this.handleEnableZoomLevelChange.bind(this);
|
||||
this.portalSelectionChange = this.portalSelectionChange.bind(this);
|
||||
this.changeStyler = this.changeStyler.bind(this);
|
||||
this.getStylersList = this.getStylersList.bind(this);
|
||||
};
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.registerHook = function() {
|
||||
window.addHook('portalAdded', this.portalAdded);
|
||||
window.addHook('portalSelected', this.portalSelectionChange);
|
||||
window.map.on('zoomstart', this.handleResonatorEntitiesBeforeZoom);
|
||||
window.map.on('zoomend', this.handleResonatorEntitiesAfterZoom);
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.portalAdded = function(data) {
|
||||
var marker = data.portal;
|
||||
var render = this;
|
||||
|
||||
marker.on('add', function() {
|
||||
render.createResonatorEntities(this); // the 'this' in here is the portal.
|
||||
});
|
||||
|
||||
marker.on('remove', function() {
|
||||
render.deleteResonatorEntities(this.options.guid); // the 'this' in here is the portal.
|
||||
});
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.createResonatorEntities = function(portal) {
|
||||
// No need to check for existing resonators, as old resonators should be removed with the portal marker.
|
||||
|
||||
if(!this.isResonatorsShow()) return;
|
||||
var portalDetails = portal.options.details;
|
||||
var resonatorsWithConnector = new L.LayerGroup()
|
||||
|
||||
var portalLatLng = [portalDetails.locationE6.latE6/1E6, portalDetails.locationE6.lngE6/1E6];
|
||||
var portalSelected = selectedPortal === portal.options.guid;
|
||||
|
||||
for(var i in portalDetails.resonatorArray.resonators) {
|
||||
resoData = portalDetails.resonatorArray.resonators[i];
|
||||
if(resoData === null) continue;
|
||||
|
||||
var resoLatLng = this.getResonatorLatLng(resoData.distanceToPortal, resoData.slot, portalLatLng);
|
||||
|
||||
var resoMarker = this.createResoMarker(resoData, resoLatLng, portalSelected);
|
||||
var connMarker = this.createConnMarker(resoData, resoLatLng, portalLatLng, portalSelected);
|
||||
|
||||
resonatorsWithConnector.addLayer(resoMarker);
|
||||
resonatorsWithConnector.addLayer(connMarker);
|
||||
}
|
||||
|
||||
resonatorsWithConnector.options = {
|
||||
details: portalDetails.resonatorArray.resonators,
|
||||
guid: portal.options.guid
|
||||
};
|
||||
|
||||
this.resonators[portal.options.guid] = resonatorsWithConnector;
|
||||
this.resonatorLayerGroup.addLayer(resonatorsWithConnector);
|
||||
|
||||
// bring portal in front of resonator connector
|
||||
portal.bringToFront();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.createResoMarker = function(resoData, resoLatLng, portalSelected) {
|
||||
var resoProperty = this.getStyler().getResonatorStyle(resoData, portalSelected);
|
||||
resoProperty.type = 'resonator';
|
||||
resoProperty.details = resoData;
|
||||
var reso = L.circleMarker(resoLatLng, resoProperty);
|
||||
return reso;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.createConnMarker = function(resoData, resoLatLng, portalLatLng, portalSelected) {
|
||||
var connProperty = this.getStyler().getConnectorStyle(resoData, portalSelected);
|
||||
connProperty.type = 'connector';
|
||||
connProperty.details = resoData;
|
||||
var conn = L.polyline([portalLatLng, resoLatLng], connProperty);
|
||||
return conn;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.getResonatorLatLng = function(dist, slot, portalLatLng) {
|
||||
// offset in meters
|
||||
var dn = dist*SLOT_TO_LAT[slot];
|
||||
var de = dist*SLOT_TO_LNG[slot];
|
||||
|
||||
// Coordinate offset in radians
|
||||
var dLat = dn/EARTH_RADIUS;
|
||||
var dLon = de/(EARTH_RADIUS*Math.cos(Math.PI/180*portalLatLng[0]));
|
||||
|
||||
// OffsetPosition, decimal degrees
|
||||
var lat0 = portalLatLng[0] + dLat * 180/Math.PI;
|
||||
var lon0 = portalLatLng[1] + dLon * 180/Math.PI;
|
||||
|
||||
return [lat0, lon0];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.deleteResonatorEntities = function(portalGuid) {
|
||||
if (!(portalGuid in this.resonators)) return;
|
||||
|
||||
var r = this.resonators[portalGuid];
|
||||
this.resonatorLayerGroup.removeLayer(r);
|
||||
delete this.resonators[portalGuid];
|
||||
}
|
||||
|
||||
// Save zoom level before zoom, use to determine redraw of resonator
|
||||
window.plugin.drawResonators.Render.prototype.handleResonatorEntitiesBeforeZoom = function() {
|
||||
this.beforeZoomLevel = map.getZoom();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.handleResonatorEntitiesAfterZoom = function() {
|
||||
if(!this.isResonatorsShow()) {
|
||||
this.clearAllResonators();
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw all resonators if they were not drawn
|
||||
if(!this.isResonatorsShowBeforeZoom()) {
|
||||
this.drawAllResonators();
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.handleEnableZoomLevelChange = function(zoomLevel) {
|
||||
this.enableZoomLevel = zoomLevel;
|
||||
|
||||
if(!this.isResonatorsShow()) {
|
||||
this.clearAllResonators();
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw all resonators if they were not drawn
|
||||
if(!Object.keys(this.resonators).length > 0) {
|
||||
this.drawAllResonators();
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.clearAllResonators = function() {
|
||||
this.resonatorLayerGroup.clearLayers();
|
||||
this.resonators = {};
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.drawAllResonators = function() {
|
||||
var render = this;
|
||||
|
||||
// loop through level of portals, only draw if the portal is shown on map
|
||||
for (var guid in window.portals) {
|
||||
var portal = window.portals[guid];
|
||||
// FIXME: need to find a proper way to check if a portal is added to the map without depending on leaflet internals
|
||||
// (and without depending on portalsLayers either - that's IITC internal)
|
||||
if (portal._map) {
|
||||
render.createResonatorEntities(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.portalSelectionChange = function(data) {
|
||||
this.toggleSelectedStyle(data.selectedPortalGuid);
|
||||
this.toggleSelectedStyle(data.unselectedPortalGuid);
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.toggleSelectedStyle = function(portalGuid) {
|
||||
if (!(portalGuid in this.resonators)) return;
|
||||
|
||||
var render = this;
|
||||
var portalSelected = selectedPortal === portalGuid;
|
||||
var r = this.resonators[portalGuid];
|
||||
|
||||
r.eachLayer(function(entity) {
|
||||
var style;
|
||||
if(entity.options.type === 'resonator') {
|
||||
style = render.getStyler().getResonatorStyle(entity.options.details, portalSelected);
|
||||
} else {
|
||||
style = render.getStyler().getConnectorStyle(entity.options.details, portalSelected);
|
||||
}
|
||||
|
||||
entity.setStyle(style);
|
||||
});
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.addStyler = function(styler) {
|
||||
this.stylers[styler.name] = styler;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.getStylersList = function() {
|
||||
return Object.keys(this.stylers);
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.getStyler = function() {
|
||||
var stylerName = this.useStyler in this.stylers ? this.useStyler : 'Default';
|
||||
return this.stylers[stylerName];
|
||||
}
|
||||
|
||||
// Change if styler need change, and redraw all resonators using new styler
|
||||
window.plugin.drawResonators.Render.prototype.changeStyler = function(name) {
|
||||
if (name === this.useStyler) return;
|
||||
for(stylerName in this.stylers) {
|
||||
if(stylerName === name) {
|
||||
if(this.stylers[this.useStyler]) this.stylers[this.useStyler].onDisableFunc();
|
||||
this.useStyler = stylerName;
|
||||
this.stylers[this.useStyler].onEnableFunc();
|
||||
this.clearAllResonators();
|
||||
this.drawAllResonators();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.refreshStyler = function() {
|
||||
this.clearAllResonators();
|
||||
this.drawAllResonators();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.isResonatorsShow = function() {
|
||||
return map.getZoom() >= this.enableZoomLevel;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Render.prototype.isResonatorsShowBeforeZoom = function() {
|
||||
return this.beforeZoomLevel >= this.enableZoomLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// Styler for getting resonator and connector style ////////
|
||||
|
||||
|
||||
|
||||
window.plugin.drawResonators.Styler = function(options) {
|
||||
options = options || {};
|
||||
this.name = options['name'] || 'Default';
|
||||
this.otherOptions = options['otherOptions'];
|
||||
this.getResonatorStyle = options['resonatorStyleFunc'] || this.defaultResonatorStyle;
|
||||
this.getConnectorStyle = options['connectorStyleFunc'] || this.defaultConnectorStyle;
|
||||
this.onEnableFunc = options['onEnableFunc'] || function() {};
|
||||
this.onDisableFunc = options['onDisableFunc'] || function() {};
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_SELECTED = {
|
||||
color: '#fff',
|
||||
weight: 1.1,
|
||||
radius: 4,
|
||||
opacity: 1,
|
||||
clickable: false};
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_NON_SELECTED = {
|
||||
color: '#aaa',
|
||||
weight: 1,
|
||||
radius: 3,
|
||||
opacity: 1,
|
||||
clickable: false};
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_LINE_SELECTED = {
|
||||
opacity: 0.7,
|
||||
weight: 3,
|
||||
color: '#FFA000',
|
||||
dashArray: '0,10' + (new Array(25).join(',8,4')),
|
||||
fill: false,
|
||||
clickable: false};
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_LINE_NON_SELECTED = {
|
||||
opacity: 0.25,
|
||||
weight: 2,
|
||||
color: '#FFA000',
|
||||
dashArray: '0,10' + (new Array(25).join(',8,4')),
|
||||
fill: false,
|
||||
clickable: false};
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.defaultResonatorStyle = function(resoDetail, selected) {
|
||||
var resoSharedStyle = selected
|
||||
? this.DEFAULT_OPTIONS_RESONATOR_SELECTED
|
||||
: this.DEFAULT_OPTIONS_RESONATOR_NON_SELECTED;
|
||||
|
||||
var resoStyle = $.extend({
|
||||
fillColor: COLORS_LVL[resoDetail.level],
|
||||
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level],
|
||||
}, resoSharedStyle);
|
||||
|
||||
return resoStyle;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Styler.prototype.defaultConnectorStyle = function(resoDetail, selected) {
|
||||
var connStyle = selected
|
||||
? this.DEFAULT_OPTIONS_RESONATOR_LINE_SELECTED
|
||||
: this.DEFAULT_OPTIONS_RESONATOR_LINE_NON_SELECTED;
|
||||
|
||||
return connStyle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// Options for storing and loading options ////////
|
||||
|
||||
|
||||
|
||||
window.plugin.drawResonators.Options = function() {
|
||||
this._options = {};
|
||||
this._callbacks = {};
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.addCallback = function(name, callback) {
|
||||
if (!this._callbacks[name]) {
|
||||
this._callbacks[name] = [];
|
||||
}
|
||||
this._callbacks[name].push(callback);
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.newOption = function(name, defaultValue) {
|
||||
this._options[name] = this.loadLocal(this.getStorageKey(name), defaultValue)
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.getOption = function(name) {
|
||||
return this._options[name];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.removeOption = function(name) {
|
||||
delete this._options[name];
|
||||
delete this._callbacks[name];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.changeOption = function(name, value) {
|
||||
if(!(name in this._options)) return false;
|
||||
if(value === this._options[name]) return false;
|
||||
|
||||
this._options[name] = value;
|
||||
this.storeLocal(this.getStorageKey(name), this._options[name]);
|
||||
|
||||
if (this._callbacks[name] !== null) {
|
||||
for(var i in this._callbacks[name]) {
|
||||
this._callbacks[name][i](value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.getStorageKey = function(name) {
|
||||
return 'plugin-drawResonators-option-' + name;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.loadLocal = function(key, defaultValue) {
|
||||
var objectJSON = localStorage[key];
|
||||
if(objectJSON) {
|
||||
return JSON.parse(objectJSON);
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Options.prototype.storeLocal = function(key, value) {
|
||||
if(typeof(value) !== 'undefined' && value !== null) {
|
||||
localStorage[key] = JSON.stringify(value);
|
||||
} else {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// Dialog
|
||||
|
||||
window.plugin.drawResonators.Dialog = function() {
|
||||
this._dialogEntries = {};
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.addLink = function() {
|
||||
$('#toolbox').append('<a id="draw-reso-show-dialog" onclick="window.plugin.drawResonators.dialog.show();">Resonators</a> ');
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.addEntry = function(name, dialogEntry) {
|
||||
this._dialogEntries[name] = dialogEntry;
|
||||
this.change();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.removeEntry = function(name) {
|
||||
delete this._dialogEntries[name];
|
||||
this.change();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.show = function() {
|
||||
window.dialog({html: this.getDialogHTML(), title: 'Resonators', modal: true, id: 'draw-reso-setting'});
|
||||
|
||||
// Attach entries event
|
||||
for(var name in this._dialogEntries) {
|
||||
var events = this._dialogEntries[name].getOnEvents();
|
||||
for(var i in events) {
|
||||
var event = events[i];
|
||||
$('#draw-reso-dialog').on(event.event, '#' + event.id, event.callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.change = function() {
|
||||
if($('#draw-reso-dialog').length > 0) this.show();
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.Dialog.prototype.getDialogHTML = function() {
|
||||
var html = '<div id="draw-reso-dialog">'
|
||||
for(var name in this._dialogEntries) {
|
||||
html += '<div>'
|
||||
+ this._dialogEntries[name].getHTML()
|
||||
+ '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// ListDialogEntry
|
||||
|
||||
|
||||
|
||||
window.plugin.drawResonators.ListDialogEntry = function(options) {
|
||||
this._name = options['name'];
|
||||
this._label = options['label'];
|
||||
this._valueFunc = options['valueFunc'];
|
||||
this._valuesList = options['valuesList'];
|
||||
this._valuesListFunc = options['valuesListFunc'];
|
||||
this._onChangeCallback = options['onChangeCallback'];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.ListDialogEntry.prototype.getHTML = function() {
|
||||
var curValue = this._valueFunc();
|
||||
var valuesList = this._valuesList ? this._valuesList : this._valuesListFunc();
|
||||
var html = '<label for="' + this.getSelectId() + '">'
|
||||
+ this._label + ': '
|
||||
+ '</label>'
|
||||
+ '<select id="' + this.getSelectId() + '">';
|
||||
|
||||
var noLabel = valuesList instanceof Array;
|
||||
for(var label in valuesList) {
|
||||
var selected = valuesList[label] === curValue;
|
||||
html += '<option value="' + valuesList[label] + '" '
|
||||
+ (selected ? 'selected="selected"' : '')
|
||||
+'>'
|
||||
+ (noLabel ? valuesList[label] : label)
|
||||
+ '</option>';
|
||||
}
|
||||
|
||||
html += '</select>';
|
||||
return html;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.ListDialogEntry.prototype.getOnEvents = function() {
|
||||
return [{'event': 'change',
|
||||
'id': this.getSelectId(),
|
||||
'callback': this._onChangeCallback
|
||||
}];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.ListDialogEntry.prototype.getSelectId = function() {
|
||||
return 'draw-reso-option-' + this._name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////// TextboxDialogEntry
|
||||
|
||||
|
||||
window.plugin.drawResonators.TextboxDialogEntry = function(options) {
|
||||
this._name = options['name'];
|
||||
this._label = options['label'];
|
||||
this._valueFunc = options['valueFunc'];
|
||||
this._onChangeCallback = options['onChangeCallback'];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.TextboxDialogEntry.prototype.getHTML = function() {
|
||||
var curValue = this._valueFunc();
|
||||
var html = '<label for="' + this.getInputId() + '">'
|
||||
+ this._label + ': '
|
||||
+ '</label>'
|
||||
+ '<input type="text" size="20" id="' + this.getInputId() + '" '
|
||||
+ 'value="' + curValue + '" />';
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
window.plugin.drawResonators.TextboxDialogEntry.prototype.getOnEvents = function() {
|
||||
return [{'event': 'change',
|
||||
'id': this.getInputId(),
|
||||
'callback': this._onChangeCallback
|
||||
}];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.TextboxDialogEntry.prototype.getInputId = function() {
|
||||
return 'draw-reso-option-' + this._name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
window.plugin.drawResonators.setupStyler = function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
|
||||
var highlightedReso = {color: '#fff', weight: 2, radius: 4, opacity: 1, clickable: false};
|
||||
var normalReso = {color: '#aaa', weight: 1, radius: 3, opacity: 1, clickable: false};
|
||||
var selectedReso = {color: '#eee', weight: 1.1, radius: 4, opacity: 1, clickable: false};
|
||||
var highlightedConn = {opacity: 0.7, weight: 3, color: '#FFA000', dashArray: '0,10,999', color: '#FFA000', fill: false, clickable: false};
|
||||
var normalConn = {opacity: 0.25, weight: 2, color: '#FFA000', dashArray: '0,10' + (new Array(25).join(',8,4')), fill: false, clickable: false};
|
||||
var selectedConn = {opacity: 0.7, weight: 3, color: '#FFA000', dashArray: '0,10' + (new Array(25).join(',8,4')), fill: false, clickable: false};
|
||||
|
||||
// Styler for highlighting resonators deployed by me
|
||||
var myReso = {
|
||||
name: 'Highlight my resonators',
|
||||
otherOptions: {
|
||||
'highlightedReso' : highlightedReso,
|
||||
'normalReso' : normalReso,
|
||||
'selectedReso' : selectedReso,
|
||||
'highlightedConn' : highlightedConn,
|
||||
'normalConn' : normalConn,
|
||||
'selectedConn' : selectedConn
|
||||
},
|
||||
resonatorStyleFunc: function(resoDetail, selected) {
|
||||
var mine = resoDetail.ownerGuid === PLAYER.guid;
|
||||
var resoSharedStyle = mine
|
||||
? this.otherOptions.highlightedReso
|
||||
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
|
||||
|
||||
var resoStyle = $.extend({
|
||||
fillColor: COLORS_LVL[resoDetail.level],
|
||||
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (mine ? 1 : 0.75)
|
||||
}, resoSharedStyle);
|
||||
return resoStyle;
|
||||
},
|
||||
connectorStyleFunc: function(resoDetail, selected) {
|
||||
var mine = resoDetail.ownerGuid === PLAYER.guid;
|
||||
var connStyle = mine
|
||||
? this.otherOptions.highlightedConn
|
||||
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
|
||||
return connStyle;
|
||||
}
|
||||
};
|
||||
|
||||
thisPlugin.render.addStyler(new thisPlugin.Styler(myReso));
|
||||
|
||||
// Styler for highlighting L8 resonators
|
||||
var l8Reso = {
|
||||
name: 'Highlight L8 resonators',
|
||||
otherOptions: {
|
||||
'highlightedReso' : highlightedReso,
|
||||
'normalReso' : normalReso,
|
||||
'selectedReso' : selectedReso,
|
||||
'highlightedConn' : highlightedConn,
|
||||
'normalConn' : normalConn,
|
||||
'selectedConn' : selectedConn
|
||||
},
|
||||
resonatorStyleFunc: function(resoDetail, selected) {
|
||||
var l8 = resoDetail.level === 8;
|
||||
var resoSharedStyle = l8
|
||||
? this.otherOptions.highlightedReso
|
||||
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
|
||||
|
||||
var resoStyle = $.extend({
|
||||
fillColor: COLORS_LVL[resoDetail.level],
|
||||
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (l8 ? 1 : 0.75)
|
||||
}, resoSharedStyle);
|
||||
return resoStyle;
|
||||
},
|
||||
connectorStyleFunc: function(resoDetail, selected) {
|
||||
var l8 = resoDetail.level === 8;
|
||||
var connStyle = l8
|
||||
? this.otherOptions.highlightedConn
|
||||
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
|
||||
return connStyle;
|
||||
}
|
||||
};
|
||||
|
||||
thisPlugin.render.addStyler(new thisPlugin.Styler(l8Reso));
|
||||
|
||||
// Styler for highlighting resonators with less than X% energy
|
||||
var lessThanXPctReso = {
|
||||
name: 'Highlight < X% resonators',
|
||||
otherOptions: {
|
||||
'highlightedReso': highlightedReso,
|
||||
'normalReso': normalReso,
|
||||
'selectedReso': selectedReso,
|
||||
'highlightedConn': highlightedConn,
|
||||
'normalConn': normalConn,
|
||||
'selectedConn': selectedConn,
|
||||
'pct': 15,
|
||||
'dialogEntry': new thisPlugin.TextboxDialogEntry({
|
||||
name: 'resoLessThanPct-pct',
|
||||
label: 'Percentage',
|
||||
valueFunc: function() {return thisPlugin.options.getOption('styler-resoLessThanPct-pct')},
|
||||
onChangeCallback: function(event) {thisPlugin.options.changeOption('styler-resoLessThanPct-pct', parseInt(event.target.value));}
|
||||
})
|
||||
},
|
||||
resonatorStyleFunc: function(resoDetail, selected) {
|
||||
var highlight = (resoDetail.energyTotal * 100) < (RESO_NRG[resoDetail.level] * this.otherOptions.pct);
|
||||
var resoSharedStyle = highlight
|
||||
? this.otherOptions.highlightedReso
|
||||
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
|
||||
|
||||
var resoStyle = $.extend({
|
||||
fillColor: COLORS_LVL[resoDetail.level],
|
||||
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level]
|
||||
}, resoSharedStyle);
|
||||
return resoStyle;
|
||||
},
|
||||
connectorStyleFunc: function(resoDetail, selected) {
|
||||
var highlight = (resoDetail.energyTotal * 100) < (RESO_NRG[resoDetail.level] * this.otherOptions.pct);
|
||||
var connStyle = highlight
|
||||
? this.otherOptions.highlightedConn
|
||||
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
|
||||
return connStyle;
|
||||
},
|
||||
onEnableFunc: function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
var thisStyler = this;
|
||||
// Add option
|
||||
thisPlugin.options.newOption('styler-resoLessThanPct-pct', 15);
|
||||
thisPlugin.options.addCallback('styler-resoLessThanPct-pct', function(value) {
|
||||
thisStyler.otherOptions.pct = value;
|
||||
thisPlugin.render.refreshStyler();
|
||||
});
|
||||
thisStyler.otherOptions.pct = thisPlugin.options.getOption('styler-resoLessThanPct-pct');
|
||||
// Add dialog entry
|
||||
thisPlugin.dialog.addEntry('resoLessThanPct-pct', this.otherOptions.dialogEntry);
|
||||
},
|
||||
onDisableFunc: function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
// Remove option
|
||||
thisPlugin.options.removeOption('styler-resoLessThanPct-pct');
|
||||
// Remove dialog entry
|
||||
thisPlugin.dialog.removeEntry('resoLessThanPct-pct');
|
||||
}
|
||||
};
|
||||
|
||||
thisPlugin.render.addStyler(new thisPlugin.Styler(lessThanXPctReso));
|
||||
|
||||
// Styler for highlighting resonators deployed by specific player
|
||||
var resoOfSpecificPlayer = {
|
||||
name: 'Highlight resonators by player',
|
||||
otherOptions: {
|
||||
'highlightedReso': highlightedReso,
|
||||
'normalReso': normalReso,
|
||||
'selectedReso': selectedReso,
|
||||
'highlightedConn': highlightedConn,
|
||||
'normalConn': normalConn,
|
||||
'selectedConn': selectedConn,
|
||||
'player': '',
|
||||
'playerGuid': '',
|
||||
'dialogEntry': new thisPlugin.TextboxDialogEntry({
|
||||
name: 'resoOfSpecificPlayer-player',
|
||||
label: 'Player name',
|
||||
valueFunc: function() {return thisPlugin.options.getOption('styler-resoOfSpecificPlayer-player')},
|
||||
onChangeCallback: function(event) {thisPlugin.options.changeOption('styler-resoOfSpecificPlayer-player', event.target.value);}
|
||||
})
|
||||
},
|
||||
resonatorStyleFunc: function(resoDetail, selected) {
|
||||
var highlight = resoDetail.ownerGuid === this.otherOptions.playerGuid;
|
||||
var resoSharedStyle = highlight
|
||||
? this.otherOptions.highlightedReso
|
||||
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
|
||||
|
||||
var resoStyle = $.extend({
|
||||
fillColor: COLORS_LVL[resoDetail.level],
|
||||
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (highlight ? 1 : 0.75)
|
||||
}, resoSharedStyle);
|
||||
return resoStyle;
|
||||
},
|
||||
connectorStyleFunc: function(resoDetail, selected) {
|
||||
var highlight = resoDetail.ownerGuid === this.otherOptions.playerGuid;
|
||||
var connStyle = highlight
|
||||
? this.otherOptions.highlightedConn
|
||||
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
|
||||
return connStyle;
|
||||
},
|
||||
onEnableFunc: function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
var thisStyler = this;
|
||||
// Add option
|
||||
thisPlugin.options.newOption('styler-resoOfSpecificPlayer-player', '');
|
||||
thisPlugin.options.addCallback('styler-resoOfSpecificPlayer-player', function(value) {
|
||||
thisStyler.otherOptions.player = value;
|
||||
thisStyler.otherOptions.playerGuid = window.playerNameToGuid(value);
|
||||
thisPlugin.render.refreshStyler();
|
||||
});
|
||||
thisStyler.otherOptions.player = thisPlugin.options.getOption('styler-resoOfSpecificPlayer-player');
|
||||
thisStyler.otherOptions.playerGuid = window.playerNameToGuid(thisStyler.otherOptions.player);
|
||||
// Add dialog entry
|
||||
thisPlugin.dialog.addEntry('resoOfSpecificPlayer-player', this.otherOptions.dialogEntry);
|
||||
},
|
||||
onDisableFunc: function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
// Remove option
|
||||
thisPlugin.options.removeOption('styler-resoOfSpecificPlayer-player');
|
||||
// Remove dialog entry
|
||||
thisPlugin.dialog.removeEntry('resoOfSpecificPlayer-player');
|
||||
}
|
||||
};
|
||||
|
||||
thisPlugin.render.addStyler(new thisPlugin.Styler(resoOfSpecificPlayer));
|
||||
|
||||
thisPlugin.render.changeStyler(thisPlugin.options.getOption('useStyler'));
|
||||
}
|
||||
|
||||
|
||||
window.plugin.drawResonators.setupOptions = function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
// Initialize options
|
||||
thisPlugin.options = new thisPlugin.Options();
|
||||
thisPlugin.options.newOption('enableZoomLevel', 17);
|
||||
thisPlugin.options.newOption('useStyler', 'Default');
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.setupDialog = function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
// Initialize dialog
|
||||
thisPlugin.dialog = new thisPlugin.Dialog();
|
||||
|
||||
var enableZoomLevelDialogEntryOptions = {
|
||||
name: 'enable-zoom-level',
|
||||
label: 'Enable zoom level',
|
||||
valueFunc: function() {return thisPlugin.options.getOption('enableZoomLevel')},
|
||||
valuesList: {'15':15, '16':16, '17':17, '18':18, '19':19, '20':20, 'None':99},
|
||||
onChangeCallback: function(event) {thisPlugin.options.changeOption('enableZoomLevel', parseInt(event.target.value));}
|
||||
};
|
||||
var enableZoomLevelDialogEntry = new thisPlugin.ListDialogEntry(enableZoomLevelDialogEntryOptions);
|
||||
thisPlugin.dialog.addEntry('enable-zoom-level', enableZoomLevelDialogEntry);
|
||||
|
||||
var stylerDialogEntryOptions = {
|
||||
name: 'use-styler',
|
||||
label: 'Styler',
|
||||
valueFunc: function() {return thisPlugin.options.getOption('useStyler')},
|
||||
valuesListFunc: thisPlugin.render.getStylersList,
|
||||
onChangeCallback: function(event) {thisPlugin.options.changeOption('useStyler', event.target.value);}
|
||||
};
|
||||
var stylerDialogEntry = new thisPlugin.ListDialogEntry(stylerDialogEntryOptions);
|
||||
thisPlugin.dialog.addEntry('use-styler', stylerDialogEntry);
|
||||
|
||||
thisPlugin.dialog.addLink();
|
||||
}
|
||||
|
||||
var setup = function() {
|
||||
var thisPlugin = window.plugin.drawResonators;
|
||||
|
||||
// Initialize options
|
||||
thisPlugin.setupOptions();
|
||||
|
||||
// Initialize render
|
||||
var renderOptions = {'enableZoomLevel': thisPlugin.options.getOption('enableZoomLevel')};
|
||||
|
||||
thisPlugin.render = new thisPlugin.Render(renderOptions);
|
||||
|
||||
// callback run at option change
|
||||
thisPlugin.options.addCallback('enableZoomLevel', thisPlugin.render.handleEnableZoomLevelChange);
|
||||
thisPlugin.options.addCallback('useStyler', thisPlugin.render.changeStyler);
|
||||
|
||||
// Initialize Dialog
|
||||
thisPlugin.setupDialog();
|
||||
// Initialize styler
|
||||
thisPlugin.setupStyler();
|
||||
|
||||
thisPlugin.render.registerHook();
|
||||
window.addLayerGroup('Resonators', thisPlugin.render.resonatorLayerGroup, true);
|
||||
}
|
||||
|
||||
// PLUGIN END //////////////////////////////////////////////////////////
|
||||
|
||||
@@PLUGINEND@@
|
@ -1,15 +1,116 @@
|
||||
// ==UserScript==
|
||||
// @id iitc-plugin-draw-resonators@xelio
|
||||
// @name IITC plugin: Draw resonators
|
||||
// @category Deleted
|
||||
// @version 0.4.0.@@DATETIMEVERSION@@
|
||||
// @category Layer
|
||||
// @version 0.4.1.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
// @description PLUGIN CURRENTLY UNAVAILABLE
|
||||
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Draw resonators on map for currently selected 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*
|
||||
// @grant none
|
||||
// ==/UserScript==
|
||||
|
||||
@@PLUGINSTART@@
|
||||
|
||||
// PLUGIN START ////////////////////////////////////////////////////////
|
||||
window.RESONATOR_MIN_ZOOM = 16;
|
||||
|
||||
// use own namespace for plugin
|
||||
window.plugin.drawResonators = function() {};
|
||||
|
||||
window.plugin.drawResonators.levelLayerGroup = null;
|
||||
|
||||
window.plugin.drawResonators.handledata = function(data) {
|
||||
window.plugin.drawResonators.levelLayerGroup.clearLayers();
|
||||
window.plugin.drawResonators.drawData(data);
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.drawData = function(portal) {
|
||||
if(window.map.getZoom() < window.RESONATOR_MIN_ZOOM) return;
|
||||
var portalDetails = portal.portalDetails;
|
||||
var portalLatLng = [portalDetails.locationE6.latE6/1E6, portalDetails.locationE6.lngE6/1E6];
|
||||
for(var i in portalDetails.resonatorArray.resonators) {
|
||||
resoData = portalDetails.resonatorArray.resonators[i];
|
||||
if(resoData === null) continue;
|
||||
|
||||
var resoLatLng = window.plugin.drawResonators.getResonatorLatLng(resoData.distanceToPortal, resoData.slot, portalLatLng);
|
||||
|
||||
var resoMarker = window.plugin.drawResonators.createResoMarker(resoData, resoLatLng);
|
||||
var connMarker = window.plugin.drawResonators.createConnMarker(resoData, resoLatLng, portalLatLng);
|
||||
|
||||
window.plugin.drawResonators.levelLayerGroup.addLayer(resoMarker);
|
||||
window.plugin.drawResonators.levelLayerGroup.addLayer(connMarker);
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.getResonatorLatLng = function(dist, slot, portalLatLng) {
|
||||
// offset in meters
|
||||
var dn = dist*SLOT_TO_LAT[slot];
|
||||
var de = dist*SLOT_TO_LNG[slot];
|
||||
|
||||
// Coordinate offset in radians
|
||||
var dLat = dn/EARTH_RADIUS;
|
||||
var dLon = de/(EARTH_RADIUS*Math.cos(Math.PI/180*portalLatLng[0]));
|
||||
|
||||
// OffsetPosition, decimal degrees
|
||||
var lat0 = portalLatLng[0] + dLat * 180/Math.PI;
|
||||
var lon0 = portalLatLng[1] + dLon * 180/Math.PI;
|
||||
|
||||
return [lat0, lon0];
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.createResoMarker = function(resoData, resoLatLng) {
|
||||
var resoProperty = {
|
||||
fillColor: COLORS_LVL[resoData.level],
|
||||
fillOpacity: resoData.energyTotal/RESO_NRG[resoData.level],
|
||||
color: '#aaa',
|
||||
weight: 1,
|
||||
radius: 3,
|
||||
opacity: 1,
|
||||
clickable: false};
|
||||
resoProperty.type = 'resonator';
|
||||
resoProperty.details = resoData;
|
||||
var reso = L.circleMarker(resoLatLng, resoProperty);
|
||||
return reso;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.createConnMarker = function(resoData, resoLatLng, portalLatLng) {
|
||||
var connProperty = {
|
||||
opacity: 0.25,
|
||||
weight: 2,
|
||||
color: '#FFA000',
|
||||
dashArray: '0,10' + (new Array(25).join(',8,4')),
|
||||
fill: false,
|
||||
clickable: false};
|
||||
connProperty.type = 'connector';
|
||||
connProperty.details = resoData;
|
||||
var conn = L.polyline([portalLatLng, resoLatLng], connProperty);
|
||||
return conn;
|
||||
}
|
||||
|
||||
window.plugin.drawResonators.zoomListener = function() {
|
||||
if(window.map.getZoom() < window.RESONATOR_MIN_ZOOM) {
|
||||
window.plugin.drawResonators.levelLayerGroup.clearLayers();
|
||||
};
|
||||
}
|
||||
|
||||
var setup = function() {
|
||||
|
||||
window.plugin.drawResonators.levelLayerGroup = new L.LayerGroup();
|
||||
|
||||
window.addLayerGroup('Draw Reso', window.plugin.drawResonators.levelLayerGroup, true);
|
||||
|
||||
window.addHook('portalDetailsUpdated', window.plugin.drawResonators.handledata);
|
||||
|
||||
window.map.on('zoomend', function() {
|
||||
window.plugin.drawResonators.zoomListener();
|
||||
});
|
||||
|
||||
}
|
||||
// PLUGIN END //////////////////////////////////////////////////////////
|
||||
|
||||
@@PLUGINEND@@
|
@ -2,7 +2,7 @@
|
||||
// @id iitc-plugin-guess-player-levels@breunigs
|
||||
// @name IITC plugin: guess player level
|
||||
// @category Info
|
||||
// @version 0.5.0.@@DATETIMEVERSION@@
|
||||
// @version 0.5.1.@@DATETIMEVERSION@@
|
||||
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
|
||||
// @updateURL @@UPDATEURL@@
|
||||
// @downloadURL @@DOWNLOADURL@@
|
||||
@ -119,56 +119,80 @@ window.plugin.guessPlayerLevels.extractPortalData = function(data) {
|
||||
|
||||
var r = data.details.resonatorArray.resonators;
|
||||
|
||||
//due to the Jarvis Virus/ADA Refactor it's possible for a player to own resonators on a portal
|
||||
//at a higher level than the player themselves. It is not possible to detect for sure when this
|
||||
//has happened, but in many cases it will result in an impossible deployment arrangement
|
||||
//(over 1 L8/7 res, over 2 L6/5 res, etc). if we detect this case, ignore all resonators owned
|
||||
//by that player on the portal
|
||||
/* Due to the Jarvis Virus/ADA Refactor it's possible for a player to own resonators on a portal at a higher level
|
||||
than the player themselves. It is not possible to detect for sure when this has happened, but in many cases it will
|
||||
result in an impossible deployment arrangement (more than 1 L8/7 res, more than 2 L6/5 res, etc). If we detect this
|
||||
case, we ignore all resonators owned by that player on the portal
|
||||
Hint: This can only happen to the owner of the portal, so resonators by other players can be used to determine
|
||||
their minimal level */
|
||||
|
||||
// TODO? go further, and just ignore all resonators owned by the portal owner?
|
||||
// or; have a 'guessed' level and a 'certain' level. 'certain' comes from res from non-owner, and COMM deploy
|
||||
// while 'guessed' comes from resonators of the portal owner
|
||||
var owner = data.details.captured && data.details.captured.capturingPlayerId || "";
|
||||
var ownerModCount = 0;
|
||||
data.details.portalV2.linkedModArray.forEach(function(mod) {
|
||||
if(mod && mod.installingUser == owner)
|
||||
ownerModCount++;
|
||||
});
|
||||
|
||||
var perPlayerResMaxLevel = {};
|
||||
var perPlayerResMaxLevelCount = {};
|
||||
var players = {};
|
||||
|
||||
$.each(r, function(ind, reso) {
|
||||
if(!reso) return true;
|
||||
|
||||
if(!perPlayerResMaxLevel[reso.ownerGuid] || reso.level > perPlayerResMaxLevel[reso.ownerGuid]) {
|
||||
perPlayerResMaxLevel[reso.ownerGuid] = reso.level;
|
||||
perPlayerResMaxLevelCount[reso.ownerGuid] = 0;
|
||||
}
|
||||
if (reso.level == perPlayerResMaxLevel[reso.ownerGuid]) perPlayerResMaxLevelCount[reso.ownerGuid]++;
|
||||
if(!players[reso.ownerGuid]) players[reso.ownerGuid] = [];
|
||||
|
||||
if(players[reso.ownerGuid][reso.level] === undefined)
|
||||
players[reso.ownerGuid][reso.level] = 1
|
||||
else
|
||||
players[reso.ownerGuid][reso.level]++;
|
||||
});
|
||||
|
||||
$.each(perPlayerResMaxLevel, function(guid, level) {
|
||||
if (perPlayerResMaxLevelCount[guid] <= window.MAX_RESO_PER_PLAYER[level]) {
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel(guid, level);
|
||||
for(nickname in players) {
|
||||
var ignore = false;
|
||||
var minLevel = 0;
|
||||
|
||||
if(nickname == owner) {
|
||||
if(ownerModCount > 2) // more than 2 mods by capturing player --> portal was flipped, ignore their resonators
|
||||
continue;
|
||||
var certain = false;
|
||||
} else { // not deployed by owner - player must be at least that level
|
||||
var certain = true;
|
||||
}
|
||||
});
|
||||
|
||||
players[nickname].forEach(function(count, level) {
|
||||
if(MAX_RESO_PER_PLAYER[level] < count)
|
||||
ignore = true;
|
||||
|
||||
if(count > 0)
|
||||
minLevel = level;
|
||||
});
|
||||
|
||||
if(ignore)
|
||||
continue;
|
||||
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel(nickname, minLevel, certain);
|
||||
}
|
||||
}
|
||||
|
||||
window.plugin.guessPlayerLevels.extractChatData = function(data) {
|
||||
data.raw.result.forEach(function(msg) {
|
||||
var plext = msg[2].plext;
|
||||
if(plext.plextType == 'SYSTEM_BROADCAST'
|
||||
&& plext.markup.length==5
|
||||
&& plext.markup[0][0] == 'PLAYER'
|
||||
&& plext.markup[1][0] == 'TEXT'
|
||||
&& plext.markup[1][1].plain == ' deployed an '
|
||||
&& plext.markup[2][0] == 'TEXT'
|
||||
&& plext.markup[2][0] == 'TEXT'
|
||||
&& plext.markup[3][0] == 'TEXT'
|
||||
&& plext.markup[3][1].plain == ' Resonator on ') {
|
||||
var nick = plext.markup[0][1].plain;
|
||||
var lvl = parseInt(plext.markup[2][1].plain.substr(1));
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel(nick, lvl, true);
|
||||
}
|
||||
});
|
||||
data.raw.result.forEach(function(msg) {
|
||||
var plext = msg[2].plext;
|
||||
if(plext.plextType == 'SYSTEM_BROADCAST'
|
||||
&& plext.markup.length==5
|
||||
&& plext.markup[0][0] == 'PLAYER'
|
||||
&& plext.markup[1][0] == 'TEXT'
|
||||
&& plext.markup[1][1].plain == ' deployed an '
|
||||
&& plext.markup[2][0] == 'TEXT'
|
||||
&& plext.markup[2][0] == 'TEXT'
|
||||
&& plext.markup[3][0] == 'TEXT'
|
||||
&& plext.markup[3][1].plain == ' Resonator on ') {
|
||||
var nick = plext.markup[0][1].plain;
|
||||
var lvl = parseInt(plext.markup[2][1].plain.substr(1));
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel(nick, lvl, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, safe) {
|
||||
window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, certain) {
|
||||
var cache = window.plugin.guessPlayerLevels._loadLevels();
|
||||
|
||||
var details = cache['#' + nick];
|
||||
@ -177,7 +201,7 @@ window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, safe) {
|
||||
if(typeof details === 'number')
|
||||
details = {min: 1, guessed: details};
|
||||
|
||||
if(safe) {
|
||||
if(certain) {
|
||||
if(details.min >= level)
|
||||
return;
|
||||
|
||||
|
@ -26,10 +26,16 @@ window.plugin.panControl.setup = function() {
|
||||
try { console.log('Loading Leaflet.Pancontrol JS now'); } catch(e) {}
|
||||
@@INCLUDERAW:external/L.Control.Pan.js@@
|
||||
try { console.log('done loading Leaflet.Pancontrol JS'); } catch(e) {}
|
||||
|
||||
|
||||
// prevent Pancontrol from being activated by default (e.g. in minimap)
|
||||
L.Map.mergeOptions({
|
||||
panControl: false
|
||||
});
|
||||
|
||||
|
||||
window.map.panControl = L.control.pan({panOffset: 350});
|
||||
window.map.addControl(window.map.panControl);
|
||||
|
||||
|
||||
if(map.zoomControl._map) { // Move above the zoom control
|
||||
window.map.removeControl(map.zoomControl);
|
||||
window.map.zoomControl = L.control.zoom();
|
||||
|