/// <summary> /// Converts a point in the Map coordinate system to one in the World coordinate system /// </summary> /// <param name="map">The map that the input is located in</param> /// <param name="input">The input point to convert, in Map coordinates</param> /// <returns>The input point converted to a World position</returns> public static Point ConvertToWorldPos(Rectangle continentRectangle, Rectangle mapRectangle, Point input) { double worldPosX = continentRectangle.X + (input.X - mapRectangle.X) * MapToWorldRatio; double worldPosY = continentRectangle.Y + ((mapRectangle.Y + mapRectangle.Height) - input.Y) * MapToWorldRatio; return new Point(worldPosX, worldPosY, input.Z); }
/// <summary> /// Converts a point in the World coordinate system to one in the Maps coordinate system /// </summary> /// <param name="map">The map that the input is located in</param> /// <param name="input">The input point to convert, in World coordinates</param> /// <returns>The input point converted to a Map position</returns> public static Point ConvertToMapPos(Rectangle continentRectangle, Rectangle mapRectangle, Point input) { double mapPosX = (input.X - continentRectangle.X) * WorldToMapRatio + mapRectangle.X; double mapPosY = (mapRectangle.Y + mapRectangle.Height) - (input.Y - continentRectangle.Y) * WorldToMapRatio; return new Point(mapPosX, mapPosY, input.Z); }
/// <summary> /// Converts a point in the Map coordinate system to one in the World coordinate system /// </summary> /// <param name="map">The map that the input is located in</param> /// <param name="input">The input point to convert, in Map coordinates</param> /// <param name="zoom">Zoom level to consider when calculating the World position</param> /// <returns>The input point converted to a World position</returns> public static Point ConvertToWorldPos(Rectangle continentRectangle, Rectangle mapRectangle, Point input, int zoom, int maxZoom) { int factor = 1 << (maxZoom - zoom); double worldPosX = continentRectangle.X + (input.X - mapRectangle.X) * MapToWorldRatio; double worldPosY = continentRectangle.Y + ((mapRectangle.Y + mapRectangle.Height) - input.Y) * MapToWorldRatio; Point scaledOutput = new Point(worldPosX / factor, worldPosY / factor, input.Z); return scaledOutput; }
/// <summary> /// Converts a point in the World coordinate system to one in the Maps coordinate system /// </summary> /// <param name="map">The map that the input is located in</param> /// <param name="input">The input point to convert, in World coordinates</param> /// <param name="zoom">Zoom level to consider when calculating the Map position</param> /// <returns>The input point converted to a Map position</returns> public static Point ConvertToMapPos(Rectangle continentRectangle, Rectangle mapRectangle, Point input, int zoom, int maxZoom) { int factor = 1 << (maxZoom - zoom); Point scaledInput = new Point(input.X * factor, input.Y * factor); double mapPosX = (scaledInput.X - continentRectangle.X) * WorldToMapRatio + mapRectangle.X; double mapPosY = (mapRectangle.Y + mapRectangle.Height) - (scaledInput.Y - continentRectangle.Y) * WorldToMapRatio; return new Point(mapPosX, mapPosY, input.Z); }
/// <summary> /// Retrieves a collection of zone items located in the given continent /// </summary> /// <param name="continentId">ID of the continent</param> /// <returns></returns> public IEnumerable<ZoneItem> GetZoneItemsByContinent(int continentId) { ConcurrentDictionary<int, ZoneItem> pointsOfInterest = new ConcurrentDictionary<int, ZoneItem>(); ConcurrentDictionary<int, ZoneItem> tasks = new ConcurrentDictionary<int, ZoneItem>(); ConcurrentDictionary<int, ZoneItem> heroPoints = new ConcurrentDictionary<int, ZoneItem>(); try { // Get the continents (used later in determining the location of items) var continent = this.GetContinent(continentId); Parallel.ForEach(continent.FloorIds, floorId => { var floor = this.GetFloor(continentId, floorId); if (floor != null && floor.Regions != null) { foreach (var region in floor.Regions) { foreach (var subRegion in region.Value.Maps) { var continentRectangle = new Rectangle() { X = subRegion.Value.ContinentRectangle.X, Y = subRegion.Value.ContinentRectangle.Y, Height = subRegion.Value.ContinentRectangle.Height, Width = subRegion.Value.ContinentRectangle.Width }; var mapRectangle = new Rectangle() { X = subRegion.Value.MapRectangle.X, Y = subRegion.Value.MapRectangle.Y, Height = subRegion.Value.MapRectangle.Height, Width = subRegion.Value.MapRectangle.Width }; // Points of Interest foreach (var item in subRegion.Value.PointsOfInterest) { // If we haven't already added the item, get it's info and add it if (!pointsOfInterest.ContainsKey(item.PointOfInterestId)) { // Determine the location var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(item.Coordinates.X, item.Coordinates.Y)); ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = item.PointOfInterestId; zoneItem.Name = item.Name; zoneItem.ContinentLocation = new Point(item.Coordinates.X, item.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = subRegion.Value.MapId; zoneItem.MapName = this.MapNamesCache[subRegion.Value.MapId].Name; var mapChatLink = item.GetMapChatLink(); if (mapChatLink != null) zoneItem.ChatCode = mapChatLink.ToString(); // Translate the item's type if (item is GW2NET.Maps.Vista) zoneItem.Type = ZoneItemType.Vista; else if (item is GW2NET.Maps.Waypoint) zoneItem.Type = ZoneItemType.Waypoint; else if (item is GW2NET.Maps.Dungeon) zoneItem.Type = ZoneItemType.Dungeon; else zoneItem.Type = ZoneItemType.PointOfInterest; if (!pointsOfInterest.TryAdd(zoneItem.ID, zoneItem)) { logger.Warn("Failed to add {0} to PointsOfInterest collection", zoneItem); } } } // Iterate over every Task in the map (Tasks are the same as HeartQuests) foreach (var task in subRegion.Value.Tasks) { // If we haven't already added the item, get it's info and add it if (!tasks.ContainsKey(task.TaskId)) { // Determine the location var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(task.Coordinates.X, task.Coordinates.Y)); ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = task.TaskId; zoneItem.Name = task.Objective; zoneItem.Level = task.Level; zoneItem.ContinentLocation = new Point(task.Coordinates.X, task.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = subRegion.Value.MapId; zoneItem.MapName = this.MapNamesCache[subRegion.Value.MapId].Name; zoneItem.Type = ZoneItemType.HeartQuest; if (!tasks.TryAdd(zoneItem.ID, zoneItem)) { logger.Warn("Failed to add {0} to Tasks collection", zoneItem); } } } // Iterate over every skill challenge in the map foreach (var skillChallenge in subRegion.Value.SkillChallenges) { // Determine the location, this serves an internally-used ID for skill challenges var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(skillChallenge.Coordinates.X, skillChallenge.Coordinates.Y)); // Use a custom-generated ID int id = (int)(subRegion.Value.MapId + location.X + location.Y); // If we havn't already added the item, get it's info and add it if (!heroPoints.ContainsKey(id)) { ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = id; zoneItem.ContinentLocation = new Point(skillChallenge.Coordinates.X, skillChallenge.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = subRegion.Value.MapId; zoneItem.MapName = this.MapNamesCache[subRegion.Value.MapId].Name; zoneItem.Type = Data.Enums.ZoneItemType.HeroPoint; if (!heroPoints.TryAdd(zoneItem.ID, zoneItem)) { logger.Warn("Failed to add {0} to HeroPoints collection", zoneItem); } } } } } } logger.Debug("{0}-{1} done", continentId, floorId); }); } catch (Exception ex) { // Don't crash if something goes wrong, but log the error logger.Error(ex); } return pointsOfInterest.Values.Concat(tasks.Values).Concat(heroPoints.Values); }
/// <summary> /// Retrieves a collection of ZoneItems located in the zone with the given mapID /// </summary> /// <param name="mapId">The mapID of the zone to retrieve zone items for</param> /// <returns>a collection of ZoneItems located in the zone with the given mapID</returns> public IEnumerable<ZoneItem> GetZoneItems(int mapId) { List<ZoneItem> zoneItems = new List<ZoneItem>(); try { // Get the continents (used later in determining the location of items) var continents = this.GetContinents(); // Get the current map info var map = GW2.V2.Maps.ForCurrentUICulture().Find(mapId); if (map != null) { // Retrieve details of items on every floor of the map foreach (var floorId in map.Floors) { var floor = this.GetFloor(map.ContinentId, floorId); if (floor != null && floor.Regions != null) { // Find the region that this map is located in var region = floor.Regions.Values.FirstOrDefault(r => r.Maps.ContainsKey(mapId)); if (region != null) { if (region.Maps.ContainsKey(mapId)) { var regionMap = region.Maps[mapId]; var continentRectangle = new Rectangle() { X = regionMap.ContinentRectangle.X, Y = regionMap.ContinentRectangle.Y, Height = regionMap.ContinentRectangle.Height, Width = regionMap.ContinentRectangle.Width }; var mapRectangle = new Rectangle() { X = regionMap.MapRectangle.X, Y = regionMap.MapRectangle.Y, Height = regionMap.MapRectangle.Height, Width = regionMap.MapRectangle.Width }; // Points of Interest foreach (var item in regionMap.PointsOfInterest) { // If we haven't already added the item, get it's info and add it if (!zoneItems.Any(zi => zi.ID == item.PointOfInterestId)) { // Determine the location var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(item.Coordinates.X, item.Coordinates.Y)); ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = item.PointOfInterestId; zoneItem.Name = item.Name; zoneItem.ContinentLocation = new Point(item.Coordinates.X, item.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = mapId; zoneItem.MapName = map.MapName; var mapChatLink = item.GetMapChatLink(); if (mapChatLink != null) zoneItem.ChatCode = mapChatLink.ToString(); // Translate the item's type if (item is GW2NET.Maps.Vista) zoneItem.Type = ZoneItemType.Vista; else if (item is GW2NET.Maps.Waypoint) zoneItem.Type = ZoneItemType.Waypoint; else if (item is GW2NET.Maps.Dungeon) zoneItem.Type = ZoneItemType.Dungeon; else zoneItem.Type = ZoneItemType.PointOfInterest; zoneItems.Add(zoneItem); } } // Iterate over every Task in the map (Tasks are the same as HeartQuests) foreach (var task in regionMap.Tasks) { // If we haven't already added the item, get it's info and add it if (!zoneItems.Any(zi => zi.ID == task.TaskId)) { // Determine the location var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(task.Coordinates.X, task.Coordinates.Y)); ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = task.TaskId; zoneItem.Name = task.Objective; zoneItem.Level = task.Level; zoneItem.ContinentLocation = new Point(task.Coordinates.X, task.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = mapId; zoneItem.MapName = map.MapName; zoneItem.Type = ZoneItemType.HeartQuest; zoneItems.Add(zoneItem); } } // Iterate over every skill challenge in the map foreach (var skillChallenge in regionMap.SkillChallenges) { // Determine the location, this serves an internally-used ID for skill challenges var location = MapsHelper.ConvertToMapPos( continentRectangle, mapRectangle, new Point(skillChallenge.Coordinates.X, skillChallenge.Coordinates.Y)); // Use a custom-generated ID int id = (int)(mapId + location.X + location.Y); // If we havn't already added the item, get it's info and add it if (!zoneItems.Any(zi => zi.ID == id)) { ZoneItem zoneItem = new ZoneItem(); zoneItem.ID = id; zoneItem.ContinentLocation = new Point(skillChallenge.Coordinates.X, skillChallenge.Coordinates.Y); zoneItem.Location = new Point(location.X, location.Y); zoneItem.MapId = mapId; zoneItem.MapName = map.MapName; zoneItem.Type = Data.Enums.ZoneItemType.HeroPoint; zoneItems.Add(zoneItem); } } } } } } } } catch (Exception ex) { // Don't crash if something goes wrong, but log the error logger.Error(ex); } return zoneItems; }