/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="fishID">The fish ID.</param> /// <param name="locations">Where the fish will spawn.</param> /// <param name="timesOfDay">When the fish will spawn.</param> /// <param name="weather">The weather in which the fish will spawn.</param> /// <param name="minFishingLevel">The minimum fishing level.</param> /// <param name="isUnique">Whether the fish can only be caught once.</param> public FishSpawnData(int fishID, FishSpawnLocationData[] locations, FishSpawnTimeOfDayData[] timesOfDay, FishSpawnWeather weather, int minFishingLevel, bool isUnique) { this.FishID = fishID; this.Locations = locations; this.TimesOfDay = timesOfDay; this.Weather = weather; this.MinFishingLevel = minFishingLevel; this.IsUnique = isUnique; }
/// <summary>Read parsed data about the spawn rules for a specific fish.</summary> /// <param name="fishID">The fish ID.</param> /// <param name="metadata">Provides metadata that's not available from the game data directly.</param> /// <remarks>Derived from <see cref="GameLocation.getFish"/>.</remarks> public FishSpawnData GetFishSpawnRules(int fishID, Metadata metadata) { // get raw fish data string[] fishFields; { if (!Game1.content.Load <Dictionary <int, string> >("Data\\Fish").TryGetValue(fishID, out string rawData)) { return(null); } fishFields = rawData.Split('/'); if (fishFields.Length < 13) { return(null); } } // parse location data var locations = new List <FishSpawnLocationData>(); foreach (var entry in Game1.content.Load <Dictionary <string, string> >("Data\\Locations")) { if (metadata.IgnoreFishingLocations.Contains(entry.Key)) { continue; // ignore event data } string locationName = entry.Key; List <FishSpawnLocationData> curLocations = new List <FishSpawnLocationData>(); // get locations string[] locationFields = entry.Value.Split('/'); for (int s = 4; s <= 7; s++) { string[] seasonFields = locationFields[s].Split(' '); string season = s switch { 4 => "spring", 5 => "summer", 6 => "fall", 7 => "winter", _ => throw new NotSupportedException() // should never happen }; for (int i = 0, last = seasonFields.Length + 1; i + 1 < last; i += 2) { if (!int.TryParse(seasonFields[i], out int curFishID) || curFishID != fishID || !int.TryParse(seasonFields[i + 1], out int areaID)) { continue; } curLocations.Add(new FishSpawnLocationData(locationName, areaID, new[] { season })); } } // combine seasons for same area locations.AddRange( from areaGroup in curLocations.GroupBy(p => p.Area) let seasons = areaGroup.SelectMany(p => p.Seasons).Distinct().ToArray() select new FishSpawnLocationData(locationName, areaGroup.Key, seasons) ); } // parse fish data var timesOfDay = new List <FishSpawnTimeOfDayData>(); FishSpawnWeather weather = FishSpawnWeather.Both; int minFishingLevel = 0; bool isUnique = false; if (locations.Any()) // ignore default spawn criteria if the fish doesn't spawn naturally; in that case it should be specified explicitly in custom data below (if any) { // times of day string[] timeFields = fishFields[5].Split(' '); for (int i = 0, last = timeFields.Length + 1; i + 1 < last; i += 2) { if (int.TryParse(timeFields[i], out int minTime) && int.TryParse(timeFields[i + 1], out int maxTime)) { timesOfDay.Add(new FishSpawnTimeOfDayData(minTime, maxTime)); } } // weather if (!Enum.TryParse(fishFields[7], true, out weather)) { weather = FishSpawnWeather.Both; } // min fishing level if (!int.TryParse(fishFields[12], out minFishingLevel)) { minFishingLevel = 0; } } // read custom data if (metadata.CustomFishSpawnRules.TryGetValue(fishID, out FishSpawnData customRules)) { if (customRules.MinFishingLevel > minFishingLevel) { minFishingLevel = customRules.MinFishingLevel; } if (customRules.Weather != FishSpawnWeather.Unknown) { weather = customRules.Weather; } isUnique = isUnique || customRules.IsUnique; if (customRules.TimesOfDay != null) { timesOfDay.AddRange(customRules.TimesOfDay); } if (customRules.Locations != null) { locations.AddRange(customRules.Locations); } } // build model return(new FishSpawnData( fishID: fishID, locations: locations.ToArray(), timesOfDay: timesOfDay.ToArray(), weather: weather, minFishingLevel: minFishingLevel, isUnique: isUnique )); }