Index: binary-improvements/webserver/js/inventory_dialog.js
===================================================================
--- binary-improvements/webserver/js/inventory_dialog.js	(revision 250)
+++ binary-improvements/webserver/js/inventory_dialog.js	(revision 251)
@@ -19,5 +19,5 @@
 
 		if (itemdata !== null) {
-			cell.attr("style", "background-image: url(" + ITEMICONBASEURL + itemdata.name + ".png);");
+			cell.attr("style", "background-image: url(" + ITEMICONBASEURL + itemdata.icon + "@@" + itemdata.iconcolor + ".png);");
 			if (itemdata.quality >= 0) {
 				cell.attr("title", itemdata.name + " (quality: " + itemdata.quality + ")");
Index: binary-improvements/webserver/js/map.js
===================================================================
--- binary-improvements/webserver/js/map.js	(revision 250)
+++ binary-improvements/webserver/js/map.js	(revision 251)
@@ -48,5 +48,31 @@
 	var tileLayerMiniMap = GetSdtdTileLayer (mapinfo, initTime, true);
 
-
+	// player icon
+	var playerIcon = L.icon({
+	    iconUrl: '/static/leaflet/images/marker-survivor.png',
+	    iconRetinaUrl: '/static/leaflet/images/marker-survivor-2x.png',
+	    iconSize: [25, 48],
+	    iconAnchor: [12, 24],
+	    popupAnchor: [0, -20]
+	});
+	
+	// hostile icon
+	var hostileIcon = L.icon({
+	    iconUrl: '/static/leaflet/images/marker-zombie.png',
+	    iconRetinaUrl: '/static/leaflet/images/marker-zombie-2x.png',
+	    iconSize: [25, 33],
+	    iconAnchor: [12, 16],
+	    popupAnchor: [0, -10]
+	});	
+	
+	// animal icon
+	var animalIcon = L.icon({
+	    iconUrl: '/static/leaflet/images/marker-animal.png',
+	    iconRetinaUrl: '/static/leaflet/images/marker-animal-2x.png',
+	    iconSize: [25, 26],
+	    iconAnchor: [12, 13],
+	    popupAnchor: [0, -10]
+	});
+	
 
 
@@ -58,4 +84,10 @@
 	});
 	var playersOfflineMarkerGroup = L.markerClusterGroup({
+		maxClusterRadius: function(zoom) { return zoom == mapinfo.maxzoom ? 10 : 50; }
+	});
+	var hostilesMarkerGroup = L.markerClusterGroup({
+		maxClusterRadius: function(zoom) { return zoom == mapinfo.maxzoom ? 10 : 50; }
+	});
+	var animalsMarkerGroup = L.markerClusterGroup({
 		maxClusterRadius: function(zoom) { return zoom == mapinfo.maxzoom ? 10 : 50; }
 	});
@@ -107,4 +139,14 @@
 	}
 	
+	if (HasPermission ("webapi.gethostilelocation")) {
+		layerControl.addOverlay (hostilesMarkerGroup, "Hostiles (<span id='mapControlHostileCount'>0</span>)");
+		layerCount++;
+	}
+	
+	if (HasPermission ("webapi.getanimalslocation")) {
+		layerControl.addOverlay (animalsMarkerGroup, "Animals (<span id='mapControlAnimalsCount'>0</span>)");
+		layerCount++;
+	}
+	
 	if (HasPermission ("webapi.getplayerslocation")) {
 		layerControl.addOverlay (playersOfflineMarkerGroup, "Players (offline) (<span id='mapControlOfflineCount'>0</span>)");
@@ -120,7 +162,9 @@
 
 
+	var hostilesMappingList = {};
+	var animalsMappingList = {};
 	var playersMappingList = {};
 
-
+	
 
 	// ===============================================================================================
@@ -155,5 +199,5 @@
 				marker = playersMappingList[val.steamid].currentPosMarker;
 			} else {
-				marker = L.marker([val.position.x, val.position.z]).bindPopup(
+				marker = L.marker([val.position.x, val.position.z], {icon: playerIcon}).bindPopup(
 					"Player: " + val.name +
 					(HasPermission ("webapi.getplayerinventory") ?
@@ -226,4 +270,152 @@
 
 
+
+
+	// ===============================================================================================
+	// Hostiles markers
+
+	var setHostileMarkers = function(data) {
+		updatingMarkersHostile = true;
+		
+		var hostileCount = 0;
+
+		hostilesMarkerGroup.clearLayers();
+		
+		$.each( data, function( key, val ) {
+			var marker;
+			if (hostilesMappingList.hasOwnProperty(val.id)) {
+				marker = hostilesMappingList[val.id].currentPosMarker;
+			} else {
+				marker = L.marker([val.position.x, val.position.z], {icon: hostileIcon}).bindPopup(
+					"Hostile: " + val.name
+				);
+				//hostilesMappingList[val.id] = { };
+				hostilesMarkerGroup.addLayer(marker);
+			}
+
+			var bAbort = false;
+			
+			oldpos = marker.getLatLng ();
+
+			//if ( oldpos.lat != val.position.x || oldpos.lng != val.position.z ) {
+			//	hostilesMarkerGroup.removeLayer(marker);
+				marker.setLatLng([val.position.x, val.position.z]);
+				marker.setOpacity(1.0);
+				hostilesMarkerGroup.addLayer(marker);
+			//}
+
+			val.currentPosMarker = marker;
+			hostilesMappingList[val.id] = val;
+			
+			hostileCount++;
+		});
+		
+		$( "#mapControlHostileCount" ).text( hostileCount );
+		
+		updatingMarkersHostile = false;
+	}
+
+	var updateHostileTimeout;
+	var updateHostileEvent = function() {
+		$.getJSON( "../api/gethostilelocation")
+		.done(setHostileMarkers)
+		.fail(function(jqxhr, textStatus, error) {
+			console.log("Error fetching hostile list");
+		})
+		.always(function() {
+			updateHostileTimeout = window.setTimeout(updateHostileEvent, 4000);
+		});
+	}
+
+	tabs.on ("tabbedcontenttabopened", function (event, data) {
+		if (data.newTab === "#tab_map") {
+			if (HasPermission ("webapi.gethostilelocation")) {
+				updateHostileEvent ();
+			}
+		} else {
+			window.clearTimeout (updateHostileTimeout);
+		}
+	});
+	
+	if (tabs.tabbedContent ("isTabOpen", "tab_map")) {
+		if (HasPermission ("webapi.gethostilelocation")) {
+			updateHostileEvent ();
+		}
+	}
+
+
+
+	// ===============================================================================================
+	// Animals markers
+
+	var setAnimalMarkers = function(data) {
+		updatingMarkersAnimals = true;
+		
+		var animalsCount = 0;
+
+		animalsMarkerGroup.clearLayers();
+		
+		$.each( data, function( key, val ) {
+			var marker;
+			if (animalsMappingList.hasOwnProperty(val.id)) {
+				marker = animalsMappingList[val.id].currentPosMarker;
+			} else {
+				marker = L.marker([val.position.x, val.position.z], {icon: animalIcon}).bindPopup(
+					"Animal: " + val.name
+				);
+				//animalsMappingList[val.id] = { };
+				animalsMarkerGroup.addLayer(marker);
+			}
+
+			var bAbort = false;
+			
+			oldpos = marker.getLatLng ();
+
+			//if ( oldpos.lat != val.position.x || oldpos.lng != val.position.z ) {
+			//	animalsMarkerGroup.removeLayer(marker);
+				marker.setLatLng([val.position.x, val.position.z]);
+				marker.setOpacity(1.0);
+				animalsMarkerGroup.addLayer(marker);
+			//}
+
+			val.currentPosMarker = marker;
+			animalsMappingList[val.id] = val;
+			
+			animalsCount++;
+		});
+		
+		$( "#mapControlAnimalsCount" ).text( animalsCount );
+		
+		updatingMarkersAnimals = false;
+	}
+
+	var updateAnimalsTimeout;
+	var updateAnimalsEvent = function() {
+		$.getJSON( "../api/getanimalslocation")
+		.done(setAnimalMarkers)
+		.fail(function(jqxhr, textStatus, error) {
+			console.log("Error fetching animals list");
+		})
+		.always(function() {
+			updateAnimalsTimeout = window.setTimeout(updateAnimalsEvent, 4000);
+		});
+	}
+
+	tabs.on ("tabbedcontenttabopened", function (event, data) {
+		if (data.newTab === "#tab_map") {
+			if (HasPermission ("webapi.getanimalslocation")) {
+				updateAnimalsEvent ();
+			}
+		} else {
+			window.clearTimeout (updateAnimalsTimeout);
+		}
+	});
+	
+	if (tabs.tabbedContent ("isTabOpen", "tab_map")) {
+		if (HasPermission ("webapi.getanimalslocation")) {
+			updateAnimalsEvent ();
+		}
+	}
+
 }
 
Index: binary-improvements/webserver/js/stats.js
===================================================================
--- binary-improvements/webserver/js/stats.js	(revision 250)
+++ binary-improvements/webserver/js/stats.js	(revision 251)
@@ -14,4 +14,6 @@
 			$("#stats_time").html (time);
 			$("#stats_players").html (data.players);
+			$("#stats_hostiles").html (data.hostiles);
+			$("#stats_animals").html (data.animals);
 		})
 		.fail(function(jqxhr, textStatus, error) {
@@ -40,4 +42,6 @@
 			$("#stats_time").html (time);
 			$("#stats_players").html (data.players);
+			$("#stats_hostiles").html (data.hostiles);
+			$("#stats_animals").html (data.animals);
 			$("#newlogcount").html (data.newlogs);
 			if (data.newlogs > 0) {
