All kinds of stuff happened, I can't even. Everything seems to work OK though.

master
Skylar Ittner 8 years ago
parent cfbfe0c227
commit ba26006bac

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0" id="com.netsyms.terranquest.TerranQuest" version="1.1.2">
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0" id="com.netsyms.terranquest.TerranQuest" version="1.2">
<name>TerranQuest</name>
<description>
Augmented Reality fantasy game

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="10102" android:versionName="1.1.2" package="com.netsyms.terranquest.TerranQuest" xmlns:android="http://schemas.android.com/apk/res/android">
<manifest android:hardwareAccelerated="true" android:versionCode="10200" android:versionName="1.2" package="com.netsyms.terranquest.TerranQuest" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name" android:supportsRtl="true">

@ -494,6 +494,6 @@
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
}
}

@ -325,7 +325,7 @@ module.exports.metadata =
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
};
// BOTTOM OF METADATA
});

@ -0,0 +1,355 @@
/* global PositionError */
//////////////////////////////////////////////
// GPS and terrain stuff
//////////////////////////////////////////////
/**
* Handles GPS and terrain data.
*/
// Globals
lockGot = false;
terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
// End Globals
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
var tileurl = "http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg";
map.setZoom(17);
map.dragging.disable();
//map.touchZoom.disable();
//map.doubleClickZoom.disable();
//map.scrollWheelZoom.disable();
map.keyboard.disable();
$(".leaflet-control-zoom").css("visibility", "hidden");
// Disable tap handler, if present.
//if (map.tap) {
// map.tap.disable();
//}
// Tile layer
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.6
});
}
}).addTo(map);
var lc = L.control.locate({
position: 'topleft', // set the location of the control
layer: undefined, // use your own layer for the location marker, creates a new layer by default
drawCircle: false, // controls whether a circle is drawn that shows the uncertainty about the location
follow: true, // follow the user's location
setView: true, // automatically sets the map view to the user's location, enabled if `follow` is true
keepCurrentZoomLevel: true, // keep the current map zoom level when displaying the user's location. (if `false`, use maxZoom)
stopFollowingOnDrag: false, // stop following when the map is dragged if `follow` is true (deprecated, see below)
remainActive: true, // if true locate control remains active on click even if the user's location is in view.
markerClass: L.circleMarker, // L.circleMarker or L.marker
circleStyle: {}, // change the style of the circle around the user's location
markerStyle: {},
followCircleStyle: {}, // set difference for the style of the circle around the user's location while following
followMarkerStyle: {},
icon: 'fa fa-map-marker', // class for icon, fa-location-arrow or fa-map-marker
iconLoading: 'fa fa-spinner fa-pulse', // class for loading icon
iconElementTag: 'span', // tag for the icon element, span or i
circlePadding: [0, 0], // padding around accuracy circle, value is passed to setBounds
metric: true, // use metric or imperial units
onLocationError: function (err) {
}, // define an error callback function
onLocationOutsideMapBounds: function (context) { // called when outside map boundaries
},
showPopup: false, // display a popup when the user click on the inner marker
strings: {
title: ".", // title of the locate control
metersUnit: "meters", // string for metric units
feetUnit: "feet", // string for imperial units
popup: "You are within {distance} {unit} from this point", // text to appear if user clicks on circle
outsideMapBoundsMsg: "You seem located outside the boundaries of the map" // default message for onLocationOutsideMapBounds
},
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
//redraw('.leaflet-map-pane');
// $('.leaflet-map-plane').css('height', '90%');
// setTimeout(function () {
// $('#map').css('width', '100%');
// $('#map').css('height', '100%');
// }, 100);
}
function onPlaceTap(feature, layer) {
layer.on('click', function (e) {
openPlace(feature);
});
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
});
}
function openPlace(feature) {
$('#main-content').load("screens/place.html", null, function () {
loadPlace(feature);
$('#overlay-main').css('display', 'block');
});
}
/**
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
}
}
var updatePosition = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
}
mapPos(latitude, longitude);
};
var updateTerrain = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
var rasterurl = "http://earth.apis.netsyms.net/terrain.php?format=json&lat="
+ latitude + "&long=" + longitude;
$.get(rasterurl, function (data) {
if (data.status === 'OK') {
terraintypeid = data.typeid;
terraintypename = data.typename;
$('#terrain-image').attr('src', 'assets/terrain/' + terraintypeid + '.png');
terrainGot = true;
hideLoading();
}
}, "json").fail(function (err) {
$('#terrain-image').attr('src', 'assets/terrain/0.png');
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}
;
function onError(error) {
$('#loading-error').text("Check your device's network and location settings, and ensure a clear view of the sky.");
}
function popGPS() {
navigator.notification.alert("Latitude: " + latitude +
"\nLongitude: " + longitude +
"\nAccuracy: " + gpsaccuracy +
"\nTerrain: " + terraintypename + " (" + terraintypeid + ")",
null,
"GPS Information",
"Close");
}
$('#terrain-image').click(function () {
popGPS();
});
// Initial GPS position and stuff
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
// Update position
setInterval(function () {
navigator.geolocation.getCurrentPosition(updatePosition, onError, {timeout: 10000, enableHighAccuracy: true});
}, 1000);
// Update position + terrain
setInterval(function () {
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
loadPlaces(latitude, longitude);
}, 1000 * 20);
// Ping the server with coordinates
setInterval(pingServer, 5000);
// Show error if it's taking too long
setTimeout(function () {
onError();
}, 15 * 1000);
//////////////////////////////////////////////
// Profile, stats, and chat stuff
//////////////////////////////////////////////
/*
* Handles general server communication.
*/
/**
* Syncs the user's stats with the server and calls refreshStats().
*/
function syncStats() {
$.getJSON(mkApiUrl('getstats'), {
user: username
}, function (data) {
if (data.status === 'OK') {
maxenergy = data.stats.maxenergy;
energy = data.stats.energy;
level = data.stats.level;
refreshStats();
}
});
}
/**
* Display the current stats on the home screen.
*/
function refreshStats() {
energypercent = (energy * 1.0 / maxenergy * 1.0) * 100.0;
$('#energybar').css('width', String(energypercent) + '%');
}
function getChat() {
if (lockGot) {
$.getJSON(mkApiUrl('chat', 'cs'), {
lat: latitude,
long: longitude
}, function (data) {
data = sortResults(data, 'time', true);
var content = "";
data.forEach(function (msg) {
content += "<span class='chat-username' onclick='openProfile(\"" + msg.username + "\");'>" + msg.username + "</span> " + msg.message + "<br />";
});
$('#chatmsgs').html(content);
});
}
}
syncStats();
setInterval(function () {
syncStats();
}, 10 * 1000);
setInterval(function () {
getChat();
}, 2000);
// Send chat messages
$("#chatsendform").submit(function (event) {
message = $('#chatbox-input').val();
if (message !== '') {
$.post(mkApiUrl('chat', 'cs'), {
user: username,
lat: latitude,
long: longitude,
msg: message
}, function (data) {
if (data.status === 'OK') {
$('#chatbox-input').val("");
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
}, "json");
}
event.preventDefault();
return false;
});
function toggleChat() {
if ($('#chatmsgs').css('display') === 'none') {
openChat();
} else {
closeChat();
}
}
function closeChat() {
$('#chatmsgs').css('display', 'none');
$('#chatbox').css('height', 'auto');
}
function openChat() {
$('#chatbox').css('height', '50%');
$('#chatmsgs').css('display', 'block');
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
function openProfile(user) {
user = typeof user !== 'undefined' ? user : username;
$('#main-content').load("screens/profile.html", null, function (x) {
$('#overlay-main').css('display', 'block');
loadProfile(user);
});
}
function openRules() {
openmodal('rules', '#rules-modal');
}
function openMenu(topage) {
topage = typeof topage !== 'undefined' ? topage : "";
$('#main-content').load("screens/menu.html", null, function (x) {
$('#overlay-main').css('display', 'block');
if (topage !== '') {
$('#' + topage + '-tab').tab('show');
}
});
}
//////////////////////////////////////////////
// Other things
//////////////////////////////////////////////
function closeMain() {
$('#overlay-main').slideDown(100, function () {
$('#overlay-main').css('display', 'none');
$('#main-content').html("");
});
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {
closeMain();
} else if ($('#chatmsgs').css('display') !== 'none') {
toggleChat();
}
}, false);
// Show the rules
if (localStorage.getItem("seenrules") !== 'yes') {
openRules();
localStorage.setItem("seenrules", 'yes');
}

@ -14,8 +14,10 @@ terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
requiredaccuracy = 40;
// End Globals
var fetchplacecounter = 0;
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
@ -36,13 +38,14 @@ $(".leaflet-control-zoom").css("visibility", "hidden");
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null, 'gameinfo': {'teamid': "0"}}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
var teamcolor = "#" + getTeamColorFromId(feature.properties.gameinfo.teamid);
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
fillColor: teamcolor,
color: "#000",
weight: 1,
opacity: 1,
@ -85,10 +88,19 @@ var lc = L.control.locate({
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
// Don't update places every time
if (fetchplacecounter === 0) {
loadPlaces(latitude, longitude);
}
fetchplacecounter++;
if (fetchplacecounter > 10) {
fetchplacecounter = 0;
}
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
@ -107,17 +119,23 @@ function onPlaceTap(feature, layer) {
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
var url = mkApiUrl('places', 'gs') + "?lat=" + lat + "&long=" + long + "&radius=.25&names=1";
try {
$.getJSON(
url,
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openPlace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
}
});
);
} catch (ex) {
serverProblemsDialog();
}
}
function openPlace(feature) {
@ -131,7 +149,7 @@ function openPlace(feature) {
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
if (lockGot && terrainGot && gpsaccuracy < requiredaccuracy && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
@ -143,7 +161,7 @@ var updatePosition = function (position) {
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
if (gpsaccuracy > requiredaccuracy) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
@ -170,7 +188,7 @@ var updateTerrain = function (position) {
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
if (lockGot && gpsaccuracy < requiredaccuracy) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}

@ -21,6 +21,10 @@ function onDeviceReady() {
}
}
function serverProblemsDialog() {
openscreen("servererror");
}
function mkApiUrl(action, server) {
server = typeof server !== 'undefined' ? server : "gs";
return "http://" + server + ".terranquest.net/" + action + ".php";
@ -111,6 +115,50 @@ function closeMain() {
});
}
function getTeamInfoFromId(id) {
var team_string = "None";
var team_color = "FFFFFF";
switch (id) {
case "1":
team_string = "Water";
team_color = "00BFFF";
break;
case "2":
team_string = "Fire";
team_color = "FF4000";
break;
case "3":
team_string = "Earth";
team_color = "D1A000";
break;
case "4":
team_string = "Wind";
team_color = "96FFFF";
break;
case "5":
team_string = "Light";
team_color = "FFFF96";
break;
case "6":
team_string = "Dark";
team_color = "ABABAB";
break;
default:
team_string = "None";
team_color = "FFFFFF";
break;
}
return {'name': team_string, 'color': team_color};
}
function getTeamNameFromId(id) {
return getTeamInfoFromId(id)['name'];
}
function getTeamColorFromId(id) {
return getTeamInfoFromId(id)['color'];
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {

@ -6,34 +6,38 @@
<h4 class="modal-title" id="intro-box-header">Welcome to TerranQuest!</h4>
</div>
<div class="modal-body" id="intro-box-body-1">
<p>TerranQuest is a video game that makes you go outside. Step outdoors and discover a fantasy world overlapping our own.</p>
<p>It's dangerous to adventure alone, read this:</p>
<p>There are seven types of magic in this world. Six elements of nature: water, fire, earth, wind, light, and dark. There is also a seventh element: life. Life is the source of all magical power.</p>
<p>Long ago, the wielders of the six elements were united as one. The magics were harnessed with responsibility and respect.</p>
<p>Then disagreement and discord arose. Some become jealous of others. A great war followed, destroying much life. As a result of this bloodshed, the magic wilted and died.</p>
<p>Over time, the magic sunk deep into the Earth, living on only in dreams. Science forgot magic, and ancient knowledge was lost.</p>
<p>Now, however, the world has come full circle. Science has become magic in a different form. The new sorcerers, scientists, harness the powers of the elements with their modern tools. They know little, but the whispers of ancient power has influenced their actions.</p>
<p>The old is become new. Magic is real, it only seems different. Control the elements and bring peace to the Earth. Channel the powers of magic through your smartphone or tablet. It is up to you to give your technology a true purpose. There are those who do not want unity, who thrive in chaos. They are all the more reason to go out and fight.</p>
<p><em>Will you join the quest?</em></p>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>You have chosen well.</p>
<p>There is some knowledge you must have now. You must discover the rest of the secrets on your own.</p>
<ol class="list-group">
<li class="list-group-item">There are different types of magic in the world.</li>
<li class="list-group-item">Some types of magic are stronger in certain types of terrain.</li>
<li class="list-group-item">Weather can also affect the flow of magic through the land.</li>
<li class="list-group-item">Weather can also affect the flow of magic.</li>
<li class="list-group-item">There are strong points of magic near important landmarks.</li>
<li class="list-group-item">These points of magic can be transmuted into different types of magic.</li>
<li class="list-group-item">These points of magic can be controlled and enhanced by the different elements to achieve good and evil.</li>
</ol>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>Many years ago, there was a disagreement between the
different magical clans. A secret war, hidden from
non-magical peoples, has festered just under the surface.
Whichever clan controls all the magical points, controls the world.</p>
</div>
<div class="modal-footer">
<button type="button" onclick="gotointropage2();" class="btn btn-default" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> Next</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> OK</button>
<button type="button" onclick="navigator.app.exitApp();" class="btn btn-danger" id="lolnope-btn"><i class="fa fa-arrow-right"></i> I will not</button>
<button type="button" onclick="gotointropage2();" class="btn btn-success" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> I will</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> I am ready!</button>
</div>
</div>
</div>
</div>
<script>
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#lolnope-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
</script>

@ -1,10 +1,39 @@
<div class="scrollable-box">
<div class="list-group" id="inventory-list">
<div class="list-group-item">
<i class="fa fa-spinner fa-pulse fa-fw"></i> Loading...
</div>
</div>
</div>
<script>
function getitemhtmlfromjson(item) {
return "\
<div class='list-group-item inventory-item' id='item-" + item.itemuuid + "'>\
<h4 class='itemname'>" + item.itemname + "</h4>\
<p class='itemdesc'>" + item.itemdesc + "</p>\
<span class='itemid' style='display: none;'>" + item.itemid + "</span>\
<span class='itemclassid' style='display: none;'>" + item.classid + "</span>\
<span class='itemjson' style='display: none;'>" + item.itemjson + "</span>\
</div>";
}
function loadinventory() {
$.getJSON(mkApiUrl('inventory'), {
user: username
}, function (data) {
var content = "";
if (data.status == 'OK') {
items = data.items;
items.forEach(function (item) {
content += getitemhtmlfromjson(item);
});
} else {
content = "<div class='list-group-item'>An error occurred.</div>";
}
$('#inventory-list').html(content);
});
}
loadinventory();
</script>

@ -1,9 +1,13 @@
<div class="scrollable-box">
<div class="h4" id="place-name" style="max-width: 90%;"></div>
<div id="team-label"></div>
</div>
<script>
function loadPlace(feature) {
$("#place-name").text(feature.properties.name);
$("#team-label").text(getTeamNameFromId(feature.properties.gameinfo.teamid));
$("#team-label").css("color", "#" + getTeamColorFromId(feature.properties.gameinfo.teamid));
}
</script>

@ -5,8 +5,10 @@
<div id="loading-badges">
<i class="fa fa-spinner fa-pulse"></i> Loading...
</div>
<div class="row" id="badges">
<div class="container">
<div class="row" id="badges">
</div>
</div>
<script>
function popBadge(name, desc) {

@ -0,0 +1,20 @@
<div style="position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-color: #324150; z-index: 9999;">
<img src="assets/logonobg.svg" alt="" style="display: block; position: absolute; max-width: 90%; top: 0; left: 0; right: 0; bottom: 25%; margin: auto; max-height: 20%;" />
<p style="font-family: sans-serif; color: white; position: absolute; max-width: 90%; left: 0; right: 0; bottom: 30%; margin: auto; text-align: center;">
We are experiencing server problems. Try again later.
<br />
<i class="fa fa-exclamation-triangle fa-3x"></i>
<br />
(sorry)
<div style="background: url(assets/mountains-simple.svg) repeat-x; background-size: auto 100%; height: 20%; position: absolute; bottom: 0; width: 100%;"></div>
</div>
<script>
/*
* Stop all scheduled network activity
*/
var id = window.setTimeout(function () {}, 0);
while (id--) {
window.clearTimeout(id);
}
</script>

@ -325,7 +325,7 @@ module.exports.metadata =
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
};
// BOTTOM OF METADATA
});

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.netsyms.terranquest.TerranQuest" version="1.1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<widget id="com.netsyms.terranquest.TerranQuest" version="1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<preference name="loglevel" value="DEBUG" />
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />

@ -458,6 +458,6 @@
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
}
}

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.netsyms.terranquest.TerranQuest" version="1.1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<widget id="com.netsyms.terranquest.TerranQuest" version="1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<feature name="Device">
<param name="browser-package" value="Device" />
</feature>

@ -392,7 +392,7 @@ module.exports.metadata =
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
}
// BOTTOM OF METADATA
});

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.netsyms.terranquest.TerranQuest" version="1.1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<widget id="com.netsyms.terranquest.TerranQuest" version="1.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:gap="http://phonegap.com/ns/1.0">
<feature name="Device">
<param name="browser-package" value="Device" />
</feature>

@ -392,7 +392,7 @@ module.exports.metadata =
"cordova-plugin-media": "2.2.1-dev",
"cordova-plugin-media-capture": "1.2.1-dev",
"cordova-plugin-geolocation": "2.1.1-dev",
"phonegap-plugin-barcodescanner": "5.0.1"
"phonegap-plugin-barcodescanner": "6.0.1"
}
// BOTTOM OF METADATA
});

@ -0,0 +1,355 @@
/* global PositionError */
//////////////////////////////////////////////
// GPS and terrain stuff
//////////////////////////////////////////////
/**
* Handles GPS and terrain data.
*/
// Globals
lockGot = false;
terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
// End Globals
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
var tileurl = "http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg";
map.setZoom(17);
map.dragging.disable();
//map.touchZoom.disable();
//map.doubleClickZoom.disable();
//map.scrollWheelZoom.disable();
map.keyboard.disable();
$(".leaflet-control-zoom").css("visibility", "hidden");
// Disable tap handler, if present.
//if (map.tap) {
// map.tap.disable();
//}
// Tile layer
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.6
});
}
}).addTo(map);
var lc = L.control.locate({
position: 'topleft', // set the location of the control
layer: undefined, // use your own layer for the location marker, creates a new layer by default
drawCircle: false, // controls whether a circle is drawn that shows the uncertainty about the location
follow: true, // follow the user's location
setView: true, // automatically sets the map view to the user's location, enabled if `follow` is true
keepCurrentZoomLevel: true, // keep the current map zoom level when displaying the user's location. (if `false`, use maxZoom)
stopFollowingOnDrag: false, // stop following when the map is dragged if `follow` is true (deprecated, see below)
remainActive: true, // if true locate control remains active on click even if the user's location is in view.
markerClass: L.circleMarker, // L.circleMarker or L.marker
circleStyle: {}, // change the style of the circle around the user's location
markerStyle: {},
followCircleStyle: {}, // set difference for the style of the circle around the user's location while following
followMarkerStyle: {},
icon: 'fa fa-map-marker', // class for icon, fa-location-arrow or fa-map-marker
iconLoading: 'fa fa-spinner fa-pulse', // class for loading icon
iconElementTag: 'span', // tag for the icon element, span or i
circlePadding: [0, 0], // padding around accuracy circle, value is passed to setBounds
metric: true, // use metric or imperial units
onLocationError: function (err) {
}, // define an error callback function
onLocationOutsideMapBounds: function (context) { // called when outside map boundaries
},
showPopup: false, // display a popup when the user click on the inner marker
strings: {
title: ".", // title of the locate control
metersUnit: "meters", // string for metric units
feetUnit: "feet", // string for imperial units
popup: "You are within {distance} {unit} from this point", // text to appear if user clicks on circle
outsideMapBoundsMsg: "You seem located outside the boundaries of the map" // default message for onLocationOutsideMapBounds
},
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
//redraw('.leaflet-map-pane');
// $('.leaflet-map-plane').css('height', '90%');
// setTimeout(function () {
// $('#map').css('width', '100%');
// $('#map').css('height', '100%');
// }, 100);
}
function onPlaceTap(feature, layer) {
layer.on('click', function (e) {
openPlace(feature);
});
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
});
}
function openPlace(feature) {
$('#main-content').load("screens/place.html", null, function () {
loadPlace(feature);
$('#overlay-main').css('display', 'block');
});
}
/**
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
}
}
var updatePosition = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
}
mapPos(latitude, longitude);
};
var updateTerrain = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
var rasterurl = "http://earth.apis.netsyms.net/terrain.php?format=json&lat="
+ latitude + "&long=" + longitude;
$.get(rasterurl, function (data) {
if (data.status === 'OK') {
terraintypeid = data.typeid;
terraintypename = data.typename;
$('#terrain-image').attr('src', 'assets/terrain/' + terraintypeid + '.png');
terrainGot = true;
hideLoading();
}
}, "json").fail(function (err) {
$('#terrain-image').attr('src', 'assets/terrain/0.png');
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}
;
function onError(error) {
$('#loading-error').text("Check your device's network and location settings, and ensure a clear view of the sky.");
}
function popGPS() {
navigator.notification.alert("Latitude: " + latitude +
"\nLongitude: " + longitude +
"\nAccuracy: " + gpsaccuracy +
"\nTerrain: " + terraintypename + " (" + terraintypeid + ")",
null,
"GPS Information",
"Close");
}
$('#terrain-image').click(function () {
popGPS();
});
// Initial GPS position and stuff
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
// Update position
setInterval(function () {
navigator.geolocation.getCurrentPosition(updatePosition, onError, {timeout: 10000, enableHighAccuracy: true});
}, 1000);
// Update position + terrain
setInterval(function () {
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
loadPlaces(latitude, longitude);
}, 1000 * 20);
// Ping the server with coordinates
setInterval(pingServer, 5000);
// Show error if it's taking too long
setTimeout(function () {
onError();
}, 15 * 1000);
//////////////////////////////////////////////
// Profile, stats, and chat stuff
//////////////////////////////////////////////
/*
* Handles general server communication.
*/
/**
* Syncs the user's stats with the server and calls refreshStats().
*/
function syncStats() {
$.getJSON(mkApiUrl('getstats'), {
user: username
}, function (data) {
if (data.status === 'OK') {
maxenergy = data.stats.maxenergy;
energy = data.stats.energy;
level = data.stats.level;
refreshStats();
}
});
}
/**
* Display the current stats on the home screen.
*/
function refreshStats() {
energypercent = (energy * 1.0 / maxenergy * 1.0) * 100.0;
$('#energybar').css('width', String(energypercent) + '%');
}
function getChat() {
if (lockGot) {
$.getJSON(mkApiUrl('chat', 'cs'), {
lat: latitude,
long: longitude
}, function (data) {
data = sortResults(data, 'time', true);
var content = "";
data.forEach(function (msg) {
content += "<span class='chat-username' onclick='openProfile(\"" + msg.username + "\");'>" + msg.username + "</span> " + msg.message + "<br />";
});
$('#chatmsgs').html(content);
});
}
}
syncStats();
setInterval(function () {
syncStats();
}, 10 * 1000);
setInterval(function () {
getChat();
}, 2000);
// Send chat messages
$("#chatsendform").submit(function (event) {
message = $('#chatbox-input').val();
if (message !== '') {
$.post(mkApiUrl('chat', 'cs'), {
user: username,
lat: latitude,
long: longitude,
msg: message
}, function (data) {
if (data.status === 'OK') {
$('#chatbox-input').val("");
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
}, "json");
}
event.preventDefault();
return false;
});
function toggleChat() {
if ($('#chatmsgs').css('display') === 'none') {
openChat();
} else {
closeChat();
}
}
function closeChat() {
$('#chatmsgs').css('display', 'none');
$('#chatbox').css('height', 'auto');
}
function openChat() {
$('#chatbox').css('height', '50%');
$('#chatmsgs').css('display', 'block');
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
function openProfile(user) {
user = typeof user !== 'undefined' ? user : username;
$('#main-content').load("screens/profile.html", null, function (x) {
$('#overlay-main').css('display', 'block');
loadProfile(user);
});
}
function openRules() {
openmodal('rules', '#rules-modal');
}
function openMenu(topage) {
topage = typeof topage !== 'undefined' ? topage : "";
$('#main-content').load("screens/menu.html", null, function (x) {
$('#overlay-main').css('display', 'block');
if (topage !== '') {
$('#' + topage + '-tab').tab('show');
}
});
}
//////////////////////////////////////////////
// Other things
//////////////////////////////////////////////
function closeMain() {
$('#overlay-main').slideDown(100, function () {
$('#overlay-main').css('display', 'none');
$('#main-content').html("");
});
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {
closeMain();
} else if ($('#chatmsgs').css('display') !== 'none') {
toggleChat();
}
}, false);
// Show the rules
if (localStorage.getItem("seenrules") !== 'yes') {
openRules();
localStorage.setItem("seenrules", 'yes');
}

@ -14,8 +14,10 @@ terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
requiredaccuracy = 40;
// End Globals
var fetchplacecounter = 0;
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
@ -36,13 +38,14 @@ $(".leaflet-control-zoom").css("visibility", "hidden");
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null, 'gameinfo': {'teamid': "0"}}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
var teamcolor = "#" + getTeamColorFromId(feature.properties.gameinfo.teamid);
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
fillColor: teamcolor,
color: "#000",
weight: 1,
opacity: 1,
@ -85,10 +88,19 @@ var lc = L.control.locate({
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
// Don't update places every time
if (fetchplacecounter === 0) {
loadPlaces(latitude, longitude);
}
fetchplacecounter++;
if (fetchplacecounter > 10) {
fetchplacecounter = 0;
}
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
@ -107,17 +119,23 @@ function onPlaceTap(feature, layer) {
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
var url = mkApiUrl('places', 'gs') + "?lat=" + lat + "&long=" + long + "&radius=.25&names=1";
try {
$.getJSON(
url,
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openPlace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
}
});
);
} catch (ex) {
serverProblemsDialog();
}
}
function openPlace(feature) {
@ -131,7 +149,7 @@ function openPlace(feature) {
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
if (lockGot && terrainGot && gpsaccuracy < requiredaccuracy && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
@ -143,7 +161,7 @@ var updatePosition = function (position) {
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
if (gpsaccuracy > requiredaccuracy) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
@ -170,7 +188,7 @@ var updateTerrain = function (position) {
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
if (lockGot && gpsaccuracy < requiredaccuracy) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}

@ -21,6 +21,10 @@ function onDeviceReady() {
}
}
function serverProblemsDialog() {
openscreen("servererror");
}
function mkApiUrl(action, server) {
server = typeof server !== 'undefined' ? server : "gs";
return "http://" + server + ".terranquest.net/" + action + ".php";
@ -111,6 +115,50 @@ function closeMain() {
});
}
function getTeamInfoFromId(id) {
var team_string = "None";
var team_color = "FFFFFF";
switch (id) {
case "1":
team_string = "Water";
team_color = "00BFFF";
break;
case "2":
team_string = "Fire";
team_color = "FF4000";
break;
case "3":
team_string = "Earth";
team_color = "D1A000";
break;
case "4":
team_string = "Wind";
team_color = "96FFFF";
break;
case "5":
team_string = "Light";
team_color = "FFFF96";
break;
case "6":
team_string = "Dark";
team_color = "ABABAB";
break;
default:
team_string = "None";
team_color = "FFFFFF";
break;
}
return {'name': team_string, 'color': team_color};
}
function getTeamNameFromId(id) {
return getTeamInfoFromId(id)['name'];
}
function getTeamColorFromId(id) {
return getTeamInfoFromId(id)['color'];
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {

@ -6,34 +6,38 @@
<h4 class="modal-title" id="intro-box-header">Welcome to TerranQuest!</h4>
</div>
<div class="modal-body" id="intro-box-body-1">
<p>TerranQuest is a video game that makes you go outside. Step outdoors and discover a fantasy world overlapping our own.</p>
<p>It's dangerous to adventure alone, read this:</p>
<p>There are seven types of magic in this world. Six elements of nature: water, fire, earth, wind, light, and dark. There is also a seventh element: life. Life is the source of all magical power.</p>
<p>Long ago, the wielders of the six elements were united as one. The magics were harnessed with responsibility and respect.</p>
<p>Then disagreement and discord arose. Some become jealous of others. A great war followed, destroying much life. As a result of this bloodshed, the magic wilted and died.</p>
<p>Over time, the magic sunk deep into the Earth, living on only in dreams. Science forgot magic, and ancient knowledge was lost.</p>
<p>Now, however, the world has come full circle. Science has become magic in a different form. The new sorcerers, scientists, harness the powers of the elements with their modern tools. They know little, but the whispers of ancient power has influenced their actions.</p>
<p>The old is become new. Magic is real, it only seems different. Control the elements and bring peace to the Earth. Channel the powers of magic through your smartphone or tablet. It is up to you to give your technology a true purpose. There are those who do not want unity, who thrive in chaos. They are all the more reason to go out and fight.</p>
<p><em>Will you join the quest?</em></p>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>You have chosen well.</p>
<p>There is some knowledge you must have now. You must discover the rest of the secrets on your own.</p>
<ol class="list-group">
<li class="list-group-item">There are different types of magic in the world.</li>
<li class="list-group-item">Some types of magic are stronger in certain types of terrain.</li>
<li class="list-group-item">Weather can also affect the flow of magic through the land.</li>
<li class="list-group-item">Weather can also affect the flow of magic.</li>
<li class="list-group-item">There are strong points of magic near important landmarks.</li>
<li class="list-group-item">These points of magic can be transmuted into different types of magic.</li>
<li class="list-group-item">These points of magic can be controlled and enhanced by the different elements to achieve good and evil.</li>
</ol>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>Many years ago, there was a disagreement between the
different magical clans. A secret war, hidden from
non-magical peoples, has festered just under the surface.
Whichever clan controls all the magical points, controls the world.</p>
</div>
<div class="modal-footer">
<button type="button" onclick="gotointropage2();" class="btn btn-default" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> Next</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> OK</button>
<button type="button" onclick="navigator.app.exitApp();" class="btn btn-danger" id="lolnope-btn"><i class="fa fa-arrow-right"></i> I will not</button>
<button type="button" onclick="gotointropage2();" class="btn btn-success" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> I will</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> I am ready!</button>
</div>
</div>
</div>
</div>
<script>
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#lolnope-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
</script>

@ -1,10 +1,39 @@
<div class="scrollable-box">
<div class="list-group" id="inventory-list">
<div class="list-group-item">
<i class="fa fa-spinner fa-pulse fa-fw"></i> Loading...
</div>
</div>
</div>
<script>
function getitemhtmlfromjson(item) {
return "\
<div class='list-group-item inventory-item' id='item-" + item.itemuuid + "'>\
<h4 class='itemname'>" + item.itemname + "</h4>\
<p class='itemdesc'>" + item.itemdesc + "</p>\
<span class='itemid' style='display: none;'>" + item.itemid + "</span>\
<span class='itemclassid' style='display: none;'>" + item.classid + "</span>\
<span class='itemjson' style='display: none;'>" + item.itemjson + "</span>\
</div>";
}
function loadinventory() {
$.getJSON(mkApiUrl('inventory'), {
user: username
}, function (data) {
var content = "";
if (data.status == 'OK') {
items = data.items;
items.forEach(function (item) {
content += getitemhtmlfromjson(item);
});
} else {
content = "<div class='list-group-item'>An error occurred.</div>";
}
$('#inventory-list').html(content);
});
}
loadinventory();
</script>

@ -1,9 +1,13 @@
<div class="scrollable-box">
<div class="h4" id="place-name" style="max-width: 90%;"></div>
<div id="team-label"></div>
</div>
<script>
function loadPlace(feature) {
$("#place-name").text(feature.properties.name);
$("#team-label").text(getTeamNameFromId(feature.properties.gameinfo.teamid));
$("#team-label").css("color", "#" + getTeamColorFromId(feature.properties.gameinfo.teamid));
}
</script>

@ -5,8 +5,10 @@
<div id="loading-badges">
<i class="fa fa-spinner fa-pulse"></i> Loading...
</div>
<div class="row" id="badges">
<div class="container">
<div class="row" id="badges">
</div>
</div>
<script>
function popBadge(name, desc) {

@ -0,0 +1,20 @@
<div style="position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-color: #324150; z-index: 9999;">
<img src="assets/logonobg.svg" alt="" style="display: block; position: absolute; max-width: 90%; top: 0; left: 0; right: 0; bottom: 25%; margin: auto; max-height: 20%;" />
<p style="font-family: sans-serif; color: white; position: absolute; max-width: 90%; left: 0; right: 0; bottom: 30%; margin: auto; text-align: center;">
We are experiencing server problems. Try again later.
<br />
<i class="fa fa-exclamation-triangle fa-3x"></i>
<br />
(sorry)
<div style="background: url(assets/mountains-simple.svg) repeat-x; background-size: auto 100%; height: 20%; position: absolute; bottom: 0; width: 100%;"></div>
</div>
<script>
/*
* Stop all scheduled network activity
*/
var id = window.setTimeout(function () {}, 0);
while (id--) {
window.clearTimeout(id);
}
</script>

@ -1,13 +1,12 @@
{
"name": "phonegap-plugin-barcodescanner",
"version": "5.0.1",
"version": "6.0.1",
"description": "You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application.",
"cordova": {
"id": "phonegap-plugin-barcodescanner",
"platforms": [
"ios",
"android",
"windows8",
"windows",
"wp8",
"blackberry10",
@ -23,7 +22,6 @@
"ecosystem:phonegap",
"cordova-ios",
"cordova-android",
"cordova-windows8",
"cordova-windows",
"cordova-wp8",
"cordova-blackberry10",

@ -2,7 +2,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="phonegap-plugin-barcodescanner"
version="5.0.1">
version="6.0.1">
<name>BarcodeScanner</name>
<description>You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera) and get the metadata encoded in them for processing within your application.</description>

@ -551,7 +551,7 @@ module.exports = {
}
function checkCancelled() {
if (BarcodeReader.scanCancelled) {
if (BarcodeReader.scanCancelled || BarcodeReader.suspended) {
throw new Error('Canceled');
}
}
@ -587,8 +587,12 @@ module.exports = {
cancelled: !result
});
}, function (error) {
destroyPreview();
// Suppress null result (cancel) on suspending
if (BarcodeReader.suspended) {
return;
}
destroyPreview();
if (error.message == 'Canceled') {
success({
cancelled: true
@ -622,20 +626,46 @@ function waitForScanEnd() {
return BarcodeReader.scanPromise || WinJS.Promise.as();
}
function suspend(args) {
BarcodeReader.suspended = true;
if (args) {
args.setPromise(BarcodeReader.destroyPreview()
.then(waitForScanEnd, waitForScanEnd));
} else {
BarcodeReader.destroyPreview();
}
}
function resume() {
BarcodeReader.suspended = false;
module.exports.scan(BarcodeReader.scanCallArgs.success, BarcodeReader.scanCallArgs.fail, BarcodeReader.scanCallArgs.args);
}
function onVisibilityChanged() {
if (document.visibilityState === 'hidden'
&& BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) {
suspend();
} else if (BarcodeReader.suspended) {
resume();
}
}
// Windows 8.1 projects
document.addEventListener('msvisibilitychange', onVisibilityChanged);
// Windows 10 projects
document.addEventListener('visibilitychange', onVisibilityChanged);
// About to be suspended
app.addEventListener('checkpoint', function (args) {
if (BarcodeReader.videoPreviewIsVisible && BarcodeReader.videoPreviewIsVisible() && BarcodeReader.destroyPreview) {
BarcodeReader.suspended = true;
args.setPromise(BarcodeReader.destroyPreview()
.then(waitForScanEnd, waitForScanEnd));
suspend(args);
}
});
// Resuming from a user suspension
Windows.UI.WebUI.WebUIApplication.addEventListener("resuming", function () {
if (BarcodeReader.suspended) {
BarcodeReader.suspended = false;
module.exports.scan(BarcodeReader.scanCallArgs.success, BarcodeReader.scanCallArgs.fail, BarcodeReader.scanCallArgs.args);
resume();
}
}, false);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 65 KiB

@ -0,0 +1,355 @@
/* global PositionError */
//////////////////////////////////////////////
// GPS and terrain stuff
//////////////////////////////////////////////
/**
* Handles GPS and terrain data.
*/
// Globals
lockGot = false;
terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
// End Globals
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
var tileurl = "http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg";
map.setZoom(17);
map.dragging.disable();
//map.touchZoom.disable();
//map.doubleClickZoom.disable();
//map.scrollWheelZoom.disable();
map.keyboard.disable();
$(".leaflet-control-zoom").css("visibility", "hidden");
// Disable tap handler, if present.
//if (map.tap) {
// map.tap.disable();
//}
// Tile layer
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.6
});
}
}).addTo(map);
var lc = L.control.locate({
position: 'topleft', // set the location of the control
layer: undefined, // use your own layer for the location marker, creates a new layer by default
drawCircle: false, // controls whether a circle is drawn that shows the uncertainty about the location
follow: true, // follow the user's location
setView: true, // automatically sets the map view to the user's location, enabled if `follow` is true
keepCurrentZoomLevel: true, // keep the current map zoom level when displaying the user's location. (if `false`, use maxZoom)
stopFollowingOnDrag: false, // stop following when the map is dragged if `follow` is true (deprecated, see below)
remainActive: true, // if true locate control remains active on click even if the user's location is in view.
markerClass: L.circleMarker, // L.circleMarker or L.marker
circleStyle: {}, // change the style of the circle around the user's location
markerStyle: {},
followCircleStyle: {}, // set difference for the style of the circle around the user's location while following
followMarkerStyle: {},
icon: 'fa fa-map-marker', // class for icon, fa-location-arrow or fa-map-marker
iconLoading: 'fa fa-spinner fa-pulse', // class for loading icon
iconElementTag: 'span', // tag for the icon element, span or i
circlePadding: [0, 0], // padding around accuracy circle, value is passed to setBounds
metric: true, // use metric or imperial units
onLocationError: function (err) {
}, // define an error callback function
onLocationOutsideMapBounds: function (context) { // called when outside map boundaries
},
showPopup: false, // display a popup when the user click on the inner marker
strings: {
title: ".", // title of the locate control
metersUnit: "meters", // string for metric units
feetUnit: "feet", // string for imperial units
popup: "You are within {distance} {unit} from this point", // text to appear if user clicks on circle
outsideMapBoundsMsg: "You seem located outside the boundaries of the map" // default message for onLocationOutsideMapBounds
},
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
//redraw('.leaflet-map-pane');
// $('.leaflet-map-plane').css('height', '90%');
// setTimeout(function () {
// $('#map').css('width', '100%');
// $('#map').css('height', '100%');
// }, 100);
}
function onPlaceTap(feature, layer) {
layer.on('click', function (e) {
openPlace(feature);
});
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
});
}
function openPlace(feature) {
$('#main-content').load("screens/place.html", null, function () {
loadPlace(feature);
$('#overlay-main').css('display', 'block');
});
}
/**
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
}
}
var updatePosition = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
}
mapPos(latitude, longitude);
};
var updateTerrain = function (position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
var rasterurl = "http://earth.apis.netsyms.net/terrain.php?format=json&lat="
+ latitude + "&long=" + longitude;
$.get(rasterurl, function (data) {
if (data.status === 'OK') {
terraintypeid = data.typeid;
terraintypename = data.typename;
$('#terrain-image').attr('src', 'assets/terrain/' + terraintypeid + '.png');
terrainGot = true;
hideLoading();
}
}, "json").fail(function (err) {
$('#terrain-image').attr('src', 'assets/terrain/0.png');
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}
;
function onError(error) {
$('#loading-error').text("Check your device's network and location settings, and ensure a clear view of the sky.");
}
function popGPS() {
navigator.notification.alert("Latitude: " + latitude +
"\nLongitude: " + longitude +
"\nAccuracy: " + gpsaccuracy +
"\nTerrain: " + terraintypename + " (" + terraintypeid + ")",
null,
"GPS Information",
"Close");
}
$('#terrain-image').click(function () {
popGPS();
});
// Initial GPS position and stuff
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
// Update position
setInterval(function () {
navigator.geolocation.getCurrentPosition(updatePosition, onError, {timeout: 10000, enableHighAccuracy: true});
}, 1000);
// Update position + terrain
setInterval(function () {
navigator.geolocation.getCurrentPosition(updateTerrain, onError, {timeout: 10000, enableHighAccuracy: true});
loadPlaces(latitude, longitude);
}, 1000 * 20);
// Ping the server with coordinates
setInterval(pingServer, 5000);
// Show error if it's taking too long
setTimeout(function () {
onError();
}, 15 * 1000);
//////////////////////////////////////////////
// Profile, stats, and chat stuff
//////////////////////////////////////////////
/*
* Handles general server communication.
*/
/**
* Syncs the user's stats with the server and calls refreshStats().
*/
function syncStats() {
$.getJSON(mkApiUrl('getstats'), {
user: username
}, function (data) {
if (data.status === 'OK') {
maxenergy = data.stats.maxenergy;
energy = data.stats.energy;
level = data.stats.level;
refreshStats();
}
});
}
/**
* Display the current stats on the home screen.
*/
function refreshStats() {
energypercent = (energy * 1.0 / maxenergy * 1.0) * 100.0;
$('#energybar').css('width', String(energypercent) + '%');
}
function getChat() {
if (lockGot) {
$.getJSON(mkApiUrl('chat', 'cs'), {
lat: latitude,
long: longitude
}, function (data) {
data = sortResults(data, 'time', true);
var content = "";
data.forEach(function (msg) {
content += "<span class='chat-username' onclick='openProfile(\"" + msg.username + "\");'>" + msg.username + "</span> " + msg.message + "<br />";
});
$('#chatmsgs').html(content);
});
}
}
syncStats();
setInterval(function () {
syncStats();
}, 10 * 1000);
setInterval(function () {
getChat();
}, 2000);
// Send chat messages
$("#chatsendform").submit(function (event) {
message = $('#chatbox-input').val();
if (message !== '') {
$.post(mkApiUrl('chat', 'cs'), {
user: username,
lat: latitude,
long: longitude,
msg: message
}, function (data) {
if (data.status === 'OK') {
$('#chatbox-input').val("");
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
}, "json");
}
event.preventDefault();
return false;
});
function toggleChat() {
if ($('#chatmsgs').css('display') === 'none') {
openChat();
} else {
closeChat();
}
}
function closeChat() {
$('#chatmsgs').css('display', 'none');
$('#chatbox').css('height', 'auto');
}
function openChat() {
$('#chatbox').css('height', '50%');
$('#chatmsgs').css('display', 'block');
$("#chatmsgs").animate({scrollTop: $('#chatmsgs').prop("scrollHeight")}, 1000);
}
function openProfile(user) {
user = typeof user !== 'undefined' ? user : username;
$('#main-content').load("screens/profile.html", null, function (x) {
$('#overlay-main').css('display', 'block');
loadProfile(user);
});
}
function openRules() {
openmodal('rules', '#rules-modal');
}
function openMenu(topage) {
topage = typeof topage !== 'undefined' ? topage : "";
$('#main-content').load("screens/menu.html", null, function (x) {
$('#overlay-main').css('display', 'block');
if (topage !== '') {
$('#' + topage + '-tab').tab('show');
}
});
}
//////////////////////////////////////////////
// Other things
//////////////////////////////////////////////
function closeMain() {
$('#overlay-main').slideDown(100, function () {
$('#overlay-main').css('display', 'none');
$('#main-content').html("");
});
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {
closeMain();
} else if ($('#chatmsgs').css('display') !== 'none') {
toggleChat();
}
}, false);
// Show the rules
if (localStorage.getItem("seenrules") !== 'yes') {
openRules();
localStorage.setItem("seenrules", 'yes');
}

@ -14,8 +14,10 @@ terrainGot = false;
latitude = 0.0000;
longitude = 0.0000;
gpsaccuracy = 9999;
requiredaccuracy = 40;
// End Globals
var fetchplacecounter = 0;
var lastgpstime = 0;
var terraintypeid = 0;
var map = L.map('map');
@ -36,13 +38,14 @@ $(".leaflet-control-zoom").css("visibility", "hidden");
map.addLayer(new L.tileLayer(tileurl, {minZoom: 17, maxZoom: 18}));
// Places layer
var placeLayer = L.geoJson(
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null}}]},
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null, 'gameinfo': {'teamid': "0"}}}]},
{
onEachFeature: onPlaceTap,
pointToLayer: function (feature, latlng) {
var teamcolor = "#" + getTeamColorFromId(feature.properties.gameinfo.teamid);
return L.circleMarker(latlng, {
radius: 14,
fillColor: "#ff7800",
fillColor: teamcolor,
color: "#000",
weight: 1,
opacity: 1,
@ -85,10 +88,19 @@ var lc = L.control.locate({
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
}).addTo(map);
lc.start();
function mapPos(lat, lon) {
lockGot = true;
hideLoading();
loadPlaces(latitude, longitude);
// Don't update places every time
if (fetchplacecounter === 0) {
loadPlaces(latitude, longitude);
}
fetchplacecounter++;
if (fetchplacecounter > 10) {
fetchplacecounter = 0;
}
//map.setView(new L.LatLng(lat, lon), 16, {animate: true});
//map.panTo(new L.LatLng(lat, lon));
//map.invalidateSize();
@ -107,17 +119,23 @@ function onPlaceTap(feature, layer) {
}
function loadPlaces(lat, long) {
$.getJSON(
"http://earth.apis.netsyms.net/places.php?format=geojson&lat=" + lat + "&long=" + long + "&radius=.25&names=1",
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openplace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
var url = mkApiUrl('places', 'gs') + "?lat=" + lat + "&long=" + long + "&radius=.25&names=1";
try {
$.getJSON(
url,
function (data) {
if (data.type === 'FeatureCollection') {
placeLayer.clearLayers();
data.features.forEach(function (item) {
item.properties.popupContent = "<span class='marker-popup-text' onclick='openPlace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
placeLayer.addData(item);
});
}
}
});
);
} catch (ex) {
serverProblemsDialog();
}
}
function openPlace(feature) {
@ -131,7 +149,7 @@ function openPlace(feature) {
* Hide the loading overlay if everything is loaded, otherwise do nothing
*/
function hideLoading() {
if (lockGot && terrainGot && gpsaccuracy < 30 && $('#loading').css('display') !== 'none') {
if (lockGot && terrainGot && gpsaccuracy < requiredaccuracy && $('#loading').css('display') !== 'none') {
$('#loading').fadeOut('slow', function () {
$('#loading').css('display', 'none');
});
@ -143,7 +161,7 @@ var updatePosition = function (position) {
longitude = position.coords.longitude;
lastgpstime = position.timestamp;
gpsaccuracy = position.coords.accuracy;
if (gpsaccuracy > 30) {
if (gpsaccuracy > requiredaccuracy) {
$('#no-lock').css('display', 'block');
} else {
$('#no-lock').css('display', 'none');
@ -170,7 +188,7 @@ var updateTerrain = function (position) {
});
};
function pingServer() {
if (lockGot && gpsaccuracy < 30) {
if (lockGot && gpsaccuracy < requiredaccuracy) {
$.get(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude);
}
}

@ -21,6 +21,10 @@ function onDeviceReady() {
}
}
function serverProblemsDialog() {
openscreen("servererror");
}
function mkApiUrl(action, server) {
server = typeof server !== 'undefined' ? server : "gs";
return "http://" + server + ".terranquest.net/" + action + ".php";
@ -111,6 +115,50 @@ function closeMain() {
});
}
function getTeamInfoFromId(id) {
var team_string = "None";
var team_color = "FFFFFF";
switch (id) {
case "1":
team_string = "Water";
team_color = "00BFFF";
break;
case "2":
team_string = "Fire";
team_color = "FF4000";
break;
case "3":
team_string = "Earth";
team_color = "D1A000";
break;
case "4":
team_string = "Wind";
team_color = "96FFFF";
break;
case "5":
team_string = "Light";
team_color = "FFFF96";
break;
case "6":
team_string = "Dark";
team_color = "ABABAB";
break;
default:
team_string = "None";
team_color = "FFFFFF";
break;
}
return {'name': team_string, 'color': team_color};
}
function getTeamNameFromId(id) {
return getTeamInfoFromId(id)['name'];
}
function getTeamColorFromId(id) {
return getTeamInfoFromId(id)['color'];
}
// Handle back button to close things
document.addEventListener("backbutton", function (event) {
if ($('#overlay-main').css('display') !== 'none') {

@ -6,34 +6,38 @@
<h4 class="modal-title" id="intro-box-header">Welcome to TerranQuest!</h4>
</div>
<div class="modal-body" id="intro-box-body-1">
<p>TerranQuest is a video game that makes you go outside. Step outdoors and discover a fantasy world overlapping our own.</p>
<p>It's dangerous to adventure alone, read this:</p>
<p>There are seven types of magic in this world. Six elements of nature: water, fire, earth, wind, light, and dark. There is also a seventh element: life. Life is the source of all magical power.</p>
<p>Long ago, the wielders of the six elements were united as one. The magics were harnessed with responsibility and respect.</p>
<p>Then disagreement and discord arose. Some become jealous of others. A great war followed, destroying much life. As a result of this bloodshed, the magic wilted and died.</p>
<p>Over time, the magic sunk deep into the Earth, living on only in dreams. Science forgot magic, and ancient knowledge was lost.</p>
<p>Now, however, the world has come full circle. Science has become magic in a different form. The new sorcerers, scientists, harness the powers of the elements with their modern tools. They know little, but the whispers of ancient power has influenced their actions.</p>
<p>The old is become new. Magic is real, it only seems different. Control the elements and bring peace to the Earth. Channel the powers of magic through your smartphone or tablet. It is up to you to give your technology a true purpose. There are those who do not want unity, who thrive in chaos. They are all the more reason to go out and fight.</p>
<p><em>Will you join the quest?</em></p>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>You have chosen well.</p>
<p>There is some knowledge you must have now. You must discover the rest of the secrets on your own.</p>
<ol class="list-group">
<li class="list-group-item">There are different types of magic in the world.</li>
<li class="list-group-item">Some types of magic are stronger in certain types of terrain.</li>
<li class="list-group-item">Weather can also affect the flow of magic through the land.</li>
<li class="list-group-item">Weather can also affect the flow of magic.</li>
<li class="list-group-item">There are strong points of magic near important landmarks.</li>
<li class="list-group-item">These points of magic can be transmuted into different types of magic.</li>
<li class="list-group-item">These points of magic can be controlled and enhanced by the different elements to achieve good and evil.</li>
</ol>
</div>
<div class="modal-body" id="intro-box-body-2" style='display: none;'>
<p>Many years ago, there was a disagreement between the
different magical clans. A secret war, hidden from
non-magical peoples, has festered just under the surface.
Whichever clan controls all the magical points, controls the world.</p>
</div>
<div class="modal-footer">
<button type="button" onclick="gotointropage2();" class="btn btn-default" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> Next</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> OK</button>
<button type="button" onclick="navigator.app.exitApp();" class="btn btn-danger" id="lolnope-btn"><i class="fa fa-arrow-right"></i> I will not</button>
<button type="button" onclick="gotointropage2();" class="btn btn-success" id="gotopage2-btn"><i class="fa fa-arrow-right"></i> I will</button>
<button type="button" data-dismiss="modal" class="btn btn-default" style="display: none;" id="close-intro"><i class="fa fa-check"></i> I am ready!</button>
</div>
</div>
</div>
</div>
<script>
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
function gotointropage2() {
$('#intro-box-body-1').css('display', 'none');
$('#intro-box-body-2').css('display', '');
$('#gotopage2-btn').css('display', 'none');
$('#lolnope-btn').css('display', 'none');
$('#close-intro').css('display', '');
}
</script>

@ -1,10 +1,39 @@
<div class="scrollable-box">
<div class="list-group" id="inventory-list">
<div class="list-group-item">
<i class="fa fa-spinner fa-pulse fa-fw"></i> Loading...
</div>
</div>
</div>
<script>
function getitemhtmlfromjson(item) {
return "\
<div class='list-group-item inventory-item' id='item-" + item.itemuuid + "'>\
<h4 class='itemname'>" + item.itemname + "</h4>\
<p class='itemdesc'>" + item.itemdesc + "</p>\
<span class='itemid' style='display: none;'>" + item.itemid + "</span>\
<span class='itemclassid' style='display: none;'>" + item.classid + "</span>\
<span class='itemjson' style='display: none;'>" + item.itemjson + "</span>\
</div>";
}
function loadinventory() {
$.getJSON(mkApiUrl('inventory'), {
user: username
}, function (data) {
var content = "";
if (data.status == 'OK') {
items = data.items;
items.forEach(function (item) {
content += getitemhtmlfromjson(item);
});
} else {
content = "<div class='list-group-item'>An error occurred.</div>";
}
$('#inventory-list').html(content);
});
}
loadinventory();
</script>

@ -1,9 +1,13 @@
<div class="scrollable-box">
<div class="h4" id="place-name" style="max-width: 90%;"></div>
<div id="team-label"></div>
</div>
<script>
function loadPlace(feature) {
$("#place-name").text(feature.properties.name);
$("#team-label").text(getTeamNameFromId(feature.properties.gameinfo.teamid));
$("#team-label").css("color", "#" + getTeamColorFromId(feature.properties.gameinfo.teamid));
}
</script>

@ -1,61 +1,63 @@
<div class="scrollable-box">
<div class="h4" id="player-name"></div>
<p id="player-level"></p>
<div class="h5">Badges</div>
<div id="loading-badges">
<i class="fa fa-spinner fa-pulse"></i> Loading...
</div>
<div class="row" id="badges">
</div>
<script>
function popBadge(name, desc) {
navigator.notification.alert(desc, null, name, "Close");
}
function loadProfile(user) {
$('#player-name').text(user);
loadBadges(user);
loadPlayerStats(user);
}
function loadPlayerStats(user) {
$.getJSON(mkApiUrl('getstats'), {
user: user
}, function (data) {
if (data.status === 'OK' && data.stats !== null) {
$('#player-level').text('Level ' + Math.floor(data.stats.level));
} else {
$('#player-level').text('Error: cannot load player stats.');
}
}).fail(function () {
$('#player-level').text('Error: Loading failed. <a onclick="loadProfile(\'' + user + '\')">Reload</a>"');
});
}
function loadBadges(user) {
$('#loading-badges').html('<i class="fa fa-spinner fa-pulse"></i> Loading...');
$('#loading-badges').css('display', 'block');
$.getJSON(
mkApiUrl('getbadges') + '?user=' + user,
function (data) {
if (data.status === 'OK') {
data.badges.forEach(function (item) {
$('#badges').append('<div class="col col-xs-3 col-md-2 col-lg-1" \
onclick="popBadge(\'' + item.badgename + '\', \'' + item.badgedesc + '\')">\n\
<img class="badge-img img-circle img-responsive" alt="" src="assets/badges/' + item.badgesid + '.png"/>\n\
</div>');
});
$('#loading-badges').css('display', 'none');
} else {
$('#loading-badges').html('Loading failed. <a onclick="loadAchievements(\'' + user + '\')">Reload</a>"');
}
}
).fail(
function (err) {
$('#loading-badges').html('Loading failed. <a onclick="loadProfile(\'' + user + '\')">Reload</a>"');
}
);
}
</script>
<div class="scrollable-box">
<div class="h4" id="player-name"></div>
<p id="player-level"></p>
<div class="h5">Badges</div>
<div id="loading-badges">
<i class="fa fa-spinner fa-pulse"></i> Loading...
</div>
<div class="container">
<div class="row" id="badges">
</div>
</div>
<script>
function popBadge(name, desc) {
navigator.notification.alert(desc, null, name, "Close");
}
function loadProfile(user) {
$('#player-name').text(user);
loadBadges(user);
loadPlayerStats(user);
}
function loadPlayerStats(user) {
$.getJSON(mkApiUrl('getstats'), {
user: user
}, function (data) {
if (data.status === 'OK' && data.stats !== null) {
$('#player-level').text('Level ' + Math.floor(data.stats.level));
} else {
$('#player-level').text('Error: cannot load player stats.');
}
}).fail(function () {
$('#player-level').text('Error: Loading failed. <a onclick="loadProfile(\'' + user + '\')">Reload</a>"');
});
}
function loadBadges(user) {
$('#loading-badges').html('<i class="fa fa-spinner fa-pulse"></i> Loading...');
$('#loading-badges').css('display', 'block');
$.getJSON(
mkApiUrl('getbadges') + '?user=' + user,
function (data) {
if (data.status === 'OK') {
data.badges.forEach(function (item) {
$('#badges').append('<div class="col col-xs-3 col-md-2 col-lg-1" \
onclick="popBadge(\'' + item.badgename + '\', \'' + item.badgedesc + '\')">\n\
<img class="badge-img img-circle img-responsive" alt="" src="assets/badges/' + item.badgesid + '.png"/>\n\
</div>');
});
$('#loading-badges').css('display', 'none');
} else {
$('#loading-badges').html('Loading failed. <a onclick="loadAchievements(\'' + user + '\')">Reload</a>"');
}
}
).fail(
function (err) {
$('#loading-badges').html('Loading failed. <a onclick="loadProfile(\'' + user + '\')">Reload</a>"');
}
);
}
</script>
</div>

@ -0,0 +1,20 @@
<div style="position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-color: #324150; z-index: 9999;">
<img src="assets/logonobg.svg" alt="" style="display: block; position: absolute; max-width: 90%; top: 0; left: 0; right: 0; bottom: 25%; margin: auto; max-height: 20%;" />
<p style="font-family: sans-serif; color: white; position: absolute; max-width: 90%; left: 0; right: 0; bottom: 30%; margin: auto; text-align: center;">
We are experiencing server problems. Try again later.
<br />
<i class="fa fa-exclamation-triangle fa-3x"></i>
<br />
(sorry)
<div style="background: url(assets/mountains-simple.svg) repeat-x; background-size: auto 100%; height: 20%; position: absolute; bottom: 0; width: 100%;"></div>
</div>
<script>
/*
* Stop all scheduled network activity
*/
var id = window.setTimeout(function () {}, 0);
while (id--) {
window.clearTimeout(id);
}
</script>