diff --git a/ARKBreedingStats/ARKBreedingStats.csproj b/ARKBreedingStats/ARKBreedingStats.csproj
index b0efff1c1..e6fc1e5c3 100644
--- a/ARKBreedingStats/ARKBreedingStats.csproj
+++ b/ARKBreedingStats/ARKBreedingStats.csproj
@@ -84,6 +84,7 @@
+
@@ -98,6 +99,7 @@
+
@@ -130,6 +132,9 @@
Component
+
+ Form
+
UserControl
@@ -676,6 +681,8 @@
PreserveNewest
+
+
TextTemplatingFileGenerator
_manifest.json
diff --git a/ARKBreedingStats/App.config b/ARKBreedingStats/App.config
index 06dd1ae2d..aa232dee9 100644
--- a/ARKBreedingStats/App.config
+++ b/ARKBreedingStats/App.config
@@ -511,6 +511,12 @@
True
+
+ False
+
+
+ False
+
diff --git a/ARKBreedingStats/Ark.cs b/ARKBreedingStats/Ark.cs
index 70dc623ea..ec557a328 100644
--- a/ARKBreedingStats/Ark.cs
+++ b/ARKBreedingStats/Ark.cs
@@ -91,10 +91,26 @@ public static class Ark
public const byte ColorFirstId = 1;
public const byte DyeFirstIdASE = 201;
public const byte DyeMaxId = 255;
+
+ ///
+ /// When choosing a random color for a mutation, ARK can erroneously select an undefined color. For ASE that's the color id 227 (one too high to be defined).
+ ///
+ public const byte UndefinedColorIdAse = 227;
+
+ ///
+ /// When choosing a random color for a mutation, ARK can erroneously select an undefined color. For ASA that's the color id 255 (one too high to be defined).
+ ///
+ public const byte UndefinedColorIdAsa = 255;
+
///
/// When choosing a random color for a mutation, ARK can erroneously select an undefined color. Usually this is color id 227 (one too high to be defined).
///
- public const byte UndefinedColorId = 227;
+ public static byte UndefinedColorId = UndefinedColorIdAse;
+
+ ///
+ /// Sets the undefined color id to the one of ASE or ASA.
+ ///
+ public static void SetUndefinedColorId(bool asa) => UndefinedColorId = asa ? UndefinedColorIdAsa : UndefinedColorIdAse;
///
/// Number of possible color regions for all species.
diff --git a/ARKBreedingStats/AsbServer/Connection.cs b/ARKBreedingStats/AsbServer/Connection.cs
index 40a49a0ce..c8bbda87b 100644
--- a/ARKBreedingStats/AsbServer/Connection.cs
+++ b/ARKBreedingStats/AsbServer/Connection.cs
@@ -1,13 +1,11 @@
using System;
using System.IO;
using System.Linq;
-using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using System.Xml;
using ARKBreedingStats.importExportGun;
using ARKBreedingStats.Library;
using Newtonsoft.Json.Linq;
@@ -21,83 +19,115 @@ internal static class Connection
{
private const string ApiUri = "https://export.arkbreeder.com/api/v1/";
- private static SimpleCancellationToken _lastCancellationToken;
+ private static CancellationTokenSource _lastCancellationTokenSource;
public static async void StartListeningAsync(
- IProgress<(string jsonText, string serverHash, string message)> progressDataSent, string token = null)
+ IProgress progressDataSent, string token = null)
{
if (string.IsNullOrEmpty(token)) return;
// stop previous listening if any
StopListening();
- var cancellationToken = new SimpleCancellationToken();
- _lastCancellationToken = cancellationToken;
- var requestUri = ApiUri + "listen/" + token; // "https://httpstat.us/429";
-
- try
+ using (var cancellationTokenSource = new CancellationTokenSource())
{
- var client = FileService.GetHttpClient;
- using (var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead))
+ _lastCancellationTokenSource = cancellationTokenSource;
+
+ var reconnectTries = 0;
+
+ while (!cancellationTokenSource.Token.IsCancellationRequested)
{
- if (!response.IsSuccessStatusCode)
- {
- var statusCode = (int)response.StatusCode;
- string serverMessage = await response.Content.ReadAsStringAsync();
+ var requestUri = ApiUri + "listen/" + token; // "https://httpstat.us/429";
- try
- {
- serverMessage = JObject.Parse(serverMessage).SelectToken("error.message").ToString();
- }
- catch
+ try
+ {
+ var client = FileService.GetHttpClient;
+ using (var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead))
{
- // server message in unknown format, use raw content string
- }
+ if (!response.IsSuccessStatusCode)
+ {
+ var statusCode = (int)response.StatusCode;
+ string serverMessage = await response.Content.ReadAsStringAsync();
- serverMessage = Environment.NewLine + serverMessage;
+ try
+ {
+ serverMessage = JObject.Parse(serverMessage).SelectToken("error.message").ToString();
+ }
+ catch
+ {
+ // server message in unknown format, use raw content string
+ }
- switch (statusCode)
- {
- case 400: // Bad Request
- WriteMessage($"Something went wrong with the server connection.{serverMessage}", response);
- return;
- case 429: // Too Many Requests
- WriteMessage($"The server is currently at the rate limit and cannot process the request. Try again later.{serverMessage}", response);
- return;
- case 507: // Insufficient Storage
- WriteMessage($"Too many connections to the server. Try again later.{serverMessage}", response);
- return;
- default:
- var errorMessage = statusCode >= 500
- ? "Something went wrong with the server or its proxy." + Environment.NewLine
- : null;
- WriteMessage($"{errorMessage}{serverMessage}", response);
- return;
+ serverMessage = Environment.NewLine + serverMessage;
+
+ switch (statusCode)
+ {
+ case 400: // Bad Request
+ WriteErrorMessage($"Something went wrong with the server connection.{serverMessage}",
+ response);
+ return;
+ case 429: // Too Many Requests
+ WriteErrorMessage(
+ $"The server is currently at the rate limit and cannot process the request. Try again later.{serverMessage}",
+ response);
+ return;
+ case 507: // Insufficient Storage
+ WriteErrorMessage($"Too many connections to the server. Try again later.{serverMessage}",
+ response);
+ return;
+ default:
+ var errorMessage = statusCode >= 500
+ ? "Something went wrong with the server or its proxy." + Environment.NewLine
+ : null;
+ WriteErrorMessage($"{errorMessage}{serverMessage}", response);
+ return;
+ }
+ }
+
+ reconnectTries = 0;
+
+ using (var stream = await response.Content.ReadAsStreamAsync())
+ using (var reader = new StreamReader(stream))
+ {
+ var report = await ReadServerSentEvents(reader, progressDataSent, token, cancellationTokenSource.Token);
+ if (report != null)
+ {
+ progressDataSent.Report(report);
+ if (report.StopListening)
+ {
+ StopListening();
+ }
+ }
+ }
}
}
-
- using (var stream = await response.Content.ReadAsStreamAsync())
- using (var reader = new StreamReader(stream))
+ catch (Exception ex)
{
- await ReadServerSentEvents(reader, progressDataSent, token, cancellationToken);
+ var tryToReconnect = reconnectTries++ < 3;
+ WriteErrorMessage(
+ $"ASB Server listening {ex.GetType()}: {ex.Message}{Environment.NewLine}{(tryToReconnect ? "Trying to reconnect" + Environment.NewLine : string.Empty)}Stack trace: {ex.StackTrace}",
+ stopListening: !tryToReconnect);
+
+ if (!tryToReconnect)
+ break;
+ // try to reconnect after some time
+ Thread.Sleep(10_000);
}
- }
- }
- catch (Exception ex)
- {
- WriteMessage($"ASB Server listening exception:\n{ex.Message}\n\nStack trace:\n{ex.StackTrace}");
- }
- finally
- {
+ finally
+ {
#if DEBUG
- Console.WriteLine($"ASB Server listening stopped using token: {token}");
+ Console.WriteLine($"ASB Server listening stopped using token: {token}");
#endif
+ }
+ }
}
+ _lastCancellationTokenSource = null;
+
return;
// Displays an error message in the UI, also logs on the console if in debug mode
- void WriteMessage(string message, HttpResponseMessage response = null)
+ void WriteErrorMessage(string message, HttpResponseMessage response = null, bool stopListening = true)
{
if (response != null)
{
@@ -106,17 +136,24 @@ void WriteMessage(string message, HttpResponseMessage response = null)
#if DEBUG
Console.WriteLine(message);
#endif
- progressDataSent.Report((null, null, message));
+ progressDataSent.Report(new ProgressReportAsbServer { Message = message, StopListening = stopListening, IsError = true });
}
}
private static Regex _eventRegex = new Regex(@"^event: (welcome|ping|replaced|export|server|closing)(?: (\-?\d+))?(?:\ndata:\s(.+))?$");
- private static async Task ReadServerSentEvents(StreamReader reader, IProgress<(string jsonText, string serverHash, string message)> progressDataSent, string token, SimpleCancellationToken cancellationToken)
+ private static async Task ReadServerSentEvents(StreamReader reader, IProgress progressDataSent, string token, CancellationToken cancellationToken)
{
#if DEBUG
Console.WriteLine($"Now listening using token: {token}");
#endif
+ progressDataSent.Report(new ProgressReportAsbServer
+ {
+ Message = "Now listening to the export server using the token (also copied to clipboard)",
+ ServerToken = token,
+ ClipboardText = token
+ });
+
while (!cancellationToken.IsCancellationRequested)
{
var received = await reader.ReadLineAsync();
@@ -133,16 +170,19 @@ private static async Task ReadServerSentEvents(StreamReader reader, IProgress<(s
case "event: ping":
continue;
case "event: replaced":
- if (!cancellationToken.IsCancellationRequested)
- progressDataSent.Report((null, null,
- "ASB Server listening stopped. Connection used by a different user"));
- return;
+ if (cancellationToken.IsCancellationRequested) return null;
+
+ return new ProgressReportAsbServer
+ {
+ Message = "ASB Server listening stopped. Connection used by a different user",
+ StopListening = true,
+ IsError = true
+ };
case "event: closing":
// only report closing if the user hasn't done this already
- if (!cancellationToken.IsCancellationRequested)
- progressDataSent.Report((null, null,
- "ASB Server listening stopped. Connection closed by the server"));
- return;
+ if (cancellationToken.IsCancellationRequested) return null;
+ return new ProgressReportAsbServer
+ { Message = "ASB Server listening stopped. Connection closed by the server, trying to reconnect", StopListening = false, IsError = true };
}
if (received != "event: export" && !received.StartsWith("event: server"))
@@ -160,23 +200,28 @@ private static async Task ReadServerSentEvents(StreamReader reader, IProgress<(s
switch (m.Groups[1].Value)
{
case "export":
- progressDataSent.Report((m.Groups[3].Value, null, null));
+ progressDataSent.Report(new ProgressReportAsbServer { JsonText = m.Groups[3].Value });
break;
case "server":
- progressDataSent.Report((m.Groups[3].Value, m.Groups[2].Value, null));
+ progressDataSent.Report(new ProgressReportAsbServer { JsonText = m.Groups[3].Value, ServerHash = m.Groups[2].Value });
break;
}
}
}
+
+ return null;
}
+ ///
+ /// Stops the currently running listener. Returns false if no listener was running.
+ ///
public static void StopListening()
{
- if (_lastCancellationToken == null)
+ if (_lastCancellationTokenSource == null)
return; // nothing to stop
- _lastCancellationToken.Cancel();
- _lastCancellationToken = null;
+ _lastCancellationTokenSource.Cancel();
+ _lastCancellationTokenSource = null;
}
///
@@ -227,12 +272,10 @@ public static string CreateNewToken()
}
///
- /// Simple replacement of CancellationTokenSource to avoid unnecessary complexities with disposal of CTS when the token is still in use.
+ /// Returns the passed token string, or wildcards if the streamer mode is enabled.
///
- private class SimpleCancellationToken
- {
- public bool IsCancellationRequested;
- public void Cancel() => IsCancellationRequested = true;
- }
+ public static string TokenStringForDisplay(string token) => Properties.Settings.Default.StreamerMode ? "****" : token;
+
+ public static bool IsCurrentlyListening => _lastCancellationTokenSource != null;
}
}
diff --git a/ARKBreedingStats/AsbServer/ProgressReportAsbServer.cs b/ARKBreedingStats/AsbServer/ProgressReportAsbServer.cs
new file mode 100644
index 000000000..b8218e772
--- /dev/null
+++ b/ARKBreedingStats/AsbServer/ProgressReportAsbServer.cs
@@ -0,0 +1,16 @@
+namespace ARKBreedingStats.AsbServer
+{
+ ///
+ /// Info of progress reports while listening to an AsbServer.
+ ///
+ internal class ProgressReportAsbServer
+ {
+ public string JsonText;
+ public string ServerHash;
+ public string Message;
+ public string ServerToken;
+ public bool IsError;
+ public bool StopListening;
+ public string ClipboardText;
+ }
+}
diff --git a/ARKBreedingStats/BreedingPlanning/BreedingPlan.cs b/ARKBreedingStats/BreedingPlanning/BreedingPlan.cs
index bdb553126..3223138f2 100644
--- a/ARKBreedingStats/BreedingPlanning/BreedingPlan.cs
+++ b/ARKBreedingStats/BreedingPlanning/BreedingPlan.cs
@@ -52,7 +52,7 @@ public partial class BreedingPlan : UserControl
private bool[] _enabledColorRegions;
private TimeSpan _incubationTime;
private Creature _chosenCreature;
- private BreedingMode _breedingMode;
+ private BreedingScore.BreedingMode _breedingMode;
public readonly StatWeighting StatWeighting;
public bool BreedingPlanNeedsUpdate;
private bool _speciesInfoNeedsUpdate;
@@ -76,7 +76,7 @@ public BreedingPlan()
for (int i = 0; i < Stats.StatsCount; i++)
_statWeights[i] = 1;
- _breedingMode = BreedingMode.TopStatsConservative;
+ _breedingMode = BreedingScore.BreedingMode.TopStatsConservative;
_breedingPairs = new List();
pedigreeCreatureBest.SetIsVirtual(true);
@@ -286,9 +286,23 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
bool considerMutationLimit = nudBPMutationLimit.Value >= 0;
bool creaturesMutationsFilteredOut = false;
+
+ // only consider creatures with top stats if breeding for that
+ Creature[] females, males;
+ if (_breedingMode == BreedingScore.BreedingMode.BestNextGen)
+ {
+ females = _females;
+ males = _males;
+ }
+ else
+ {
+ females = _females.Where(c => c.topStatsCountBP > 0).ToArray();
+ males = _males?.Where(c => c.topStatsCountBP > 0).ToArray();
+ }
+
// filter by tags
- int crCountF = _females.Length;
- int crCountM = _males?.Length ?? 0;
+ int crCountF = females.Length;
+ int crCountM = males?.Length ?? 0;
IEnumerable selectFemales;
IEnumerable selectMales = null;
if (considerChosenCreature && (_chosenCreature.sex == Sex.Female || _currentSpecies.noGender))
@@ -297,10 +311,10 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
}
else if (!cbBPMutationLimitOnlyOnePartner.Checked && considerMutationLimit)
{
- selectFemales = FilterByTags(_females.Where(c => c.Mutations <= nudBPMutationLimit.Value));
- creaturesMutationsFilteredOut = _females.Any(c => c.Mutations > nudBPMutationLimit.Value);
+ selectFemales = FilterByTags(females.Where(c => c.Mutations <= nudBPMutationLimit.Value));
+ creaturesMutationsFilteredOut = females.Any(c => c.Mutations > nudBPMutationLimit.Value);
}
- else selectFemales = FilterByTags(_females);
+ else selectFemales = FilterByTags(females);
if (considerChosenCreature && !_currentSpecies.noGender && _chosenCreature.sex == Sex.Male)
{
@@ -308,14 +322,14 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
}
else if (!cbBPMutationLimitOnlyOnePartner.Checked && considerMutationLimit)
{
- if (_males != null)
+ if (males != null)
{
- selectMales = FilterByTags(_males.Where(c => c.Mutations <= nudBPMutationLimit.Value));
+ selectMales = FilterByTags(males.Where(c => c.Mutations <= nudBPMutationLimit.Value));
creaturesMutationsFilteredOut = creaturesMutationsFilteredOut ||
- _males.Any(c => c.Mutations > nudBPMutationLimit.Value);
+ males.Any(c => c.Mutations > nudBPMutationLimit.Value);
}
}
- else selectMales = FilterByTags(_males);
+ else selectMales = FilterByTags(males);
// filter by servers
if (cbServerFilterLibrary.Checked && (Settings.Default.FilterHideServers?.Any() ?? false))
@@ -401,18 +415,16 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
ref creaturesMutationsFilteredOut, levelLimitWithOutDomLevels, CbDontSuggestOverLimitOffspring.Checked,
cbBPOnlyOneSuggestionForFemales.Checked, _statOddEvens);
- //double minScore = _breedingPairs.LastOrDefault()?.BreedingScore ?? 0;
- //if (minScore < 0)
- //{
- // foreach (BreedingPair bp in _breedingPairs)
- // bp.BreedingScore -= minScore;
- //}
+ double minScore = _breedingPairs.LastOrDefault()?.BreedingScore.OneNumber ?? 0;
+ var displayScoreOffset = (minScore < 0 ? -minScore : 0) + .5; // don't display negative scores, could be confusing
+
+ _breedingPairs = _breedingPairs.Take(CreatureCollection.maxBreedingSuggestions).ToList();
var sb = new StringBuilder();
// draw best parents
using (var brush = new SolidBrush(Color.Black))
{
- for (int i = 0; i < _breedingPairs.Count && i < CreatureCollection.maxBreedingSuggestions; i++)
+ for (int i = 0; i < _breedingPairs.Count; i++)
{
PedigreeCreature pc;
if (2 * i < _pcs.Count)
@@ -486,7 +498,7 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
sb.AppendLine(_breedingPairs[i].Father + " can produce a mutation.");
}
- var colorPercent = (int)(_breedingPairs[i].BreedingScore.OneNumber * 12.5);
+ var colorPercent = (int)((_breedingPairs[i].BreedingScore.OneNumber + displayScoreOffset) * 12.5);
// outline
brush.Color = Utils.GetColorFromPercent(colorPercent, -.2);
g.FillRectangle(brush, 0, 15, 87, 5);
@@ -504,7 +516,7 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
}
// breeding score text
brush.Color = Color.Black;
- g.DrawString(_breedingPairs[i].BreedingScore.ToString("N4"),
+ g.DrawString((_breedingPairs[i].BreedingScore.Primary + displayScoreOffset).ToString("N4"),
new Font("Microsoft Sans Serif", 8.25f), brush, 24, 12);
pb.Image = bm;
}
@@ -526,7 +538,7 @@ private void DoCalculateBreedingScoresAndDisplayPairs()
SetParents(0);
// if breeding mode is conservative and a creature with top-stats already exists, the scoring might seem off
- if (_breedingMode == BreedingMode.TopStatsConservative)
+ if (_breedingMode == BreedingScore.BreedingMode.TopStatsConservative)
{
bool bestCreatureAlreadyAvailable = true;
Creature bestCreature = null;
@@ -795,7 +807,7 @@ private void SetBestLevels(int[] bestLevels, IEnumerable creatures, bo
crB.levelsWild[s] = bestLevels[s];
if (crB.levelsWild[s] == -1)
totalLevelUnknown = true;
- crB.topBreedingStats[s] = crB.levelsWild[s] > 0 && crB.levelsWild[s] == _bestLevels[s];
+ crB.SetTopStat(s, crB.levelsWild[s] > 0 && crB.levelsWild[s] == _bestLevels[s]);
}
crB.levelsWild[Stats.Torpidity] = crB.levelsWild.Sum();
crB.RecalculateCreatureValues(levelStep);
@@ -840,26 +852,26 @@ private void SetParents(int comboIndex)
crW.Father = father;
double probabilityBest = 1;
bool totalLevelUnknown = false; // if stats are unknown, total level is as well (==> oxygen, speed)
- bool topStatBreedingMode = _breedingMode == BreedingMode.TopStatsConservative || _breedingMode == BreedingMode.TopStatsLucky;
+ bool topStatBreedingMode = _breedingMode == BreedingScore.BreedingMode.TopStatsConservative || _breedingMode == BreedingScore.BreedingMode.TopStatsLucky;
for (int s = 0; s < Stats.StatsCount; s++)
{
if (s == Stats.Torpidity) continue;
crB.levelsWild[s] = _statWeights[s] < 0 ? Math.Min(mother.levelsWild[s], father.levelsWild[s]) : BreedingScore.GetHigherBestLevel(mother.levelsWild[s], father.levelsWild[s], _statOddEvens[s]);
crB.levelsMutated[s] = (crB.levelsWild[s] == mother.levelsWild[s] ? mother : father).levelsMutated?[s] ?? 0;
crB.valuesBreeding[s] = StatValueCalculation.CalculateValue(_currentSpecies, s, crB.levelsWild[s], crB.levelsMutated[s], 0, true, 1, 0);
- crB.topBreedingStats[s] = (_currentSpecies.stats[s].IncPerTamedLevel != 0 && crB.levelsWild[s] == _bestLevels[s]);
+ crB.SetTopStat(s, _currentSpecies.stats[s].IncPerTamedLevel != 0 && crB.levelsWild[s] == _bestLevels[s]);
crW.levelsWild[s] = _statWeights[s] < 0 ? Math.Max(mother.levelsWild[s], father.levelsWild[s]) : Math.Min(mother.levelsWild[s], father.levelsWild[s]);
crB.levelsMutated[s] = (crW.levelsWild[s] == mother.levelsWild[s] ? mother : father).levelsMutated?[s] ?? 0;
crW.valuesBreeding[s] = StatValueCalculation.CalculateValue(_currentSpecies, s, crW.levelsWild[s], crW.levelsMutated[s], 0, true, 1, 0);
- crW.topBreedingStats[s] = (_currentSpecies.stats[s].IncPerTamedLevel != 0 && crW.levelsWild[s] == _bestLevels[s]);
+ crW.SetTopStat(s, _currentSpecies.stats[s].IncPerTamedLevel != 0 && crW.levelsWild[s] == _bestLevels[s]);
if (crB.levelsWild[s] == -1 || crW.levelsWild[s] == -1)
totalLevelUnknown = true;
// in top stats breeding mode consider only probability of top stats
if (crB.levelsWild[s] > crW.levelsWild[s]
- && (!topStatBreedingMode || crB.topBreedingStats[s]))
+ && (!topStatBreedingMode || crB.IsTopStat(s)))
probabilityBest *= Ark.ProbabilityInheritHigherLevel;
else if (crB.levelsWild[s] < crW.levelsWild[s]
- && (!topStatBreedingMode || crB.topBreedingStats[s]))
+ && (!topStatBreedingMode || crB.IsTopStat(s)))
probabilityBest *= Ark.ProbabilityInheritLowerLevel;
}
crB.levelsWild[Stats.Torpidity] = crB.levelsWild.Sum();
@@ -984,7 +996,7 @@ private void radioButtonBPTopStatsCn_CheckedChanged(object sender, EventArgs e)
{
if (rbBPTopStatsCn.Checked)
{
- _breedingMode = BreedingMode.TopStatsConservative;
+ _breedingMode = BreedingScore.BreedingMode.TopStatsConservative;
CalculateBreedingScoresAndDisplayPairs();
}
}
@@ -993,7 +1005,7 @@ private void radioButtonBPTopStats_CheckedChanged(object sender, EventArgs e)
{
if (rbBPTopStats.Checked)
{
- _breedingMode = BreedingMode.TopStatsLucky;
+ _breedingMode = BreedingScore.BreedingMode.TopStatsLucky;
CalculateBreedingScoresAndDisplayPairs();
}
}
@@ -1002,7 +1014,7 @@ private void radioButtonBPHighStats_CheckedChanged(object sender, EventArgs e)
{
if (rbBPHighStats.Checked)
{
- _breedingMode = BreedingMode.BestNextGen;
+ _breedingMode = BreedingScore.BreedingMode.BestNextGen;
CalculateBreedingScoresAndDisplayPairs();
}
}
@@ -1096,13 +1108,6 @@ public bool IgnoreSexInBreedingPlan
set => CbIgnoreSexInPlanning.Checked = value;
}
- public enum BreedingMode
- {
- BestNextGen,
- TopStatsLucky,
- TopStatsConservative
- }
-
private void cbTagExcludeDefault_CheckedChanged(object sender, EventArgs e)
{
CalculateBreedingScoresAndDisplayPairs();
diff --git a/ARKBreedingStats/BreedingPlanning/BreedingScore.cs b/ARKBreedingStats/BreedingPlanning/BreedingScore.cs
index d5b05bc90..1c6c5415b 100644
--- a/ARKBreedingStats/BreedingPlanning/BreedingScore.cs
+++ b/ARKBreedingStats/BreedingPlanning/BreedingScore.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using ARKBreedingStats.Library;
-using ARKBreedingStats.Properties;
using ARKBreedingStats.species;
namespace ARKBreedingStats.BreedingPlanning
@@ -32,7 +31,7 @@ public static class BreedingScore
/// Array for each stat if the higher level should be considered for score: 0: consider any level, 1: consider only if odd, 2: consider only if even.
///
public static List CalculateBreedingScores(Creature[] females, Creature[] males, Species species,
- short[] bestPossLevels, double[] statWeights, int[] bestLevelsOfSpecies, BreedingPlan.BreedingMode breedingMode,
+ short[] bestPossLevels, double[] statWeights, int[] bestLevelsOfSpecies, BreedingMode breedingMode,
bool considerChosenCreature, bool considerMutationLimit, int mutationLimit,
ref bool creaturesMutationsFilteredOut, int offspringLevelLimit = 0, bool downGradeOffspringWithLevelHigherThanLimit = false,
bool onlyBestSuggestionForFemale = false, byte[] anyOddEven = null)
@@ -86,8 +85,8 @@ public static List CalculateBreedingScores(Creature[] females, Cre
{
if (s == Stats.Torpidity || !species.UsesStat(s)) continue;
bestPossLevels[s] = 0;
- int higherLevel = Math.Max(female.levelsWild[s] + (female.levelsMutated?[s] ?? 0), male.levelsWild[s] + (male.levelsMutated?[s] ?? 0));
- int lowerLevel = Math.Min(female.levelsWild[s] + (female.levelsMutated?[s] ?? 0), male.levelsWild[s] + (male.levelsMutated?[s] ?? 0));
+ int higherLevel = Math.Max(female.levelsWild[s], male.levelsWild[s]);
+ int lowerLevel = Math.Min(female.levelsWild[s], male.levelsWild[s]);
if (higherLevel < 0) higherLevel = 0;
if (lowerLevel < 0) lowerLevel = 0;
maxPossibleOffspringLevel += higherLevel;
@@ -112,7 +111,7 @@ public static List CalculateBreedingScores(Creature[] females, Cre
double weightedExpectedStatLevel = statWeights[s] * (Ark.ProbabilityInheritHigherLevel * higherLevel + Ark.ProbabilityInheritLowerLevel * lowerLevel) / 40;
if (weightedExpectedStatLevel != 0)
{
- if (breedingMode == BreedingPlan.BreedingMode.TopStatsLucky)
+ if (breedingMode == BreedingMode.TopStatsLucky)
{
if (!ignoreTopStats && (female.levelsWild[s] == bestLevelsOfSpecies[s] || male.levelsWild[s] == bestLevelsOfSpecies[s]))
{
@@ -122,7 +121,7 @@ public static List CalculateBreedingScores(Creature[] females, Cre
else if (bestLevelsOfSpecies[s] > 0)
weightedExpectedStatLevel *= .01;
}
- else if (breedingMode == BreedingPlan.BreedingMode.TopStatsConservative && bestLevelsOfSpecies[s] > 0)
+ else if (breedingMode == BreedingMode.TopStatsConservative && bestLevelsOfSpecies[s] > 0)
{
bool higherIsBetter = statWeights[s] >= 0;
bestPossLevels[s] = (short)(higherIsBetter ? Math.Max(female.levelsWild[s], male.levelsWild[s]) : Math.Min(female.levelsWild[s], male.levelsWild[s]));
@@ -141,7 +140,7 @@ public static List CalculateBreedingScores(Creature[] females, Cre
}
}
- if (breedingMode == BreedingPlan.BreedingMode.TopStatsConservative)
+ if (breedingMode == BreedingMode.TopStatsConservative)
{
if (topStatsMother < offspringPotentialTopStatCount && topStatsFather < offspringPotentialTopStatCount)
t += offspringExpectedTopStatCount;
@@ -275,5 +274,12 @@ public static int GetHigherBestLevel(int level1, int level2, byte anyOddEven)
default: return Math.Max(level1, level2);
}
}
+
+ public enum BreedingMode
+ {
+ BestNextGen,
+ TopStatsLucky,
+ TopStatsConservative
+ }
}
}
diff --git a/ARKBreedingStats/CreatureInfoInput.cs b/ARKBreedingStats/CreatureInfoInput.cs
index 56f15bc04..4b226c548 100644
--- a/ARKBreedingStats/CreatureInfoInput.cs
+++ b/ARKBreedingStats/CreatureInfoInput.cs
@@ -720,7 +720,7 @@ private void SetAdd2LibColor(bool buttonEnabled)
{
btAdd2Library.BackColor = !buttonEnabled
? SystemColors.Control
- : _alreadyExistingCreature != null ? Color.LightGreen
+ : _alreadyExistingCreature == null ? Color.LightGreen
: Color.LightSkyBlue;
}
diff --git a/ARKBreedingStats/Extraction.cs b/ARKBreedingStats/Extraction.cs
index 933ed9e01..745ae8cf1 100644
--- a/ARKBreedingStats/Extraction.cs
+++ b/ARKBreedingStats/Extraction.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using ARKBreedingStats.uiControls;
namespace ARKBreedingStats
{
diff --git a/ARKBreedingStats/FileService.cs b/ARKBreedingStats/FileService.cs
index c46b620bd..405e705c7 100644
--- a/ARKBreedingStats/FileService.cs
+++ b/ARKBreedingStats/FileService.cs
@@ -285,7 +285,7 @@ internal static bool IsValidJsonFile(string filePath)
private static HttpClient _httpClient;
///
- /// Returns a static HttpClient. It's apparently better to reuse on object per app only.
+ /// Returns a static HttpClient. It's apparently better to reuse one object per app only.
///
public static HttpClient GetHttpClient
{
diff --git a/ARKBreedingStats/Form1.Designer.cs b/ARKBreedingStats/Form1.Designer.cs
index 68e2741b4..e97111173 100644
--- a/ARKBreedingStats/Form1.Designer.cs
+++ b/ARKBreedingStats/Form1.Designer.cs
@@ -385,6 +385,7 @@ private void InitializeComponent()
this.toolStripSeparator27 = new System.Windows.Forms.ToolStripSeparator();
this.resetColumnOrderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.speciesSelector1 = new ARKBreedingStats.SpeciesSelector();
+ this.currentTokenToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownImprintingBonusTester)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NumericUpDownTestingTE)).BeginInit();
@@ -1342,6 +1343,7 @@ private void InitializeComponent()
//
this.serverToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.listenToolStripMenuItem,
+ this.currentTokenToolStripMenuItem,
this.listenWithNewTokenToolStripMenuItem,
this.sendExampleCreatureToolStripMenuItem});
this.serverToolStripMenuItem.Name = "serverToolStripMenuItem";
@@ -3781,6 +3783,13 @@ private void InitializeComponent()
this.speciesSelector1.SplitterDistance = 500;
this.speciesSelector1.TabIndex = 0;
//
+ // currentTokenToolStripMenuItem
+ //
+ this.currentTokenToolStripMenuItem.Name = "currentTokenToolStripMenuItem";
+ this.currentTokenToolStripMenuItem.Size = new System.Drawing.Size(194, 22);
+ this.currentTokenToolStripMenuItem.Text = "Current token";
+ this.currentTokenToolStripMenuItem.Click += new System.EventHandler(this.currentTokenToolStripMenuItem_Click);
+ //
// Form1
//
this.AcceptButton = this.btExtractLevels;
@@ -4241,5 +4250,6 @@ private void InitializeComponent()
private System.Windows.Forms.Label label5;
private System.Windows.Forms.CheckBox CbLinkWildMutatedLevelsTester;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemMutationColumns;
+ private System.Windows.Forms.ToolStripMenuItem currentTokenToolStripMenuItem;
}
}
diff --git a/ARKBreedingStats/Form1.collection.cs b/ARKBreedingStats/Form1.collection.cs
index c938fc068..d2f3af6af 100644
--- a/ARKBreedingStats/Form1.collection.cs
+++ b/ARKBreedingStats/Form1.collection.cs
@@ -15,6 +15,8 @@
using ARKBreedingStats.importExportGun;
using ARKBreedingStats.uiControls;
using ARKBreedingStats.utils;
+using ARKBreedingStats.AsbServer;
+using Newtonsoft.Json.Linq;
namespace ARKBreedingStats
{
@@ -945,24 +947,40 @@ private void UpdateListsAfterCreaturesAdded()
}
///
- /// Imports a creature when listening to a server.
+ /// Handle reports from the AsbServer listening, e.g. importing creatures or handle errors.
///
- private void AsbServerDataSent((string jsonData, string serverHash, string errorMessage) data)
+ private void AsbServerDataSent(ProgressReportAsbServer data)
{
- if (!string.IsNullOrEmpty(data.errorMessage))
+ if (!string.IsNullOrEmpty(data.Message))
{
- SetMessageLabelText(data.errorMessage, MessageBoxIcon.Error);
- // don't remove the error message with the stop listening message
- _ignoreNextMessageLabel = true;
- listenToolStripMenuItem.Checked = false;
+ var displayPopup = false;
+ var message = data.Message;
+ if (!string.IsNullOrEmpty(data.ServerToken))
+ {
+ message += Environment.NewLine + Connection.TokenStringForDisplay(data.ServerToken);
+ displayPopup = !Properties.Settings.Default.StreamerMode;
+ }
+
+ SetMessageLabelText(message, data.IsError ? MessageBoxIcon.Error : MessageBoxIcon.Information, clipboardText: data.ClipboardText, displayPopup: displayPopup);
+
+ if (!string.IsNullOrEmpty(data.ClipboardText))
+ Clipboard.SetText(data.ClipboardText);
+
+ if (data.StopListening)
+ {
+ // don't remove the error message with the stop listening message
+ _ignoreNextMessageLabel = true;
+ listenToolStripMenuItem.Checked = false;
+ }
+
return;
}
string resultText;
- if (string.IsNullOrEmpty(data.serverHash))
+ if (string.IsNullOrEmpty(data.ServerHash))
{
// import creature
- var creature = ImportExportGun.ImportCreatureFromJson(data.jsonData, null, out resultText, out _);
+ var creature = ImportExportGun.ImportCreatureFromJson(data.JsonText, null, out resultText, out _);
if (creature == null)
{
SetMessageLabelText(resultText, MessageBoxIcon.Error);
@@ -987,7 +1005,7 @@ private void AsbServerDataSent((string jsonData, string serverHash, string error
}
// import server settings
- var success = ImportExportGun.ImportServerMultipliersFromJson(_creatureCollection, data.jsonData, data.serverHash, out resultText);
+ var success = ImportExportGun.ImportServerMultipliersFromJson(_creatureCollection, data.JsonText, data.ServerHash, out resultText);
SetMessageLabelText(resultText, success ? MessageBoxIcon.Information : MessageBoxIcon.Error, resultText);
}
}
diff --git a/ARKBreedingStats/Form1.cs b/ARKBreedingStats/Form1.cs
index 4e2dd11b3..caca52f1b 100644
--- a/ARKBreedingStats/Form1.cs
+++ b/ARKBreedingStats/Form1.cs
@@ -21,6 +21,7 @@
using ARKBreedingStats.utils;
using static ARKBreedingStats.settings.Settings;
using Color = System.Drawing.Color;
+using ARKBreedingStats.AsbServer;
namespace ARKBreedingStats
{
@@ -31,11 +32,12 @@ public partial class Form1 : Form
private bool _collectionDirty;
///
- /// List of all top stats per species
+ /// List of all highest stats per species
///
- private readonly Dictionary _topLevels = new Dictionary();
-
- private readonly Dictionary _lowestLevels = new Dictionary();
+ private readonly Dictionary _highestSpeciesLevels = new Dictionary();
+ private readonly Dictionary _lowestSpeciesLevels = new Dictionary();
+ private readonly Dictionary _highestSpeciesMutationLevels = new Dictionary();
+ private readonly Dictionary _lowestSpeciesMutationLevels = new Dictionary();
private readonly StatIO[] _statIOs = new StatIO[Stats.StatsCount];
private readonly StatIO[] _testingIOs = new StatIO[Stats.StatsCount];
private int _activeStatIndex = -1;
@@ -53,8 +55,8 @@ public delegate void
Species species = null, // if null is passed for species, breeding-related controls are not updated
bool triggeredByFileWatcher = false);
- public delegate void SetMessageLabelTextEventHandler(string text = null,
- MessageBoxIcon icon = MessageBoxIcon.None, string path = null, string clipboardContent = null);
+ public delegate void SetMessageLabelTextEventHandler(string text = null, MessageBoxIcon icon = MessageBoxIcon.None,
+ string path = null, string clipboardContent = null, bool displayPopup = false);
private bool _updateTorporInTester;
private bool _filterListAllowed;
@@ -631,7 +633,7 @@ private void ToggleViewSpeciesSelector(bool showSpeciesSelector)
private void TbSpeciesGlobal_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Enter && e.KeyCode != Keys.Tab) return;
- if (speciesSelector1.SetSpeciesByName(tbSpeciesGlobal.Text))
+ if (speciesSelector1.SetSpeciesByEntryName(tbSpeciesGlobal.Text))
ToggleViewSpeciesSelector(false);
}
@@ -734,7 +736,7 @@ private void SpeciesSelector1OnSpeciesSelected(bool speciesChanged)
breedingPlan1.SetSpecies(species);
}
}
- hatching1.SetSpecies(species, _topLevels.TryGetValue(species, out var bl) ? bl : null, _lowestLevels.TryGetValue(species, out var ll) ? ll : null);
+ hatching1.SetSpecies(species, _highestSpeciesLevels.TryGetValue(species, out var bl) ? bl : null, _lowestSpeciesLevels.TryGetValue(species, out var ll) ? ll : null);
_hiddenLevelsCreatureTester = 0;
@@ -1350,6 +1352,7 @@ private void Form1_FormClosed(object sender, FormClosedEventArgs e)
// remove old cache-files
CreatureColored.CleanupCache();
+ AsbServerStopListening(false);
_tt?.Dispose();
_timerGlobal?.Dispose();
}
@@ -1362,7 +1365,7 @@ private void Form1_FormClosed(object sender, FormClosedEventArgs e)
/// If valid path to file or folder, the user can click on the message to display the path in the explorer
/// If not null, user can copy this text to the clipboard by clicking on the label
private void SetMessageLabelText(string text = null, MessageBoxIcon icon = MessageBoxIcon.None,
- string path = null, string clipboardText = null)
+ string path = null, string clipboardText = null, bool displayPopup = false)
{
if (_ignoreNextMessageLabel)
{
@@ -1388,6 +1391,8 @@ private void SetMessageLabelText(string text = null, MessageBoxIcon icon = Messa
TbMessageLabel.BackColor = SystemColors.Control;
break;
}
+ if (displayPopup && !string.IsNullOrEmpty(text))
+ PopupMessage.Show(this, text, 20);
}
///
@@ -3049,8 +3054,8 @@ private void CreatureInfoInput_CreatureDataRequested(CreatureInfoInput input, bo
if (openPatternEditor)
{
- input.OpenNamePatternEditor(cr, _topLevels.TryGetValue(cr.Species, out var tl) ? tl : null,
- _lowestLevels.TryGetValue(cr.Species, out var ll) ? ll : null,
+ input.OpenNamePatternEditor(cr, _highestSpeciesLevels.TryGetValue(cr.Species, out var tl) ? tl : null,
+ _lowestSpeciesLevels.TryGetValue(cr.Species, out var ll) ? ll : null,
_customReplacingNamingPattern, namingPatternIndex, ReloadNamePatternCustomReplacings);
UpdatePatternButtons();
@@ -3069,8 +3074,8 @@ private void CreatureInfoInput_CreatureDataRequested(CreatureInfoInput input, bo
colorAlreadyExistingInformation = _creatureCollection.ColorAlreadyAvailable(cr.Species, input.RegionColors, out _);
input.ColorAlreadyExistingInformation = colorAlreadyExistingInformation;
- input.GenerateCreatureName(cr, alreadyExistingCreature, _topLevels.TryGetValue(cr.Species, out var tl) ? tl : null,
- _lowestLevels.TryGetValue(cr.Species, out var ll) ? ll : null,
+ input.GenerateCreatureName(cr, alreadyExistingCreature, _highestSpeciesLevels.TryGetValue(cr.Species, out var tl) ? tl : null,
+ _lowestSpeciesLevels.TryGetValue(cr.Species, out var ll) ? ll : null,
_customReplacingNamingPattern, showDuplicateNameWarning, namingPatternIndex);
if (Properties.Settings.Default.PatternNameToClipboardAfterManualApplication)
{
@@ -3097,8 +3102,9 @@ private Creature CreateCreatureFromExtractorOrTester(CreatureInfoInput input)
cr.imprintingBonus = _extractor.ImprintingBonus;
cr.tamingEff = _extractor.UniqueTamingEffectiveness();
cr.isBred = rbBredExtractor.Checked;
- cr.topBreedingStats = _statIOs.Select(s =>
- s.TopLevel.HasFlag(LevelStatus.TopLevel) || s.TopLevel.HasFlag(LevelStatus.NewTopLevel)).ToArray();
+ for (int s = 0; s < Stats.StatsCount; s++)
+ cr.SetTopStat(s, _statIOs[s].TopLevel.HasFlag(LevelStatusFlags.LevelStatus.TopLevel) || _statIOs[s].TopLevel.HasFlag(LevelStatusFlags.LevelStatus.NewTopLevel));
+
}
else
{
@@ -3516,14 +3522,15 @@ private void GenerateCreatureNames()
foreach (int i in listViewLibrary.SelectedIndices)
{
var cr = _creaturesDisplayed[i];
+ if (cr.Species == null) continue;
if (sameSpecies?.FirstOrDefault()?.Species != cr.Species)
sameSpecies = _creatureCollection.creatures.Where(c => c.Species == cr.Species).ToArray();
// set new name
cr.name = NamePattern.GenerateCreatureName(cr, cr, sameSpecies,
- _topLevels.ContainsKey(cr.Species) ? _topLevels[cr.Species] : null,
- _lowestLevels.ContainsKey(cr.Species) ? _lowestLevels[cr.Species] : null,
+ _highestSpeciesLevels.TryGetValue(cr.Species, out var highestSpeciesLevels) ? highestSpeciesLevels : null,
+ _lowestSpeciesLevels.TryGetValue(cr.Species, out var lowestSpeciesLevels) ? lowestSpeciesLevels : null,
_customReplacingNamingPattern, false, 0, libraryCreatureCount: libraryCreatureCount);
creaturesToUpdate.Add(cr);
@@ -3878,25 +3885,41 @@ private void listenWithNewTokenToolStripMenuItem_Click(object sender, EventArgs
private void AsbServerStartListening()
{
- AsbServer.Connection.StopListening();
- var progressDataSent = new Progress<(string jsonText, string serverHash, string message)>(AsbServerDataSent);
+ var progressReporter = new Progress(AsbServerDataSent);
if (string.IsNullOrEmpty(Properties.Settings.Default.ExportServerToken))
Properties.Settings.Default.ExportServerToken = AsbServer.Connection.CreateNewToken();
- Task.Factory.StartNew(() => AsbServer.Connection.StartListeningAsync(progressDataSent, Properties.Settings.Default.ExportServerToken));
- MessageServerListening(Properties.Settings.Default.ExportServerToken);
+ Task.Factory.StartNew(() => AsbServer.Connection.StartListeningAsync(progressReporter, Properties.Settings.Default.ExportServerToken));
}
- private void AsbServerStopListening()
+ private void AsbServerStopListening(bool displayMessage = true)
{
AsbServer.Connection.StopListening();
- SetMessageLabelText($"ASB Server listening stopped using token: {Properties.Settings.Default.ExportServerToken}", MessageBoxIcon.Error);
+ if (displayMessage)
+ SetMessageLabelText($"ASB Server listening stopped using token: {Connection.TokenStringForDisplay(Properties.Settings.Default.ExportServerToken)}", MessageBoxIcon.Error);
}
- private void MessageServerListening(string token)
+ private void currentTokenToolStripMenuItem_Click(object sender, EventArgs e)
{
- SetMessageLabelText($"Now listening to the export server using the token (also copied to clipboard){Environment.NewLine}{token}", MessageBoxIcon.Information, clipboardText: token);
- if (!string.IsNullOrEmpty(token))
- Clipboard.SetText(token);
+ var tokenIsSet = !string.IsNullOrEmpty(Properties.Settings.Default.ExportServerToken);
+ string message;
+ bool isError;
+ if (tokenIsSet)
+ {
+ message = $"Currently {(Connection.IsCurrentlyListening ? string.Empty : "not ")}listening to the server."
+ + " The current token is " + Environment.NewLine + Connection.TokenStringForDisplay(Properties.Settings.Default.ExportServerToken)
+ + Environment.NewLine + "(token copied to clipboard)";
+
+ Clipboard.SetText(Properties.Settings.Default.ExportServerToken);
+ isError = false;
+ }
+ else
+ {
+ message = "Currently no token set. A token is created once you start listening to the server.";
+ isError = true;
+ }
+
+ SetMessageLabelText(message, isError ? MessageBoxIcon.Error : MessageBoxIcon.Information,
+ clipboardText: Properties.Settings.Default.ExportServerToken, displayPopup: !Properties.Settings.Default.StreamerMode);
}
private void sendExampleCreatureToolStripMenuItem_Click(object sender, EventArgs e)
@@ -3906,6 +3929,5 @@ private void sendExampleCreatureToolStripMenuItem_Click(object sender, EventArgs
}
#endregion
-
}
}
diff --git a/ARKBreedingStats/Form1.extractor.cs b/ARKBreedingStats/Form1.extractor.cs
index 31a174581..e489d1331 100644
--- a/ARKBreedingStats/Form1.extractor.cs
+++ b/ARKBreedingStats/Form1.extractor.cs
@@ -9,8 +9,10 @@
using System.Linq;
using System.Threading;
using System.Windows.Forms;
+using ARKBreedingStats.library;
using ARKBreedingStats.utils;
using ARKBreedingStats.ocr;
+using ARKBreedingStats.uiControls;
namespace ARKBreedingStats
{
@@ -65,7 +67,7 @@ private void ShowSumOfChosenLevels()
valid = false;
break;
}
- _statIOs[s].TopLevel = LevelStatus.Neutral;
+ _statIOs[s].TopLevel = LevelStatusFlags.LevelStatus.Neutral;
}
if (valid)
{
@@ -116,80 +118,33 @@ private void ShowSumOfChosenLevels()
radarChartExtractor.SetLevels(_statIOs.Select(s => s.LevelWild).ToArray(), _statIOs.Select(s => s.LevelMut).ToArray(), speciesSelector1.SelectedSpecies);
cbExactlyImprinting.BackColor = Color.Transparent;
var species = speciesSelector1.SelectedSpecies;
- var checkTopLevels = _topLevels.TryGetValue(species, out int[] topSpeciesLevels);
- var checkLowLevels = _lowestLevels.TryGetValue(species, out int[] lowSpeciesLevels);
+ _highestSpeciesLevels.TryGetValue(species, out int[] highSpeciesLevels);
+ _lowestSpeciesLevels.TryGetValue(species, out int[] lowSpeciesLevels);
+ _highestSpeciesMutationLevels.TryGetValue(species, out int[] highSpeciesMutationLevels);
+ //_lowestSpeciesMutationLevels.TryGetValue(species, out int[] lowSpeciesMutationLevels);
- var customStatNames = species.statNames;
var statWeights = breedingPlan1.StatWeighting.GetWeightingForSpecies(species);
- if (statWeights.Item1 == null) checkLowLevels = false;
- var analysisState = LevelStatus.Neutral;
- var newTopStatsText = new List();
- var topStatsText = new List();
- for (int s = 0; s < Stats.StatsCount; s++)
- {
- if (s == Stats.Torpidity
- || _statIOs[s].LevelWild <= 0)
- continue;
-
- var levelStatus = LevelStatus.Neutral;
-
- if (checkTopLevels && (statWeights.Item1?[s] ?? 0) >= 0)
- {
- // higher stats are considered to be good. If no custom weightings are available, consider higher levels to be better.
+ LevelStatusFlags.DetermineLevelStatus(species, highSpeciesLevels, lowSpeciesLevels, highSpeciesMutationLevels,
+ statWeights, GetCurrentWildLevels(), GetCurrentMutLevels(),GetCurrentBreedingValues(),
+ out var topStatsText, out var newTopStatsText);
- // check if higher level is only considered if even or odd
- if ((statWeights.Item2?[s] ?? 0) == 0 // even/odd doesn't matter
- || (statWeights.Item2[s] == 1 && _statIOs[s].LevelWild % 2 == 1)
- || (statWeights.Item2[s] == 2 && _statIOs[s].LevelWild % 2 == 0)
- )
- {
- if (_statIOs[s].LevelWild == topSpeciesLevels[s])
- {
- levelStatus = LevelStatus.TopLevel;
- topStatsText.Add(Utils.StatName(s, false, customStatNames));
- if (analysisState != LevelStatus.NewTopLevel)
- analysisState = LevelStatus.TopLevel;
- }
- else if (topSpeciesLevels[s] != -1 && _statIOs[s].LevelWild > topSpeciesLevels[s])
- {
- levelStatus = LevelStatus.NewTopLevel;
- newTopStatsText.Add(Utils.StatName(s, false, customStatNames));
- analysisState = LevelStatus.NewTopLevel;
- }
- }
- }
- else if (checkLowLevels && statWeights.Item1[s] < 0)
- {
- // lower stats are considered to be good
- if (_statIOs[s].LevelWild == lowSpeciesLevels[s])
- {
- levelStatus = LevelStatus.TopLevel;
- topStatsText.Add(Utils.StatName(s, false, customStatNames));
- if (analysisState != LevelStatus.NewTopLevel)
- analysisState = LevelStatus.TopLevel;
- }
- else if (_statIOs[s].LevelWild < lowSpeciesLevels[s])
- {
- levelStatus = LevelStatus.NewTopLevel;
- newTopStatsText.Add(Utils.StatName(s, false, customStatNames));
- analysisState = LevelStatus.NewTopLevel;
- }
- }
+ for (var s = 0; s < Stats.StatsCount; s++)
+ {
+ var levelStatusForStatIo = LevelStatusFlags.LevelStatusFlagsCurrentNewCreature[s];
// ASA can have up to 511 levels because 255 mutation levels also contribute to the wild value. TODO separate to mutation levels
- if (_creatureCollection.Game != Ark.Asa)
+ if (_creatureCollection.Game != Ark.Asa && s != Stats.Torpidity)
{
if (_statIOs[s].LevelWild > 255)
- levelStatus |= LevelStatus.UltraMaxLevel;
+ levelStatusForStatIo |= LevelStatusFlags.LevelStatus.UltraMaxLevel;
else if (_statIOs[s].LevelWild == 255)
- levelStatus |= LevelStatus.MaxLevel;
+ levelStatusForStatIo |= LevelStatusFlags.LevelStatus.MaxLevel;
else if (_statIOs[s].LevelWild == 254)
- levelStatus |= LevelStatus.MaxLevelForLevelUp;
+ levelStatusForStatIo |= LevelStatusFlags.LevelStatus.MaxLevelForLevelUp;
}
- if (levelStatus != LevelStatus.Neutral)
- _statIOs[s].TopLevel = levelStatus;
+ _statIOs[s].TopLevel = levelStatusForStatIo;
}
string infoText = null;
@@ -204,7 +159,7 @@ private void ShowSumOfChosenLevels()
if (infoText == null) infoText = "No top stats";
- creatureAnalysis1.SetStatsAnalysis(analysisState, infoText);
+ creatureAnalysis1.SetStatsAnalysis(LevelStatusFlags.CombinedLevelStatusFlags, infoText);
}
creatureInfoInputExtractor.ButtonEnabled = allValid;
groupBoxRadarChartExtractor.Visible = allValid;
@@ -414,7 +369,7 @@ private bool ExtractLevels(bool autoExtraction = false, bool statInputsHighPreci
int domLevelsChosenSum = 0;
for (int s = 0; s < Stats.StatsCount; s++)
{
- if (s != Stats.Torpidity)
+ if (s != Stats.Torpidity && _extractor.Results[s].Any())
domLevelsChosenSum += _extractor.Results[s][_extractor.ChosenResults[s]].levelDom;
}
if (domLevelsChosenSum != _extractor.LevelDomSum)
@@ -762,17 +717,18 @@ private void SetLevelCombination(int s, int i, bool validateCombination = false)
///
private void SetWildUnknownLevelsAccordingToOthers()
{
+ var species = speciesSelector1.SelectedSpecies;
// wild speed level is wildTotalLevels - determinedWildLevels. sometimes the oxygen level cannot be determined as well
var unknownLevelIndices = new List();
int notDeterminedLevels = _statIOs[Stats.Torpidity].LevelWild;
for (int s = 0; s < Stats.StatsCount; s++)
{
- if (s == Stats.Torpidity || !speciesSelector1.SelectedSpecies.UsesStat(s))
+ if (s == Stats.Torpidity || !species.UsesStat(s))
{
continue;
}
- if (_statIOs[s].LevelWild < 0)
+ if (_statIOs[s].LevelWild < 0 || species.stats[s].IncPerWildLevel == 0)
{
unknownLevelIndices.Add(s);
continue;
@@ -1219,7 +1175,7 @@ private void CreatureInfoInputColorsChanged(CreatureInfoInput input)
input.ColorAlreadyExistingInformation = colorAlreadyExisting;
if (input == creatureInfoInputExtractor)
- creatureAnalysis1.SetColorAnalysis(newColorStatus.newInSpecies ? LevelStatus.NewTopLevel : newColorStatus.newInRegion ? LevelStatus.TopLevel : LevelStatus.Neutral, infoText);
+ creatureAnalysis1.SetColorAnalysis(newColorStatus.newInSpecies ? LevelStatusFlags.LevelStatus.NewTopLevel : newColorStatus.newInRegion ? LevelStatusFlags.LevelStatus.TopLevel : LevelStatusFlags.LevelStatus.Neutral, infoText);
}
private void copyLibrarydumpToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
diff --git a/ARKBreedingStats/Form1.importExported.cs b/ARKBreedingStats/Form1.importExported.cs
index 2ae5f5dda..6539b4853 100644
--- a/ARKBreedingStats/Form1.importExported.cs
+++ b/ARKBreedingStats/Form1.importExported.cs
@@ -8,6 +8,7 @@
using System.Linq;
using System.Text;
using System.Windows.Forms;
+using ARKBreedingStats.library;
using ARKBreedingStats.NamePatterns;
using ARKBreedingStats.species;
using ARKBreedingStats.utils;
@@ -232,7 +233,8 @@ private Creature ImportExportedAddIfPossible(string filePath)
creature = GetCreatureFromInput(true, species, levelStep);
}
- OverlayFeedbackForImport(creature, uniqueExtraction, alreadyExists, addedToLibrary, copiedNameToClipboard, out bool hasTopLevels, out bool hasNewTopLevels);
+ OverlayFeedbackForImport(creature, uniqueExtraction, alreadyExists, addedToLibrary, copiedNameToClipboard,
+ out bool hasTopLevels, out bool hasNewTopLevels, out var newMutationStatFlags);
if (addedToLibrary)
{
@@ -296,7 +298,9 @@ private Creature ImportExportedAddIfPossible(string filePath)
if (uniqueExtraction)
{
if (alreadyExists)
- SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.Indifferent);
+ SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.Updated);
+ else if (newMutationStatFlags != 0)
+ SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.NewMutation);
else if (hasNewTopLevels)
SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.Great);
else if (hasTopLevels)
@@ -339,8 +343,8 @@ private bool SetNameOfImportedCreature(Creature creature, Creature[] creaturesOf
creaturesOfSpecies = _creatureCollection.creatures.Where(c => c.Species == creature.Species)
.ToArray();
creature.name = NamePattern.GenerateCreatureName(creature, alreadyExistingCreature, creaturesOfSpecies,
- _topLevels.TryGetValue(creature.Species, out var topLevels) ? topLevels : null,
- _lowestLevels.TryGetValue(creature.Species, out var lowestLevels) ? lowestLevels : null,
+ _highestSpeciesLevels.TryGetValue(creature.Species, out var topLevels) ? topLevels : null,
+ _lowestSpeciesLevels.TryGetValue(creature.Species, out var lowestLevels) ? lowestLevels : null,
_customReplacingNamingPattern, false, 0, libraryCreatureCount: totalCreatureCount);
if (alreadyExistingCreature != null)
alreadyExistingCreature.name = creature.name; // if alreadyExistingCreature was already updated and creature is not used anymore make sure name is not lost
@@ -377,10 +381,12 @@ private bool CopyCreatureNameToClipboardOnImportIfSetting(string creatureName)
///
/// Give feedback in overlay for imported creature.
///
- private void OverlayFeedbackForImport(Creature creature, bool uniqueExtraction, bool alreadyExists, bool addedToLibrary, bool copiedNameToClipboard, out bool topLevels, out bool newTopLevels)
+ private void OverlayFeedbackForImport(Creature creature, bool uniqueExtraction, bool alreadyExists, bool addedToLibrary,
+ bool copiedNameToClipboard, out bool topLevels, out bool newTopLevels, out int newMutationStatFlags)
{
topLevels = false;
newTopLevels = false;
+ newMutationStatFlags = 0;
string infoText;
Color textColor;
const int colorSaturation = 200;
@@ -391,24 +397,27 @@ private void OverlayFeedbackForImport(Creature creature, bool uniqueExtraction,
if (addedToLibrary && copiedNameToClipboard)
sb.AppendLine("Name copied to clipboard.");
- for (int s = 0; s < Stats.StatsCount; s++)
- {
- int statIndex = Stats.DisplayOrder[s];
- if (!creature.Species.UsesStat(statIndex)) continue;
-
- sb.Append($"{Utils.StatName(statIndex, true, creature.Species.statNames)}: {creature.levelsWild[statIndex]} ({creature.valuesBreeding[statIndex]})");
- if (_statIOs[statIndex].TopLevel.HasFlag(LevelStatus.NewTopLevel))
- {
- sb.Append($" {Loc.S("newTopLevel")}");
- newTopLevels = true;
- }
- else if (creature.topBreedingStats[statIndex])
- {
- sb.Append($" {Loc.S("topLevel")}");
- topLevels = true;
- }
- sb.AppendLine();
- }
+ var checkMutations = _highestSpeciesMutationLevels.TryGetValue(creature.Species, out var highestMutations) && creature.levelsMutated != null;
+ var species = speciesSelector1.SelectedSpecies;
+ _highestSpeciesLevels.TryGetValue(species, out int[] highSpeciesLevels);
+ _lowestSpeciesLevels.TryGetValue(species, out int[] lowSpeciesLevels);
+ _highestSpeciesMutationLevels.TryGetValue(species, out int[] highSpeciesMutationLevels);
+
+ var statWeights = breedingPlan1.StatWeighting.GetWeightingForSpecies(species);
+
+ LevelStatusFlags.DetermineLevelStatus(species, highSpeciesLevels, lowSpeciesLevels, highSpeciesMutationLevels,
+ statWeights, creature.levelsWild, creature.levelsMutated, creature.valuesBreeding,
+ out _, out _, sb);
+
+ topLevels = LevelStatusFlags.CombinedLevelStatusFlags.HasFlag(LevelStatusFlags.LevelStatus.TopLevel);
+ newTopLevels = LevelStatusFlags.CombinedLevelStatusFlags.HasFlag(LevelStatusFlags.LevelStatus.NewTopLevel);
+ newMutationStatFlags = Enumerable.Range(0, Stats.StatsCount)
+ .Aggregate(0,
+ (flags, statIndex) =>
+ flags | (LevelStatusFlags.LevelStatusFlagsCurrentNewCreature[statIndex]
+ .HasFlag(LevelStatusFlags.LevelStatus.NewMutation)
+ ? (1 << statIndex)
+ : 0));
infoText = sb.ToString();
textColor = Color.FromArgb(colorSaturation, 255, colorSaturation);
@@ -417,6 +426,7 @@ private void OverlayFeedbackForImport(Creature creature, bool uniqueExtraction,
{
infoText = $"Creature \"{creature.name}\" couldn't be extracted uniquely, manual level selection is necessary.";
textColor = Color.FromArgb(255, colorSaturation, colorSaturation);
+ LevelStatusFlags.Clear();
}
if (_overlay != null)
diff --git a/ARKBreedingStats/Form1.library.cs b/ARKBreedingStats/Form1.library.cs
index 209d1ffd3..c83e5a80a 100644
--- a/ARKBreedingStats/Form1.library.cs
+++ b/ARKBreedingStats/Form1.library.cs
@@ -196,40 +196,25 @@ private bool IsArkIdUniqueOrOnlyPlaceHolder(Creature creature)
/// Returns the wild levels from the extractor or tester in an array.
///
private int[] GetCurrentWildLevels(bool fromExtractor = true)
- {
- int[] levelsWild = new int[Stats.StatsCount];
- for (int s = 0; s < Stats.StatsCount; s++)
- {
- levelsWild[s] = fromExtractor ? _statIOs[s].LevelWild : _testingIOs[s].LevelWild;
- }
- return levelsWild;
- }
+ => (fromExtractor ? _statIOs : _testingIOs).Select(i => i.LevelWild).ToArray();
///
/// Returns the mutated levels from the extractor or tester in an array.
///
private int[] GetCurrentMutLevels(bool fromExtractor = true)
- {
- int[] levelsMut = new int[Stats.StatsCount];
- for (int s = 0; s < Stats.StatsCount; s++)
- {
- levelsMut[s] = fromExtractor ? _statIOs[s].LevelMut : _testingIOs[s].LevelMut;
- }
- return levelsMut;
- }
+ => (fromExtractor ? _statIOs : _testingIOs).Select(i => i.LevelMut).ToArray();
///
/// Returns the domesticated levels from the extractor or tester in an array.
///
private int[] GetCurrentDomLevels(bool fromExtractor = true)
- {
- int[] levelsDom = new int[Stats.StatsCount];
- for (int s = 0; s < Stats.StatsCount; s++)
- {
- levelsDom[s] = fromExtractor ? _statIOs[s].LevelDom : _testingIOs[s].LevelDom;
- }
- return levelsDom;
- }
+ => (fromExtractor ? _statIOs : _testingIOs).Select(i => i.LevelDom).ToArray();
+
+ ///
+ /// Returns the breeding values from the extractor or tester in an array.
+ ///
+ private double[] GetCurrentBreedingValues(bool fromExtractor = true)
+ => (fromExtractor ? _statIOs : _testingIOs).Select(i => i.BreedingValue).ToArray();
///
/// Call after the creatureCollection-object was created anew (e.g. after loading a file)
@@ -295,6 +280,11 @@ private static void ApplySpeciesObjectsToCollection(CreatureCollection cc)
/// creatures to consider
private void CalculateTopStats(List creatures)
{
+ _highestSpeciesLevels.Clear();
+ _lowestSpeciesLevels.Clear();
+ _highestSpeciesMutationLevels.Clear();
+ _lowestSpeciesMutationLevels.Clear();
+
var filteredCreaturesHash = Properties.Settings.Default.useFiltersInTopStatCalculation ? new HashSet(ApplyLibraryFilterSettings(creatures)) : null;
var speciesCreaturesGroups = creatures.GroupBy(c => c.Species);
@@ -308,13 +298,15 @@ private void CalculateTopStats(List creatures)
List usedStatIndices = new List(Stats.StatsCount);
List usedAndConsideredStatIndices = new List(Stats.StatsCount);
- int[] bestStat = new int[Stats.StatsCount];
- int[] lowestStat = new int[Stats.StatsCount];
+ var highestLevels = new int[Stats.StatsCount];
+ var lowestLevels = new int[Stats.StatsCount];
+ var highestMutationLevels = new int[Stats.StatsCount];
+ var lowestMutationLevels = new int[Stats.StatsCount];
var statWeights = breedingPlan1.StatWeighting.GetWeightingForSpecies(species);
for (int s = 0; s < Stats.StatsCount; s++)
{
- bestStat[s] = -1;
- lowestStat[s] = -1;
+ highestLevels[s] = -1;
+ lowestLevels[s] = -1;
if (species.UsesStat(s))
{
usedStatIndices.Add(s);
@@ -322,17 +314,24 @@ private void CalculateTopStats(List creatures)
usedAndConsideredStatIndices.Add(s);
}
}
- List[] bestCreatures = new List[Stats.StatsCount];
- int usedStatsCount = usedStatIndices.Count;
- int usedAndConsideredStatsCount = usedAndConsideredStatIndices.Count;
+ List[] bestCreaturesWildLevels = new List[Stats.StatsCount];
+ List[] bestCreaturesMutatedLevels = new List[Stats.StatsCount];
+ var statPreferences = new StatWeighting.StatValuePreference[Stats.StatsCount];
+ for (int s = 0; s < Stats.StatsCount; s++)
+ {
+ var statWeight = statWeights.Item1[s];
+ statPreferences[s] = statWeight > 0 ? StatWeighting.StatValuePreference.High :
+ statWeight < 0 ? StatWeighting.StatValuePreference.Low :
+ StatWeighting.StatValuePreference.Indifferent;
+ }
foreach (var c in speciesCreatures)
{
if (c.flags.HasFlag(CreatureFlags.Placeholder))
continue;
- // reset topBreeding stats for this creature
- c.topBreedingStats = new bool[Stats.StatsCount];
+ c.ResetTopStats();
+ c.ResetTopMutationStats();
c.topBreedingCreature = false;
if (
@@ -348,47 +347,110 @@ private void CalculateTopStats(List creatures)
continue;
}
- for (int s = 0; s < usedStatsCount; s++)
+ foreach (var s in usedStatIndices)
{
- int si = usedStatIndices[s];
- if (c.levelsWild[si] != -1 && (lowestStat[si] == -1 || c.levelsWild[si] < lowestStat[si]))
+ if (c.levelsWild[s] >= 0)
{
- lowestStat[si] = c.levelsWild[si];
- }
-
- if (c.levelsWild[si] <= 0) continue;
+ if (statPreferences[s] == StatWeighting.StatValuePreference.Low)
+ {
+ if (lowestLevels[s] == -1 || c.levelsWild[s] < lowestLevels[s])
+ {
+ bestCreaturesWildLevels[s] = new List { c };
+ lowestLevels[s] = c.levelsWild[s];
+ }
+ else if (c.levelsWild[s] == lowestLevels[s])
+ {
+ bestCreaturesWildLevels[s].Add(c);
+ }
- if (c.levelsWild[si] == bestStat[si])
- {
- bestCreatures[si].Add(c);
+ if (c.levelsWild[s] > highestLevels[s])
+ {
+ highestLevels[s] = c.levelsWild[s];
+ }
+ }
+ else if (statPreferences[s] == StatWeighting.StatValuePreference.High)
+ {
+ if (c.levelsWild[s] > highestLevels[s])
+ {
+ // creature has a higher level than the current highest level
+ // check if highest stats are only counted if odd or even
+ if ((statWeights.Item2?[s] ?? 0) == 0 // even/odd doesn't matter
+ || (statWeights.Item2[s] == 1 && c.levelsWild[s] % 2 == 1)
+ || (statWeights.Item2[s] == 2 && c.levelsWild[s] % 2 == 0)
+ )
+ {
+ bestCreaturesWildLevels[s] = new List { c };
+ highestLevels[s] = c.levelsWild[s];
+ }
+ }
+ else if (c.levelsWild[s] == highestLevels[s])
+ {
+ bestCreaturesWildLevels[s].Add(c);
+ }
+ if (lowestLevels[s] == -1 || c.levelsWild[s] < lowestLevels[s])
+ {
+ lowestLevels[s] = c.levelsWild[s];
+ }
+ }
}
- else if (c.levelsWild[si] > bestStat[si])
+
+ if (c.levelsMutated != null && c.levelsMutated[s] >= 0)
{
- // check if highest stats are only counted if odd or even
- if ((statWeights.Item2?[s] ?? 0) == 0 // even/odd doesn't matter
- || (statWeights.Item2[s] == 1 && c.levelsWild[si] % 2 == 1)
- || (statWeights.Item2[s] == 2 && c.levelsWild[si] % 2 == 0)
- )
+ if (statPreferences[s] == StatWeighting.StatValuePreference.Low)
{
- bestCreatures[si] = new List { c };
- bestStat[si] = c.levelsWild[si];
+ if (c.levelsMutated[s] < lowestMutationLevels[s])
+ {
+ bestCreaturesMutatedLevels[s] = new List { c };
+ lowestMutationLevels[s] = c.levelsMutated[s];
+ }
+ else if (c.levelsMutated[s] == lowestMutationLevels[s])
+ {
+ if (bestCreaturesMutatedLevels[s] == null)
+ bestCreaturesMutatedLevels[s] = new List { c };
+ else bestCreaturesMutatedLevels[s].Add(c);
+ }
+ }
+ else if (statPreferences[s] == StatWeighting.StatValuePreference.High
+ && c.levelsMutated[s] > 0)
+ {
+ if (c.levelsMutated[s] > 0 && c.levelsMutated[s] > highestMutationLevels[s])
+ {
+ bestCreaturesMutatedLevels[s] = new List { c };
+ highestMutationLevels[s] = c.levelsMutated[s];
+ }
+ else if (c.levelsMutated[s] == highestMutationLevels[s])
+ {
+ bestCreaturesMutatedLevels[s].Add(c);
+ }
}
}
}
}
- _topLevels[species] = bestStat;
- _lowestLevels[species] = lowestStat;
+ _highestSpeciesLevels[species] = highestLevels;
+ _lowestSpeciesLevels[species] = lowestLevels;
+ _highestSpeciesMutationLevels[species] = highestMutationLevels;
+ _lowestSpeciesMutationLevels[species] = lowestMutationLevels;
// bestStat and bestCreatures now contain the best stats and creatures for each stat.
// set topness of each creature (== mean wildLevels/mean top wildLevels in permille)
int sumTopLevels = 0;
- for (int s = 0; s < usedAndConsideredStatsCount; s++)
+ foreach (var s in usedAndConsideredStatIndices)
{
- int si = usedAndConsideredStatIndices[s];
- if (bestStat[si] > 0)
- sumTopLevels += bestStat[si];
+ switch (statPreferences[s])
+ {
+ case StatWeighting.StatValuePreference.Indifferent:
+ continue;
+ case StatWeighting.StatValuePreference.Low:
+ if (highestLevels[s] > 0 && lowestLevels[s] != 0)
+ sumTopLevels += highestLevels[s] - lowestLevels[s];
+ break;
+ case StatWeighting.StatValuePreference.High:
+ if (highestLevels[s] > 0)
+ sumTopLevels += highestLevels[s];
+ break;
+ }
}
if (sumTopLevels > 0)
{
@@ -396,10 +458,18 @@ private void CalculateTopStats(List creatures)
{
if (c.levelsWild == null || c.flags.HasFlag(CreatureFlags.Placeholder)) continue;
int sumCreatureLevels = 0;
- for (int s = 0; s < usedAndConsideredStatsCount; s++)
+ foreach (var s in usedAndConsideredStatIndices)
{
- int si = usedAndConsideredStatIndices[s];
- sumCreatureLevels += c.levelsWild[si] > 0 ? c.levelsWild[si] : 0;
+ switch (statPreferences[s])
+ {
+ case StatWeighting.StatValuePreference.Low:
+ if (c.levelsWild[s] >= 0)
+ sumCreatureLevels += highestLevels[s] - c.levelsWild[s];
+ break;
+ case StatWeighting.StatValuePreference.High:
+ sumCreatureLevels += c.levelsWild[s] > 0 ? c.levelsWild[s] : 0;
+ break;
+ }
}
c.topness = (short)(1000 * sumCreatureLevels / sumTopLevels);
}
@@ -408,54 +478,59 @@ private void CalculateTopStats(List creatures)
// if any male is in more than 1 category, remove any male from the topBreedingCreatures that is not top in at least 2 categories himself
for (int s = 0; s < Stats.StatsCount; s++)
{
- if (bestCreatures[s] == null || bestCreatures[s].Count == 0)
+ if (bestCreaturesMutatedLevels[s] != null)
{
- continue; // no creature has levelups in this stat or the stat is not used for this species
+ foreach (var c in bestCreaturesMutatedLevels[s])
+ c.topBreedingCreature = true;
}
- var crCount = bestCreatures[s].Count;
+ if (bestCreaturesWildLevels[s] == null || bestCreaturesWildLevels[s].Count == 0)
+ continue; // no creature has levelups in this stat or the stat is not used for this species
+
+ var crCount = bestCreaturesWildLevels[s].Count;
if (crCount == 1)
{
- bestCreatures[s][0].topBreedingCreature = true;
+ bestCreaturesWildLevels[s][0].topBreedingCreature = true;
continue;
}
- for (int c = 0; c < crCount; c++)
+ foreach (var currentCreature in bestCreaturesWildLevels[s])
{
- bestCreatures[s][c].topBreedingCreature = true;
- if (bestCreatures[s][c].sex != Sex.Male)
+ currentCreature.topBreedingCreature = true;
+ if (currentCreature.sex != Sex.Male)
continue;
- Creature currentCreature = bestCreatures[s][c];
// check how many best stat the male has
int maxval = 0;
for (int cs = 0; cs < Stats.StatsCount; cs++)
{
- if (currentCreature.levelsWild[cs] == bestStat[cs])
+ if (currentCreature.levelsWild[cs] == highestLevels[cs])
maxval++;
}
if (maxval > 1)
{
// check now if the other males have only 1.
- for (int oc = 0; oc < crCount; oc++)
+ foreach (var otherMale in bestCreaturesWildLevels[s])
{
- if (bestCreatures[s][oc].sex != Sex.Male)
- continue;
-
- if (oc == c)
+ if (otherMale.sex != Sex.Male
+ || currentCreature.Equals(otherMale))
continue;
- Creature otherMale = bestCreatures[s][oc];
-
int othermaxval = 0;
for (int ocs = 0; ocs < Stats.StatsCount; ocs++)
{
- if (otherMale.levelsWild[ocs] == bestStat[ocs])
+ if (otherMale.levelsWild[ocs] == highestLevels[ocs])
othermaxval++;
+ if (otherMale.IsTopMutationStat(ocs))
+ {
+ // if this creature has top mutation levels, don't remove it from breeding pool
+ othermaxval = 99;
+ break;
+ }
}
if (othermaxval == 1)
- bestCreatures[s][oc].topBreedingCreature = false;
+ otherMale.topBreedingCreature = false;
}
}
}
@@ -464,13 +539,16 @@ private void CalculateTopStats(List creatures)
// now we have a list of all candidates for breeding. Iterate on stats.
for (int s = 0; s < Stats.StatsCount; s++)
{
- if (bestCreatures[s] != null)
+ if (bestCreaturesWildLevels[s] != null)
{
- for (int c = 0; c < bestCreatures[s].Count; c++)
- {
- // flag topStats in creatures
- bestCreatures[s][c].topBreedingStats[s] = true;
- }
+ foreach (var c in bestCreaturesWildLevels[s])
+ c.SetTopStat(s, true);
+ }
+
+ if (bestCreaturesMutatedLevels[s] != null)
+ {
+ foreach (var c in bestCreaturesMutatedLevels[s])
+ c.SetTopMutationStat(s, true);
}
}
}
@@ -481,7 +559,7 @@ private void CalculateTopStats(List creatures)
var selectedSpecies = speciesSelector1.SelectedSpecies;
if (selectedSpecies != null)
- hatching1.SetSpecies(selectedSpecies, _topLevels.TryGetValue(selectedSpecies, out var tl) ? tl : null, _lowestLevels.TryGetValue(selectedSpecies, out var ll) ? ll : null);
+ hatching1.SetSpecies(selectedSpecies, _highestSpeciesLevels.TryGetValue(selectedSpecies, out var tl) ? tl : null, _lowestSpeciesLevels.TryGetValue(selectedSpecies, out var ll) ? ll : null);
}
///
@@ -757,7 +835,8 @@ private Creature[] InsertDividers(IList creatures)
private void ListViewLibrary_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
// check to see if the requested item is currently in the cache
- if (_libraryListViewItemCache != null && e.ItemIndex >= _libraryItemCacheFirstIndex && e.ItemIndex < _libraryItemCacheFirstIndex + _libraryListViewItemCache.Length)
+ if (_libraryListViewItemCache != null && e.ItemIndex >= _libraryItemCacheFirstIndex &&
+ e.ItemIndex < _libraryItemCacheFirstIndex + _libraryListViewItemCache.Length)
{
// get the ListViewItem from the cache instead of making a new one.
e.Item = _libraryListViewItemCache[e.ItemIndex - _libraryItemCacheFirstIndex];
@@ -765,7 +844,14 @@ private void ListViewLibrary_RetrieveVirtualItem(object sender, RetrieveVirtualI
else if (_creaturesDisplayed?.Length > e.ItemIndex)
{
// create item not available in the cache
- e.Item = CreateCreatureLvItem(_creaturesDisplayed[e.ItemIndex], Properties.Settings.Default.DisplayLibraryCreatureIndex);
+ e.Item = CreateCreatureLvItem(_creaturesDisplayed[e.ItemIndex],
+ Properties.Settings.Default.DisplayLibraryCreatureIndex);
+ }
+ else
+ {
+ throw new Exception($"ListViewItem could not be retrieved. ItemIndex: {e.ItemIndex}."
+ + $"_creaturesDisplayedLength: {_creaturesDisplayed?.Length}."
+ + $"_libraryListViewItemCacheLength: {_libraryListViewItemCache?.Length}");
}
}
@@ -988,7 +1074,7 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
Utils.SexSymbol(cr.sex),
cr.domesticatedAt?.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") ?? string.Empty,
(cr.topness / 10).ToString(),
- cr.topStatsCount.ToString(),
+ cr.topStatsConsideredCount.ToString(),
cr.generation.ToString(),
cr.levelFound.ToString(),
cr.Mutations.ToString(),
@@ -1013,6 +1099,7 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
ListViewItem lvi = new ListViewItem(subItems) { Tag = cr };
// apply colors to the subItems
+ var displayZeroMutationLevels = Properties.Settings.Default.LibraryDisplayZeroMutationLevels;
for (int s = 0; s < Stats.StatsCount; s++)
{
@@ -1030,17 +1117,17 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
}
else
lvi.SubItems[ColumnIndexFirstStat + s].BackColor = Utils.GetColorFromPercent((int)(cr.levelsWild[s] * (s == Stats.Torpidity ? colorFactor / 7 : colorFactor)), // TODO set factor to number of other stats (flyers have 6, Gacha has 8?)
- _considerStatHighlight[s] ? cr.topBreedingStats[s] ? 0.2 : 0.7 : 0.93);
+ _considerStatHighlight[s] ? cr.IsTopStat(s) ? 0.2 : 0.75 : 0.93);
// mutated levels
- if (cr.levelsMutated == null || cr.levelsMutated[s] == 0)
+ if (cr.levelsMutated == null || (!displayZeroMutationLevels && cr.levelsMutated[s] == 0))
{
lvi.SubItems[ColumnIndexFirstStat + Stats.StatsCount + s].ForeColor = Color.White;
lvi.SubItems[ColumnIndexFirstStat + Stats.StatsCount + s].BackColor = Color.White;
}
else
- lvi.SubItems[ColumnIndexFirstStat + Stats.StatsCount + s].BackColor = Utils.GetColorFromPercent((int)(cr.levelsMutated[s] * (s == Stats.Torpidity ? colorFactor / 7 : colorFactor)),
- _considerStatHighlight[s] ? 0.7 : 0.93, true);
+ lvi.SubItems[ColumnIndexFirstStat + Stats.StatsCount + s].BackColor = Utils.GetColorFromPercent((int)(cr.levelsMutated[s] * colorFactor),
+ _considerStatHighlight[s] ? cr.IsTopMutationStat(s) ? 0.5 : 0.8 : 0.93, true);
}
lvi.SubItems[ColumnIndexSex].BackColor = cr.flags.HasFlag(CreatureFlags.Neutered) ? Color.FromArgb(220, 220, 220) :
cr.sex == Sex.Female ? Color.FromArgb(255, 230, 255) :
@@ -1072,7 +1159,7 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
lvi.UseItemStyleForSubItems = false;
// color for top-stats-nr
- if (cr.topStatsCount > 0)
+ if (cr.topStatsConsideredCount > 0)
{
if (Properties.Settings.Default.LibraryHighlightTopCreatures && cr.topBreedingCreature)
{
@@ -1081,7 +1168,7 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
else
lvi.BackColor = Color.LightGreen;
}
- lvi.SubItems[ColumnIndexTopStats].BackColor = Utils.GetColorFromPercent(cr.topStatsCount * 8 + 44, 0.7);
+ lvi.SubItems[ColumnIndexTopStats].BackColor = Utils.GetColorFromPercent(cr.topStatsConsideredCount * 8 + 44, 0.7);
}
else
{
@@ -1106,7 +1193,7 @@ private ListViewItem CreateCreatureLvItem(Creature cr, bool displayIndex = false
if (cr.levelFound == 0)
lvi.SubItems[ColumnIndexWildLevel].ForeColor = Color.LightGray;
- // color for mutation
+ // color for mutations counter
if (cr.Mutations > 0)
{
if (cr.Mutations < Ark.MutationPossibleWithLessThan)
diff --git a/ARKBreedingStats/Form1.tester.cs b/ARKBreedingStats/Form1.tester.cs
index e4cb127d2..8148ee3d3 100644
--- a/ARKBreedingStats/Form1.tester.cs
+++ b/ARKBreedingStats/Form1.tester.cs
@@ -5,6 +5,7 @@
using System.Linq;
using System.Windows.Forms;
using ARKBreedingStats.library;
+using ARKBreedingStats.uiControls;
using ARKBreedingStats.utils;
namespace ARKBreedingStats
@@ -353,6 +354,7 @@ private void pictureBoxColorRegionsTester_Click(object sender, EventArgs e)
{
Species = speciesSelector1.SelectedSpecies,
levelsWild = GetCurrentWildLevels(false),
+ levelsMutated = CreatureCollection.CurrentCreatureCollection.Game == Ark.Asa ? GetCurrentMutLevels(false) : null,
levelsDom = GetCurrentDomLevels(false),
tamingEff = TamingEffectivenessTester,
isBred = rbBredTester.Checked,
@@ -373,6 +375,7 @@ private void PbCreatureColorsExtractor_Click(object sender, EventArgs e)
{
Species = speciesSelector1.SelectedSpecies,
levelsWild = GetCurrentWildLevels(true),
+ levelsMutated = CreatureCollection.CurrentCreatureCollection.Game == Ark.Asa ? GetCurrentMutLevels(true) : null,
levelsDom = GetCurrentDomLevels(true),
tamingEff = _extractor.UniqueTamingEffectiveness(),
isBred = rbBredExtractor.Checked,
diff --git a/ARKBreedingStats/Pedigree/PedigreeCreature.cs b/ARKBreedingStats/Pedigree/PedigreeCreature.cs
index 7cf3c6a1a..d8e804e6b 100644
--- a/ARKBreedingStats/Pedigree/PedigreeCreature.cs
+++ b/ARKBreedingStats/Pedigree/PedigreeCreature.cs
@@ -215,7 +215,7 @@ public Creature Creature
{
_labels[s].Text = _creature.levelsWild[si].ToString();
if (Properties.Settings.Default.Highlight255Level && _creature.levelsWild[si] > 253) // 255 is max, 254 is the highest that allows dom leveling
- _labels[s].BackColor = Utils.AdjustColorLight(_creature.levelsWild[si] == 254 ? Utils.Level254 : Utils.Level255, _creature.topBreedingStats[si] ? 0.2 : 0.7);
+ _labels[s].BackColor = Utils.AdjustColorLight(_creature.levelsWild[si] == 254 ? Utils.Level254 : Utils.Level255, _creature.IsTopStat(si) ? 0.2 : 0.7);
else if (Properties.Settings.Default.HighlightEvenOdd)
{
var levelForColor = Math.Min(maxChartLevel, Math.Max(minChartLevel, _creature.levelsWild[si]));
@@ -228,10 +228,10 @@ public Creature Creature
{
hue = Properties.Settings.Default.ChartHueOddMin + levelForColor * hueRangeOdd / chartLevelRange;
}
- _labels[s].BackColor = Utils.ColorFromHue(hue, _creature.topBreedingStats[si] ? 0.4 : 0.7);
+ _labels[s].BackColor = Utils.ColorFromHue(hue, _creature.IsTopStat(si) ? 0.4 : 0.7);
}
else
- _labels[s].BackColor = Utils.GetColorFromPercent((int)(_creature.levelsWild[si] * 2.5), _creature.topBreedingStats[si] ? 0.2 : 0.7);
+ _labels[s].BackColor = Utils.GetColorFromPercent((int)(_creature.levelsWild[si] * 2.5), _creature.IsTopStat(si) ? 0.2 : 0.7);
_labels[s].ForeColor = Parent?.ForeColor ?? Color.Black; // needed so text is not transparent on overlay
_ttMonospaced.SetToolTip(_labels[s], Utils.StatName(si, false, _creature.Species?.statNames) + ": "
+ $"{_creature.valuesBreeding[si] * (Utils.Precision(si) == 3 ? 100 : 1),7:#,0.0}"
@@ -241,7 +241,7 @@ public Creature Creature
));
}
// fonts are strange, and this seems to work. The assigned font-object is probably only used to read out the properties and then not used anymore.
- using (var font = new Font("Microsoft Sans Serif", 8.25F, (_creature.topBreedingStats?[si]).GetValueOrDefault() ? FontStyle.Bold : FontStyle.Regular, GraphicsUnit.Point, 0))
+ using (var font = new Font("Microsoft Sans Serif", 8.25F, _creature.IsTopStat(si) ? FontStyle.Bold : FontStyle.Regular, GraphicsUnit.Point, 0))
_labels[s].Font = font;
}
if (OnlyLevels)
diff --git a/ARKBreedingStats/Pedigree/PedigreeCreatureCompact.cs b/ARKBreedingStats/Pedigree/PedigreeCreatureCompact.cs
index f21b5afca..8acf3985a 100644
--- a/ARKBreedingStats/Pedigree/PedigreeCreatureCompact.cs
+++ b/ARKBreedingStats/Pedigree/PedigreeCreatureCompact.cs
@@ -162,7 +162,7 @@ private void DrawData(Creature creature, bool highlight, int highlightStatIndex,
var pieRadius = (int)(radiusInnerCircle + (centerCoord - radiusInnerCircle - borderWidth) * statSize);
var leftTop = centerCoord - pieRadius;
var angle = AngleOffset + anglePerStat * i++;
- brush.Color = Utils.GetColorFromPercent((int)(100 * statSize), creature.topBreedingStats[si] ? 0 : 0.7);
+ brush.Color = Utils.GetColorFromPercent((int)(100 * statSize), creature.IsTopStat(si) ? 0 : 0.7);
g.FillPie(brush, leftTop, leftTop, 2 * pieRadius, 2 * pieRadius, angle, anglePerStat);
pen.Width = highlightStatIndex == si ? 2 : 1;
diff --git a/ARKBreedingStats/Properties/AssemblyInfo.cs b/ARKBreedingStats/Properties/AssemblyInfo.cs
index 50ab4ac2f..1a2a4a781 100644
--- a/ARKBreedingStats/Properties/AssemblyInfo.cs
+++ b/ARKBreedingStats/Properties/AssemblyInfo.cs
@@ -30,6 +30,6 @@
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("0.59.6.0")]
+[assembly: AssemblyFileVersion("0.60.0.0")]
[assembly: NeutralResourcesLanguage("en")]
diff --git a/ARKBreedingStats/Properties/Resources.Designer.cs b/ARKBreedingStats/Properties/Resources.Designer.cs
index 168f7e4ac..db5458304 100644
--- a/ARKBreedingStats/Properties/Resources.Designer.cs
+++ b/ARKBreedingStats/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace ARKBreedingStats.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -98,6 +98,15 @@ internal static System.Drawing.Bitmap locked {
}
}
+ ///
+ /// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
+ ///
+ internal static System.IO.UnmanagedMemoryStream newMutation {
+ get {
+ return ResourceManager.GetStream("newMutation", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -184,5 +193,14 @@ internal static System.Drawing.Bitmap unlocked {
return ((System.Drawing.Bitmap)(obj));
}
}
+
+ ///
+ /// Looks up a localized resource of type System.IO.UnmanagedMemoryStream similar to System.IO.MemoryStream.
+ ///
+ internal static System.IO.UnmanagedMemoryStream updated {
+ get {
+ return ResourceManager.GetStream("updated", resourceCulture);
+ }
+ }
}
}
diff --git a/ARKBreedingStats/Properties/Resources.resx b/ARKBreedingStats/Properties/Resources.resx
index cba3c906c..d3252ce0a 100644
--- a/ARKBreedingStats/Properties/Resources.resx
+++ b/ARKBreedingStats/Properties/Resources.resx
@@ -157,4 +157,10 @@
..\Resources\topstat.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\Resources\updated.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\newMutation.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/ARKBreedingStats/Properties/Settings.Designer.cs b/ARKBreedingStats/Properties/Settings.Designer.cs
index 41c269f08..06aaf611e 100644
--- a/ARKBreedingStats/Properties/Settings.Designer.cs
+++ b/ARKBreedingStats/Properties/Settings.Designer.cs
@@ -2278,5 +2278,29 @@ public bool LibraryShowMutationLevelColumns {
this["LibraryShowMutationLevelColumns"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool StreamerMode {
+ get {
+ return ((bool)(this["StreamerMode"]));
+ }
+ set {
+ this["StreamerMode"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool LibraryDisplayZeroMutationLevels {
+ get {
+ return ((bool)(this["LibraryDisplayZeroMutationLevels"]));
+ }
+ set {
+ this["LibraryDisplayZeroMutationLevels"] = value;
+ }
+ }
}
}
diff --git a/ARKBreedingStats/Properties/Settings.settings b/ARKBreedingStats/Properties/Settings.settings
index 1b15c4dfd..92abc3e12 100644
--- a/ARKBreedingStats/Properties/Settings.settings
+++ b/ARKBreedingStats/Properties/Settings.settings
@@ -572,5 +572,11 @@
True
+
+ False
+
+
+ False
+
\ No newline at end of file
diff --git a/ARKBreedingStats/Resources/newMutation.wav b/ARKBreedingStats/Resources/newMutation.wav
new file mode 100644
index 000000000..82faae579
Binary files /dev/null and b/ARKBreedingStats/Resources/newMutation.wav differ
diff --git a/ARKBreedingStats/Resources/updated.wav b/ARKBreedingStats/Resources/updated.wav
new file mode 100644
index 000000000..cf03f3275
Binary files /dev/null and b/ARKBreedingStats/Resources/updated.wav differ
diff --git a/ARKBreedingStats/SpeciesSelector.cs b/ARKBreedingStats/SpeciesSelector.cs
index 4a21c20b2..c526a81d8 100644
--- a/ARKBreedingStats/SpeciesSelector.cs
+++ b/ARKBreedingStats/SpeciesSelector.cs
@@ -313,14 +313,26 @@ private void lvSpeciesInLibrary_SelectedIndexChanged(object sender, EventArgs e)
SetSpecies((Species)lvSpeciesInLibrary.SelectedItems[0].Tag, true);
}
+ ///
+ /// Return species by entry string.
+ ///
+ public bool SetSpeciesByEntryName(string entryString)
+ {
+ if (_entryList == null || string.IsNullOrEmpty(entryString)) return false;
+ var species = _entryList.FirstOrDefault(e => e.DisplayName.Equals(entryString, StringComparison.OrdinalIgnoreCase))?.Species;
+ if (species == null) return false;
+ SetSpeciesByName(null, species);
+ return true;
+ }
+
///
/// Sets the species with the speciesName. This may not be unique.
///
- ///
/// True if the species was recognized and was already or is set.
- public bool SetSpeciesByName(string speciesName)
+ public bool SetSpeciesByName(string speciesName, Species species = null)
{
- if (Values.V.TryGetSpeciesByName(speciesName, out Species species))
+ if (species != null
+ || (!string.IsNullOrEmpty(speciesName) && Values.V.TryGetSpeciesByName(speciesName, out species)))
{
var speciesWasSet = SetSpecies(species);
if (speciesWasSet)
diff --git a/ARKBreedingStats/_manifest.json b/ARKBreedingStats/_manifest.json
index 66fe0e5fa..1ee774ddc 100644
--- a/ARKBreedingStats/_manifest.json
+++ b/ARKBreedingStats/_manifest.json
@@ -4,7 +4,7 @@
"ARK Smart Breeding": {
"Id": "ARK Smart Breeding",
"Category": "main",
- "version": "0.59.6.0"
+ "version": "0.60.0.0"
},
"SpeciesColorImages": {
"Id": "SpeciesColorImages",
diff --git a/ARKBreedingStats/json/ocr/ocr_1920x1080_100.json b/ARKBreedingStats/json/ocr/ocr_1920x1080_100.json
index 23da53e40..e06d6e711 100644
--- a/ARKBreedingStats/json/ocr/ocr_1920x1080_100.json
+++ b/ARKBreedingStats/json/ocr/ocr_1920x1080_100.json
@@ -1 +1 @@
-{"Version":"2.0","description":null,"resize":1.0,"resolutionWidth":1920,"resolutionHeight":1080,"statDistance":0,"guiZoom":100,"RecognitionPatterns":{"Texts":[{"Text":"!","Patterns":[{"y":0,"Data":[2,12,14679551]},{"y":0,"Data":[1,10,895]}]},{"Text":"\"","Patterns":[{"y":0,"Data":[5,4,987377]},{"y":0,"Data":[4,3,3595]}]},{"Text":"#","Patterns":[{"y":0,"Data":[13,12,-5675593754190184176,1806490977058232337,1577345]},{"y":0,"Data":[11,10,-4526032829485600692,829739179836]}]},{"Text":"$","Patterns":[{"y":0,"Data":[7,12,-3573634383000125384,248894]},{"y":0,"Data":[6,10,259439581955807260]}]},{"Text":"%","Patterns":[{"y":0,"Data":[11,12,134599147163596804,132918339478960134,7]},{"y":0,"Data":[10,11,-7492051260306076666,30841146759792]},{"y":0,"Data":[9,10,7449013377828664838,63017188]},{"y":0,"Data":[9,10,8011956633315583495,62951652]}]},{"Text":"&","Patterns":[{"y":0,"Data":[10,12,4351539627639693576,1693112599339974]},{"y":0,"Data":[9,10,-8338676649610969914,1063967]}]},{"Text":"'","Patterns":[{"y":0,"Data":[2,4,241]},{"y":0,"Data":[2,2,7]}]},{"Text":"(","Patterns":[{"y":0,"Data":[4,15,576528938667213248]},{"y":0,"Data":[3,13,412417515760]},{"y":0,"Data":[3,15,26396868939768]}]},{"Text":")","Patterns":[{"y":0,"Data":[4,15,15780187594014721]},{"y":0,"Data":[3,13,68516179969]}]},{"Text":"*","Patterns":[{"y":0,"Data":[5,5,4595332]},{"y":0,"Data":[4,4,42850]}]},{"Text":"+","Patterns":[{"y":5,"Data":[6,6,13102793484]},{"y":3,"Data":[5,6,204731148]}]},{"Text":",","Patterns":[{"y":10,"Data":[3,4,508]},{"y":10,"Data":[3,3,126]},{"y":9,"Data":[2,3,30]}]},{"Text":"-","Patterns":[{"y":7,"Data":[4,2,255]},{"y":5,"Data":[3,2,63]}]},{"Text":".","Patterns":[{"y":10,"Data":[2,2,15]},{"y":8,"Data":[2,2,15]},{"y":8,"Data":[1,2,3]}]},{"Text":"/","Patterns":[{"y":0,"Data":[8,12,-2290065002308040704,1049344]},{"y":0,"Data":[7,11,252695124297384960,4]},{"y":0,"Data":[7,10,1156314657855504896,0]},{"y":0,"Data":[6,10,1133626670908160]}]},{"Text":"0","Patterns":[{"y":0,"Data":[10,12,4324511409900601584,17952408180884416]},{"y":0,"Data":[10,11,135173988541264120,4140321273871]},{"y":0,"Data":[9,10,4325427893140715640,16547824]}]},{"Text":"1","Patterns":[{"y":0,"Data":[3,12,68702707714]},{"y":0,"Data":[3,11,8585746434]},{"y":0,"Data":[3,10,1073740801]}]},{"Text":"2","Patterns":[{"y":0,"Data":[8,12,4432650607404264448,3287056076]},{"y":0,"Data":[8,11,3597319504896466432,12654843]},{"y":0,"Data":[7,10,-1373771675889563904,48]}]},{"Text":"3","Patterns":[{"y":0,"Data":[8,12,4351539627643911170,969408198]},{"y":0,"Data":[7,11,4171244095319055875,3963]},{"y":0,"Data":[7,10,-1153148225409202431,28]}]},{"Text":"4","Patterns":[{"y":0,"Data":[9,12,3534782280039661952,1103790862608]},{"y":0,"Data":[8,11,-4568775273204481600,3153888]},{"y":0,"Data":[8,10,-8078117213996597056,8255]}]},{"Text":"5","Patterns":[{"y":0,"Data":[7,12,4351535228523789375,246654]},{"y":0,"Data":[7,11,-1088995471009935809,513]},{"y":0,"Data":[6,10,542597737130510111]}]},{"Text":"6","Patterns":[{"y":0,"Data":[9,12,4338869619491013056,4125283328707]},{"y":0,"Data":[8,11,1792780293042585824,8132803]},{"y":0,"Data":[8,10,893429643454443760,14367]}]},{"Text":"7","Patterns":[{"y":0,"Data":[8,12,3585833139966062595,15736583]},{"y":0,"Data":[8,11,2129700729988847619,24636]},{"y":0,"Data":[7,10,8085150145732674561,0]},{"y":0,"Data":[8,10,8103226357411480577,64]}]},{"Text":"8","Patterns":[{"y":0,"Data":[9,12,4351539627975107456,8300023018438]},{"y":0,"Data":[8,11,1865401086104304064,8116719]},{"y":0,"Data":[8,10,-223190121080963900,29118]}]},{"Text":"9","Patterns":[{"y":0,"Data":[9,12,4378567770993319960,533110932332]},{"y":0,"Data":[8,11,-5717851056935669732,1034125]},{"y":0,"Data":[8,10,8252179774253890572,3975]}]},{"Text":":","Patterns":[{"y":3,"Data":[1,9,387]},{"y":2,"Data":[1,8,195]},{"y":3,"Data":[2,9,198531]}]},{"Text":";","Patterns":[{"y":3,"Data":[3,11,3774350336]},{"y":2,"Data":[3,10,138284544]}]},{"Text":"<","Patterns":[{"y":4,"Data":[7,7,438925902941704]},{"y":3,"Data":[6,6,55605576460]}]},{"Text":"=","Patterns":[{"y":5,"Data":[6,5,935194491]},{"y":4,"Data":[5,4,768955]}]},{"Text":">","Patterns":[{"y":4,"Data":[7,7,124121447510499]},{"y":3,"Data":[6,6,13360639203]}]},{"Text":"?","Patterns":[{"y":0,"Data":[8,12,3486637399386107906,8404486]},{"y":0,"Data":[7,10,4646607660775228417,0]}]},{"Text":"@","Patterns":[{"y":0,"Data":[16,15,7350093424881304000,-7270718866723136000,-9195228645226820212,17318379831393]},{"y":0,"Data":[14,13,-7199565064100151056,-62648989679651173,1108839793629196]}]},{"Text":"A","Patterns":[{"y":0,"Data":[12,12,8078903044008315904,33779127974727448,32782]},{"y":0,"Data":[10,10,-2194305236006927616,51568975367]},{"y":0,"Data":[12,12,8087373147937966080,-9205918423200987376,49167]}]},{"Text":"B","Patterns":[{"y":0,"Data":[8,12,4351533028967710719,2112815046]},{"y":0,"Data":[7,10,-238952719835199489,30]}]},{"Text":"C","Patterns":[{"y":0,"Data":[10,12,4324406062942765152,54091590150128576]},{"y":0,"Data":[9,10,2019584885671589944,50446448]}]},{"Text":"D","Patterns":[{"y":0,"Data":[10,12,4324511431203487743,4367244623348672]},{"y":0,"Data":[8,10,4327679692952569855,16280]}]},{"Text":"E","Patterns":[{"y":0,"Data":[8,12,4351539627644420095,3222037446]},{"y":0,"Data":[6,10,920759402994911231]}]},{"Text":"F","Patterns":[{"y":0,"Data":[7,12,3486637341404561407,25350]},{"y":0,"Data":[6,10,55223024169830399]}]},{"Text":"G","Patterns":[{"y":0,"Data":[10,12,4324546800431120480,69858037136622528]},{"y":0,"Data":[9,10,2019584885671589944,65140848]}]},{"Text":"H","Patterns":[{"y":0,"Data":[10,12,27028196461379583,72057589843648518]},{"y":0,"Data":[8,10,54096023676568575,65475]}]},{"Text":"I","Patterns":[{"y":0,"Data":[2,12,16777215]},{"y":0,"Data":[1,10,1023]}]},{"Text":"J","Patterns":[{"y":0,"Data":[4,12,70334380248064]},{"y":0,"Data":[3,10,536609536]}]},{"Text":"K","Patterns":[{"y":0,"Data":[10,12,-9155811445357674497,36059599995080221]},{"y":0,"Data":[9,10,3681811502760723455,33603704]}]},{"Text":"L","Patterns":[{"y":0,"Data":[6,12,864902286244052991,192]},{"y":0,"Data":[5,10,845250369946623]}]},{"Text":"M","Patterns":[{"y":0,"Data":[12,12,252218072276991999,-71810821926223648,65535]},{"y":0,"Data":[10,10,1009791719497015295,68652828430]}]},{"Text":"N","Patterns":[{"y":0,"Data":[10,12,31526846893948927,72057591622238220]},{"y":0,"Data":[9,10,216225584456409087,67108824]}]},{"Text":"O","Patterns":[{"y":0,"Data":[12,12,4324511684778508384,-256445677905902656,3843]},{"y":0,"Data":[10,10,2019584883524106296,17075519728]}]},{"Text":"P","Patterns":[{"y":0,"Data":[8,12,3513656738551169023,65044230]},{"y":0,"Data":[7,10,-2275389783044782081,0]}]},{"Text":"Q","Patterns":[{"y":0,"Data":[12,15,3567099134693212256,249956857632790720,32989629351804]},{"y":0,"Data":[10,13,3463690901644099640,2288329816673371650,0]}]},{"Text":"R","Patterns":[{"y":0,"Data":[9,12,3513656738551169023,8799346177854]},{"y":0,"Data":[8,10,-689911607977834497,32816]}]},{"Text":"S","Patterns":[{"y":0,"Data":[9,12,4351539627644149788,4133876425670]},{"y":0,"Data":[8,10,2073680907601738766,30815]}]},{"Text":"T","Patterns":[{"y":0,"Data":[8,12,4611685949758255107,3146496]},{"y":0,"Data":[7,10,1154049602464252929,0]}]},{"Text":"U","Patterns":[{"y":0,"Data":[10,12,864902286235661311,4494800850780352]},{"y":0,"Data":[8,10,865536378825212415,32728]}]},{"Text":"V","Patterns":[{"y":0,"Data":[12,12,1116925695017218051,504949032470118624,16]},{"y":0,"Data":[10,10,1009791994408483843,67571471]}]},{"Text":"W","Patterns":[{"y":0,"Data":[14,12,-9097007296847810545,-9214646046281429245,8455516175]},{"y":0,"Data":[13,10,3466707627345442831,76560158593910656,0]}]},{"Text":"X","Patterns":[{"y":0,"Data":[11,12,141926911075956737,126231692548632591,8]},{"y":0,"Data":[10,10,-4476516203142312447,34477269452]}]},{"Text":"Y","Patterns":[{"y":0,"Data":[10,12,1143918154112593921,52841012031740]},{"y":0,"Data":[9,10,-2241684246565483519,65728]}]},{"Text":"Z","Patterns":[{"y":0,"Data":[8,12,-4885334407164969469,3229355969]},{"y":0,"Data":[7,10,4332196512590137217,48]}]},{"Text":"[","Patterns":[{"y":0,"Data":[4,15,864823074145435647]},{"y":0,"Data":[4,13,3378661927419903]}]},{"Text":"\\","Patterns":[{"y":0,"Data":[8,12,126108486617591811,2148270192]},{"y":0,"Data":[7,10,865183829952830465,32]}]},{"Text":"]","Patterns":[{"y":0,"Data":[4,15,1152921504338534403]},{"y":0,"Data":[3,13,549739051009]}]},{"Text":"^","Patterns":[{"y":0,"Data":[7,6,2224894561824]},{"y":0,"Data":[6,5,820088208]}]},{"Text":"_","Patterns":[{"y":12,"Data":[8,2,65535]},{"y":10,"Data":[7,2,16383]}]},{"Text":"`","Patterns":[{"y":0,"Data":[4,2,181]},{"y":0,"Data":[3,1,7]}]},{"Text":"a","Patterns":[{"y":3,"Data":[7,9,9192507906305549536]},{"y":2,"Data":[6,8,279669406167664]}]},{"Text":"b","Patterns":[{"y":0,"Data":[7,12,871659335216861183,254071]},{"y":0,"Data":[6,10,568465942083544063]}]},{"Text":"c","Patterns":[{"y":3,"Data":[7,9,6967200823140547704]},{"y":2,"Data":[6,8,215245570342460]}]},{"Text":"d","Patterns":[{"y":0,"Data":[8,12,871659335749403584,4294967233]},{"y":0,"Data":[7,10,-271840546660112,63]}]},{"Text":"e","Patterns":[{"y":3,"Data":[8,9,7472132848649632824,14]},{"y":2,"Data":[7,8,8126335215697468]},{"y":3,"Data":[7,7,55476904689468]}]},{"Text":"f","Patterns":[{"y":0,"Data":[5,12,283193416728574]},{"y":0,"Data":[4,10,1087387647]},{"y":0,"Data":[4,10,9676258300]}]},{"Text":"g","Patterns":[{"y":3,"Data":[8,12,4432624217029075064,1072168904]},{"y":2,"Data":[7,11,-5561846539751364,2041]}]},{"Text":"h","Patterns":[{"y":0,"Data":[7,12,6757048977133567,1044735]},{"y":0,"Data":[6,10,1143940706524472319]}]},{"Text":"i","Patterns":[{"y":0,"Data":[1,12,4091]},{"y":0,"Data":[1,10,1021]},{"y":0,"Data":[3,12,1090502643]},{"y":1,"Data":[1,9,509]},{"y":1,"Data":[2,9,261117]},{"y":0,"Data":[2,12,16760827]}]},{"Text":"j","Patterns":[{"y":0,"Data":[2,15,1073602560]},{"y":0,"Data":[2,13,33537024]}]},{"Text":"k","Patterns":[{"y":0,"Data":[8,12,-9000424613577814017,2215440633]},{"y":0,"Data":[7,10,928810467592250367,32]}]},{"Text":"l","Patterns":[{"y":0,"Data":[1,12,4095]},{"y":0,"Data":[1,10,1023]}]},{"Text":"m","Patterns":[{"y":3,"Data":[12,9,9205287476162727423,17488973005569]},{"y":2,"Data":[10,8,217016098992816895,65027]},{"y":3,"Data":[11,7,-9006623177486319745,3903]}]},{"Text":"n","Patterns":[{"y":3,"Data":[7,9,9205287476162727423]},{"y":2,"Data":[6,8,279301773722367]}]},{"Text":"o","Patterns":[{"y":3,"Data":[8,9,3580493903357934712,126]},{"y":2,"Data":[7,8,35684390097092156]}]},{"Text":"p","Patterns":[{"y":3,"Data":[7,12,-2196885592294801409,31758]},{"y":2,"Data":[6,11,4471618708997283839,0]}]},{"Text":"q","Patterns":[{"y":3,"Data":[8,12,3567721930789216376,4293918488]},{"y":2,"Data":[7,11,-32596644889104324,8187]}]},{"Text":"r","Patterns":[{"y":3,"Data":[4,9,403181055]},{"y":2,"Data":[3,8,197375]},{"y":3,"Data":[5,9,137709223935]}]},{"Text":"s","Patterns":[{"y":3,"Data":[7,9,4088841016286592012]},{"y":2,"Data":[6,8,126287534086670]},{"y":3,"Data":[8,9,8986505593863748616,112]}]},{"Text":"t","Patterns":[{"y":2,"Data":[4,10,831888817407]},{"y":1,"Data":[4,9,52447411455]}]},{"Text":"u","Patterns":[{"y":3,"Data":[7,9,9214338500961435903]},{"y":2,"Data":[6,8,280922012303615]}]},{"Text":"v","Patterns":[{"y":3,"Data":[8,9,-8948760151530128377,1]},{"y":2,"Data":[7,8,861161896549895]}]},{"Text":"w","Patterns":[{"y":3,"Data":[12,9,270466176792985095,107370102844]},{"y":2,"Data":[11,8,-2288946752006357497,69624]}]},{"Text":"x","Patterns":[{"y":3,"Data":[8,9,-2244543304241541373,128]},{"y":2,"Data":[7,8,36525150153008771]}]},{"Text":"y","Patterns":[{"y":3,"Data":[8,12,-9088127652882948089,3149575]},{"y":2,"Data":[7,11,542546870131552263,12]}]},{"Text":"z","Patterns":[{"y":3,"Data":[7,9,6985639089849468800]},{"y":2,"Data":[6,8,144652815819715]}]},{"Text":"{","Patterns":[{"y":0,"Data":[5,15,2290062676612612480,1024]},{"y":0,"Data":[4,13,3378519994007648]}]},{"Text":"|","Patterns":[{"y":0,"Data":[2,15,1073741823]},{"y":0,"Data":[1,13,8191]}]},{"Text":"}","Patterns":[{"y":0,"Data":[5,15,15771391554994177,24]},{"y":0,"Data":[4,13,52792730841089]}]},{"Text":"~","Patterns":[{"y":6,"Data":[6,3,222362]},{"y":5,"Data":[5,2,703]}]},{"Text":"♀","Patterns":[{"y":0,"Data":[22,15,72023508120469630,15763114108125432,-4607463764923645892,2233851387752603655,-1143931348285667392,3]}]},{"Text":"♂","Patterns":[{"y":0,"Data":[21,15,-33812185335986240,216179379686882816,13511211203166336,-1144054909694640104,15784582485901119]}]}],"TrainingSettings":{"IsTrainingEnabled":false,"SkipName":false,"SkipTribe":false,"SkipOwner":false}},"labelRectangles":["989, 509, 129, 14","989, 552, 129, 14","989, 595, 129, 14","989, 638, 129, 14","989, 681, 129, 14","989, 724, 129, 14","989, 767, 129, 14","989, 810, 129, 14","989, 853, 129, 14","857, 199, 206, 15","850, 164, 219, 15","877, 233, 168, 13","892, 273, 150, 13"]}
\ No newline at end of file
+{"Version":"2.0","description":null,"resize":1.0,"resolutionWidth":1920,"resolutionHeight":1080,"statDistance":0,"guiZoom":100,"RecognitionPatterns":{"Texts":[{"Text":"!","Patterns":[{"y":0,"Data":[2,12,14679551]},{"y":0,"Data":[1,10,895]}]},{"Text":"\"","Patterns":[{"y":0,"Data":[5,4,987377]},{"y":0,"Data":[4,3,3595]}]},{"Text":"#","Patterns":[{"y":0,"Data":[13,12,-5675593754190184176,1806490977058232337,1577345]},{"y":0,"Data":[11,10,-4526032829485600692,829739179836]}]},{"Text":"$","Patterns":[{"y":0,"Data":[7,12,-3573634383000125384,248894]},{"y":0,"Data":[6,10,259439581955807260]}]},{"Text":"%","Patterns":[{"y":0,"Data":[11,12,134599147163596804,132918339478960134,7]},{"y":0,"Data":[10,11,-7492051260306076666,30841146759792]},{"y":0,"Data":[9,10,7449013377828664838,63017188]},{"y":0,"Data":[9,10,8011956633315583495,62951652]}]},{"Text":"&","Patterns":[{"y":0,"Data":[10,12,4351539627639693576,1693112599339974]},{"y":0,"Data":[9,10,-8338676649610969914,1063967]}]},{"Text":"'","Patterns":[{"y":0,"Data":[2,4,241]},{"y":0,"Data":[2,2,7]}]},{"Text":"(","Patterns":[{"y":0,"Data":[4,15,576528938667213248]},{"y":0,"Data":[3,13,412417515760]},{"y":0,"Data":[3,15,26396868939768]}]},{"Text":")","Patterns":[{"y":0,"Data":[4,15,15780187594014721]},{"y":0,"Data":[3,13,68516179969]}]},{"Text":"*","Patterns":[{"y":0,"Data":[5,5,4595332]},{"y":0,"Data":[4,4,42850]}]},{"Text":"+","Patterns":[{"y":5,"Data":[6,6,13102793484]},{"y":3,"Data":[5,6,204731148]}]},{"Text":",","Patterns":[{"y":10,"Data":[3,4,508]},{"y":10,"Data":[3,3,126]},{"y":9,"Data":[2,3,30]}]},{"Text":"-","Patterns":[{"y":7,"Data":[4,2,255]},{"y":5,"Data":[3,2,63]}]},{"Text":".","Patterns":[{"y":10,"Data":[2,2,15]},{"y":8,"Data":[2,2,15]},{"y":8,"Data":[1,2,3]}]},{"Text":"/","Patterns":[{"y":0,"Data":[8,12,-2290065002308040704,1049344]},{"y":0,"Data":[7,11,252695124297384960,4]},{"y":0,"Data":[7,10,1156314657855504896,0]},{"y":0,"Data":[6,10,1133626670908160]}]},{"Text":"0","Patterns":[{"y":0,"Data":[10,12,4324511409900601584,17952408180884416]},{"y":0,"Data":[10,11,135173988541264120,4140321273871]},{"y":0,"Data":[9,10,4325427893140715640,16547824]}]},{"Text":"1","Patterns":[{"y":0,"Data":[3,12,68702707714]},{"y":0,"Data":[3,11,8585746434]},{"y":0,"Data":[3,10,1073740801]}]},{"Text":"2","Patterns":[{"y":0,"Data":[8,12,4432650607404264448,3287056076]},{"y":0,"Data":[8,11,3597319504896466432,12654843]},{"y":0,"Data":[7,10,-1373771675889563904,48]}]},{"Text":"3","Patterns":[{"y":0,"Data":[8,12,4351539627643911170,969408198]},{"y":0,"Data":[7,11,4171244095319055875,3963]},{"y":0,"Data":[7,10,-1153148225409202431,28]}]},{"Text":"4","Patterns":[{"y":0,"Data":[9,12,3534782280039661952,1103790862608]},{"y":0,"Data":[8,11,-4568775273204481600,3153888]},{"y":0,"Data":[8,10,-8078117213996597056,8255]}]},{"Text":"5","Patterns":[{"y":0,"Data":[7,12,4351535228523789375,246654]},{"y":0,"Data":[7,11,-1088995471009935809,513]},{"y":0,"Data":[6,10,542597737130510111]}]},{"Text":"6","Patterns":[{"y":0,"Data":[9,12,4338869619491013056,4125283328707]},{"y":0,"Data":[8,11,1792780293042585824,8132803]},{"y":0,"Data":[8,10,893429643454443760,14367]}]},{"Text":"7","Patterns":[{"y":0,"Data":[8,12,3585833139966062595,15736583]},{"y":0,"Data":[8,11,2129700729988847619,24636]},{"y":0,"Data":[7,10,8085150145732674561,0]},{"y":0,"Data":[8,10,8103226357411480577,64]}]},{"Text":"8","Patterns":[{"y":0,"Data":[9,12,4351539627975107456,8300023018438]},{"y":0,"Data":[8,11,1865401086104304064,8116719]},{"y":0,"Data":[8,10,-223190121080963900,29118]}]},{"Text":"9","Patterns":[{"y":0,"Data":[9,12,4378567770993319960,533110932332]},{"y":0,"Data":[8,11,-5717851056935669732,1034125]},{"y":0,"Data":[8,10,8252179774253890572,3975]}]},{"Text":":","Patterns":[{"y":3,"Data":[1,9,387]},{"y":2,"Data":[1,8,195]},{"y":3,"Data":[2,9,198531]}]},{"Text":";","Patterns":[{"y":3,"Data":[3,11,3774350336]},{"y":2,"Data":[3,10,138284544]}]},{"Text":"<","Patterns":[{"y":4,"Data":[7,7,438925902941704]},{"y":3,"Data":[6,6,55605576460]}]},{"Text":"=","Patterns":[{"y":5,"Data":[6,5,935194491]},{"y":4,"Data":[5,4,768955]}]},{"Text":">","Patterns":[{"y":4,"Data":[7,7,124121447510499]},{"y":3,"Data":[6,6,13360639203]}]},{"Text":"?","Patterns":[{"y":0,"Data":[8,12,3486637399386107906,8404486]},{"y":0,"Data":[7,10,4646607660775228417,0]}]},{"Text":"@","Patterns":[{"y":0,"Data":[16,15,7350093424881304000,-7270718866723136000,-9195228645226820212,17318379831393]},{"y":0,"Data":[14,13,-7199565064100151056,-62648989679651173,1108839793629196]}]},{"Text":"A","Patterns":[{"y":0,"Data":[12,12,8078903044008315904,33779127974727448,32782]},{"y":0,"Data":[10,10,-2194305236006927616,51568975367]},{"y":0,"Data":[12,12,8087373147937966080,-9205918423200987376,49167]}]},{"Text":"B","Patterns":[{"y":0,"Data":[8,12,4351533028967710719,2112815046]},{"y":0,"Data":[7,10,-238952719835199489,30]}]},{"Text":"C","Patterns":[{"y":0,"Data":[10,12,4324406062942765152,54091590150128576]},{"y":0,"Data":[9,10,2019584885671589944,50446448]}]},{"Text":"D","Patterns":[{"y":0,"Data":[10,12,4324511431203487743,4367244623348672]},{"y":0,"Data":[8,10,4327679692952569855,16280]}]},{"Text":"E","Patterns":[{"y":0,"Data":[8,12,4351539627644420095,3222037446]},{"y":0,"Data":[6,10,920759402994911231]}]},{"Text":"F","Patterns":[{"y":0,"Data":[7,12,3486637341404561407,25350]},{"y":0,"Data":[6,10,55223024169830399]}]},{"Text":"G","Patterns":[{"y":0,"Data":[10,12,4324546800431120480,69858037136622528]},{"y":0,"Data":[9,10,2019584885671589944,65140848]}]},{"Text":"H","Patterns":[{"y":0,"Data":[10,12,27028196461379583,72057589843648518]},{"y":0,"Data":[8,10,54096023676568575,65475]}]},{"Text":"I","Patterns":[{"y":0,"Data":[2,12,16777215]},{"y":0,"Data":[1,10,1023]}]},{"Text":"J","Patterns":[{"y":0,"Data":[4,12,70334380248064]},{"y":0,"Data":[3,10,536609536]}]},{"Text":"K","Patterns":[{"y":0,"Data":[10,12,-9155811445357674497,36059599995080221]},{"y":0,"Data":[9,10,3681811502760723455,33603704]}]},{"Text":"L","Patterns":[{"y":0,"Data":[6,12,864902286244052991,192]},{"y":0,"Data":[5,10,845250369946623]}]},{"Text":"M","Patterns":[{"y":0,"Data":[12,12,252218072276991999,-71810821926223648,65535]},{"y":0,"Data":[10,10,1009791719497015295,68652828430]}]},{"Text":"N","Patterns":[{"y":0,"Data":[10,12,31526846893948927,72057591622238220]},{"y":0,"Data":[9,10,216225584456409087,67108824]}]},{"Text":"O","Patterns":[{"y":0,"Data":[12,12,4324511684778508384,-256445677905902656,3843]},{"y":0,"Data":[10,10,2019584883524106296,17075519728]}]},{"Text":"P","Patterns":[{"y":0,"Data":[8,12,3513656738551169023,65044230]},{"y":0,"Data":[7,10,-2275389783044782081,0]}]},{"Text":"Q","Patterns":[{"y":0,"Data":[12,15,3567099134693212256,249956857632790720,32989629351804]},{"y":0,"Data":[10,13,3463690901644099640,2288329816673371650,0]}]},{"Text":"R","Patterns":[{"y":0,"Data":[9,12,3513656738551169023,8799346177854]},{"y":0,"Data":[8,10,-689911607977834497,32816]}]},{"Text":"S","Patterns":[{"y":0,"Data":[9,12,4351539627644149788,4133876425670]},{"y":0,"Data":[8,10,2073680907601738766,30815]}]},{"Text":"T","Patterns":[{"y":0,"Data":[8,12,4611685949758255107,3146496]},{"y":0,"Data":[7,10,1154049602464252929,0]}]},{"Text":"U","Patterns":[{"y":0,"Data":[10,12,864902286235661311,4494800850780352]},{"y":0,"Data":[8,10,865536378825212415,32728]}]},{"Text":"V","Patterns":[{"y":0,"Data":[12,12,1116925695017218051,504949032470118624,16]},{"y":0,"Data":[10,10,1009791994408483843,67571471]}]},{"Text":"W","Patterns":[{"y":0,"Data":[14,12,-9097007296847810545,-9214646046281429245,8455516175]},{"y":0,"Data":[13,10,3466707627345442831,76560158593910656,0]}]},{"Text":"X","Patterns":[{"y":0,"Data":[11,12,141926911075956737,126231692548632591,8]},{"y":0,"Data":[10,10,-4476516203142312447,34477269452]}]},{"Text":"Y","Patterns":[{"y":0,"Data":[10,12,1143918154112593921,52841012031740]},{"y":0,"Data":[9,10,-2241684246565483519,65728]}]},{"Text":"Z","Patterns":[{"y":0,"Data":[8,12,-4885334407164969469,3229355969]},{"y":0,"Data":[7,10,4332196512590137217,48]}]},{"Text":"[","Patterns":[{"y":0,"Data":[4,15,864823074145435647]},{"y":0,"Data":[4,13,3378661927419903]}]},{"Text":"\\","Patterns":[{"y":0,"Data":[8,12,126108486617591811,2148270192]},{"y":0,"Data":[7,10,865183829952830465,32]}]},{"Text":"]","Patterns":[{"y":0,"Data":[4,15,1152921504338534403]},{"y":0,"Data":[3,13,549739051009]}]},{"Text":"^","Patterns":[{"y":0,"Data":[7,6,2224894561824]},{"y":0,"Data":[6,5,820088208]}]},{"Text":"_","Patterns":[{"y":12,"Data":[8,2,65535]},{"y":10,"Data":[7,2,16383]}]},{"Text":"`","Patterns":[{"y":0,"Data":[4,2,181]},{"y":0,"Data":[3,1,7]}]},{"Text":"a","Patterns":[{"y":3,"Data":[7,9,9192507906305549536]},{"y":2,"Data":[6,8,279669406167664]}]},{"Text":"b","Patterns":[{"y":0,"Data":[7,12,871659335216861183,254071]},{"y":0,"Data":[6,10,568465942083544063]}]},{"Text":"c","Patterns":[{"y":3,"Data":[7,9,6967200823140547704]},{"y":2,"Data":[6,8,215245570342460]}]},{"Text":"d","Patterns":[{"y":0,"Data":[8,12,871659335749403584,4294967233]},{"y":0,"Data":[7,10,-271840546660112,63]}]},{"Text":"e","Patterns":[{"y":3,"Data":[8,9,7472132848649632824,14]},{"y":2,"Data":[7,8,8126335215697468]},{"y":3,"Data":[7,7,55476904689468]}]},{"Text":"f","Patterns":[{"y":0,"Data":[5,12,283193416728574]},{"y":0,"Data":[4,10,1087387647]},{"y":0,"Data":[4,10,9676258300]}]},{"Text":"g","Patterns":[{"y":3,"Data":[8,12,4432624217029075064,1072168904]},{"y":2,"Data":[7,11,-5561846539751364,2041]}]},{"Text":"h","Patterns":[{"y":0,"Data":[7,12,6757048977133567,1044735]},{"y":0,"Data":[6,10,1143940706524472319]}]},{"Text":"i","Patterns":[{"y":0,"Data":[1,12,4091]},{"y":0,"Data":[1,10,1021]},{"y":0,"Data":[3,12,1090502643]},{"y":1,"Data":[1,9,509]},{"y":1,"Data":[2,9,261117]},{"y":0,"Data":[2,12,16760827]}]},{"Text":"j","Patterns":[{"y":0,"Data":[2,15,1073602560]},{"y":0,"Data":[2,13,33537024]}]},{"Text":"k","Patterns":[{"y":0,"Data":[8,12,-9000424613577814017,2215440633]},{"y":0,"Data":[7,10,928810467592250367,32]}]},{"Text":"l","Patterns":[{"y":0,"Data":[1,12,4095]},{"y":0,"Data":[1,10,1023]}]},{"Text":"m","Patterns":[{"y":3,"Data":[12,9,9205287476162727423,17488973005569]},{"y":2,"Data":[10,8,217016098992816895,65027]},{"y":3,"Data":[11,7,-9006623177486319745,3903]}]},{"Text":"n","Patterns":[{"y":3,"Data":[7,9,9205287476162727423]},{"y":2,"Data":[6,8,279301773722367]}]},{"Text":"o","Patterns":[{"y":3,"Data":[8,9,3580493903357934712,126]},{"y":2,"Data":[7,8,35684390097092156]}]},{"Text":"p","Patterns":[{"y":3,"Data":[7,12,-2196885592294801409,31758]},{"y":2,"Data":[6,11,4471618708997283839,0]}]},{"Text":"q","Patterns":[{"y":3,"Data":[8,12,3567721930789216376,4293918488]},{"y":2,"Data":[7,11,-32596644889104324,8187]}]},{"Text":"r","Patterns":[{"y":3,"Data":[4,9,403181055]},{"y":2,"Data":[3,8,197375]},{"y":3,"Data":[5,9,137709223935]}]},{"Text":"s","Patterns":[{"y":3,"Data":[7,9,4088841016286592012]},{"y":2,"Data":[6,8,126287534086670]},{"y":3,"Data":[8,9,8986505593863748616,112]}]},{"Text":"t","Patterns":[{"y":2,"Data":[4,10,831888817407]},{"y":1,"Data":[4,9,52447411455]}]},{"Text":"u","Patterns":[{"y":3,"Data":[7,9,9214338500961435903]},{"y":2,"Data":[6,8,280922012303615]}]},{"Text":"v","Patterns":[{"y":3,"Data":[8,9,-8948760151530128377,1]},{"y":2,"Data":[7,8,861161896549895]}]},{"Text":"w","Patterns":[{"y":3,"Data":[12,9,270466176792985095,107370102844]},{"y":2,"Data":[11,8,-2288946752006357497,69624]}]},{"Text":"x","Patterns":[{"y":3,"Data":[8,9,-2244543304241541373,128]},{"y":2,"Data":[7,8,36525150153008771]}]},{"Text":"y","Patterns":[{"y":3,"Data":[8,12,-9088127652882948089,3149575]},{"y":2,"Data":[7,11,542546870131552263,12]}]},{"Text":"z","Patterns":[{"y":3,"Data":[7,9,6985639089849468800]},{"y":2,"Data":[6,8,144652815819715]}]},{"Text":"{","Patterns":[{"y":0,"Data":[5,15,2290062676612612480,1024]},{"y":0,"Data":[4,13,3378519994007648]}]},{"Text":"|","Patterns":[{"y":0,"Data":[2,15,1073741823]},{"y":0,"Data":[1,13,8191]}]},{"Text":"}","Patterns":[{"y":0,"Data":[5,15,15771391554994177,24]},{"y":0,"Data":[4,13,52792730841089]}]},{"Text":"~","Patterns":[{"y":6,"Data":[6,3,222362]},{"y":5,"Data":[5,2,703]}]},{"Text":"♀","Patterns":[{"y":0,"Data":[22,15,72023508120469630,15763114108125432,-4607463764923645892,2233851387752603655,-1143931348285667392,3]}]},{"Text":"♂","Patterns":[{"y":0,"Data":[21,15,-33812185335986240,216179379686882816,13511211203166336,-1144054909694640104,15784582485901119]}]}],"TrainingSettings":{"IsTrainingEnabled":false,"SkipName":false,"SkipTribe":false,"SkipOwner":false}},"LabelRectangles":{"default":["989, 509, 129, 14","989, 552, 129, 14","989, 595, 129, 14","989, 638, 129, 14","989, 681, 129, 14","989, 724, 129, 14","989, 767, 129, 14","989, 810, 129, 14","989, 853, 129, 14","857, 199, 206, 15","850, 164, 219, 15","877, 233, 168, 13","892, 273, 150, 13"]},"SelectedLabelSetName":"default"}
\ No newline at end of file
diff --git a/ARKBreedingStats/json/ocr/ocr_2560x1440_100.json b/ARKBreedingStats/json/ocr/ocr_2560x1440_100.json
index 2588099b5..8b4175b99 100644
--- a/ARKBreedingStats/json/ocr/ocr_2560x1440_100.json
+++ b/ARKBreedingStats/json/ocr/ocr_2560x1440_100.json
@@ -1 +1 @@
-{"Version":"2.0","description":null,"resize":1.0,"resolutionWidth":2560,"resolutionHeight":1440,"statDistance":0,"guiZoom":100,"RecognitionPatterns":{"Texts":[{"Text":"!","Patterns":[{"y":1,"Data":[3,18,16325542206742527]}]},{"Text":"\"","Patterns":[{"y":1,"Data":[7,5,34326184959]}]},{"Text":"#","Patterns":[{"y":1,"Data":[21,18,1730233282148184064,287684887449722892,432558372080782590,-9151450814992345085,-4503546425407192193,105553519117824]}]},{"Text":"$","Patterns":[{"y":1,"Data":[10,18,-4103278981860531728,1022826792737775416,273643088650183]}]},{"Text":"%","Patterns":[{"y":1,"Data":[16,18,4106163815056277566,137325641983386488,-8680719338870668825,2049171967118085937,1006657408]},{"y":0,"Data":[12,14,-7053536677925691362,-932582802203840509,481169521857]},{"y":0,"Data":[12,14,4483561862185410590,-6693201297471932665,515452713155]},{"y":1,"Data":[15,16,8079985718278946828,270224490505649185,-4174900503865950992,61574731646467]}]},{"Text":"&","Patterns":[{"y":1,"Data":[15,18,-2170735123539362692,-560559554484271135,-286244522801241887,3941197286469663,56]}]},{"Text":"'","Patterns":[{"y":1,"Data":[2,5,1023]}]},{"Text":"(","Patterns":[{"y":1,"Data":[5,22,-8796109668416,35184438149247]}]},{"Text":")","Patterns":[{"y":1,"Data":[5,22,-549488427005,1097368338403]},{"y":4,"Data":[3,14,272864638983]}]},{"Text":"*","Patterns":[{"y":1,"Data":[7,7,21318136116748]}]},{"Text":"+","Patterns":[{"y":8,"Data":[9,9,1010811825620545592,14364]}]},{"Text":",","Patterns":[{"y":17,"Data":[5,5,1310680]},{"y":12,"Data":[3,4,2044]}]},{"Text":"-","Patterns":[{"y":11,"Data":[6,3,262143]}]},{"Text":".","Patterns":[{"y":16,"Data":[3,3,511]},{"y":12,"Data":[2,2,15]}]},{"Text":"/","Patterns":[{"y":1,"Data":[12,18,17451508685733888,35466388239679614,31525729975795838,64]},{"y":0,"Data":[9,14,-2297396698093182976,281595267259905]},{"y":0,"Data":[9,13,2234876663345188864,1100451660024]},{"y":0,"Data":[8,14,-572096859246413824,51555340160]}]},{"Text":"0","Patterns":[{"y":1,"Data":[15,18,549439034279084016,-576322213305643144,35465982357528577,288214982963234748,1023]},{"y":0,"Data":[12,14,531453342862213312,-5185965275232861960,136935630595]},{"y":0,"Data":[13,16,-1150819108452032520,-2304787461407776761,4610696728277934087,8184]}]},{"Text":"1","Patterns":[{"y":1,"Data":[5,18,-68717903866,67108863]},{"y":0,"Data":[3,14,4398046494722]},{"y":0,"Data":[4,16,-131070]},{"y":0,"Data":[5,14,-144115188344258558,31]}]},{"Text":"2","Patterns":[{"y":1,"Data":[12,18,142989833631924238,-306105273587595272,2300811624938727297,14687800]},{"y":0,"Data":[9,14,276988695431673862,3465733197579215095]},{"y":0,"Data":[10,16,-575352410490806266,-2031150885676778493,3766280702]}]},{"Text":"3","Patterns":[{"y":1,"Data":[11,18,-2163917507132424185,-560559554484271136,-3474527130504666655,15]},{"y":0,"Data":[8,14,-4340609070631161853,137413182501360]},{"y":0,"Data":[10,16,-4502507245899620345,-33226378460797,1044152190]}]},{"Text":"4","Patterns":[{"y":1,"Data":[14,18,-2304734697466349568,-4357302029505535985,-139365245363745273,54043401703651391]},{"y":0,"Data":[11,14,4331267114076734976,4607463637696742278,4194688]},{"y":0,"Data":[13,16,2296870445095328768,2019613877842222320,1729663598741028835,4096]},{"y":0,"Data":[10,13,7053547462563727232,4620676722868667406,0]},{"y":0,"Data":[11,14,4326763239554679552,4607322899134579650,2099196]}]},{"Text":"5","Patterns":[{"y":1,"Data":[12,18,7059427591953679328,-569566788098881568,-1119148769023631135,2031631]},{"y":0,"Data":[9,14,7188183737201324287,504541764850036976]},{"y":0,"Data":[10,16,-4556586399423274498,-899627269675040573,1057193859]}]},{"Text":"6","Patterns":[{"y":1,"Data":[13,18,9088262965693546368,-568317737051243280,-572504694404685711,541174251551]},{"y":0,"Data":[10,14,7404405454224101344,2288078762587986160,480]},{"y":0,"Data":[12,16,-2243794301736697920,-2250743424589840178,864760949582651840]}]},{"Text":"7","Patterns":[{"y":1,"Data":[12,18,141863903660081159,-4327833965794162696,283731157457503217,960]},{"y":0,"Data":[9,14,-4360593020886654973,1970857541925063]},{"y":0,"Data":[11,16,-574244103575371769,71780409994067463,30066802751]},{"y":0,"Data":[10,14,-8937376417146945533,-4607462811190103857,0]}]},{"Text":"8","Patterns":[{"y":1,"Data":[13,18,-1018095025189749700,-560559554484271135,-528729742253855,1083346763679]},{"y":0,"Data":[11,14,-4340449831568833024,-5044098038478655248,15730671]},{"y":0,"Data":[13,16,-2022257527479334912,-4484527756880387641,4556657105958855111,3072]}]},{"Text":"9","Patterns":[{"y":1,"Data":[13,18,-4485444628543700488,-2566983514540603583,-873139651416196736,34226044803]},{"y":0,"Data":[10,14,-8951452811812437764,287700518790717689,62]},{"y":0,"Data":[12,16,4829833003767038204,4252368931551175427,27025978899177351]}]},{"Text":":","Patterns":[{"y":6,"Data":[3,13,481564883975]},{"y":4,"Data":[2,12,14712327]},{"y":5,"Data":[2,11,3153411]}]},{"Text":";","Patterns":[{"y":6,"Data":[5,16,4037468304070197248,2055]}]},{"Text":"<","Patterns":[{"y":7,"Data":[11,11,-1288660680781348752,126655199102223928]}]},{"Text":"=","Patterns":[{"y":9,"Data":[9,7,8351872316837001715]}]},{"Text":">","Patterns":[{"y":7,"Data":[11,11,-1288901282071298297,7885151801377648]}]},{"Text":"?","Patterns":[{"y":1,"Data":[11,18,-4469276791359668217,-4598052022172842009,558455115594203361,0]}]},{"Text":"@","Patterns":[{"y":1,"Data":[24,22,-139638043770944,1015949255508464,-222989876083621778,3571126657511528947,-3571245546502069492,-4357232883757245416,8950904744193352703,18012208076031744,508]}]},{"Text":"A","Patterns":[{"y":1,"Data":[19,18,17732987957411840,-4602749052621193153,-4327835838431952865,35747459213246209,1090719796170720,2097166]},{"y":1,"Data":[16,16,2287967153330118656,1010776774528467952,1143923067194377743,-4611422131408846976]}]},{"Text":"B","Patterns":[{"y":1,"Data":[14,18,144115188075855871,-562811414427727904,7997845516770074817,135215734493003772]}]},{"Text":"C","Patterns":[{"y":1,"Data":[14,18,544935288621768672,-576321113827570052,35465982357528577,1008840951279387128]},{"y":0,"Data":[11,13,-9192401818209025568,24773646711058439,24587]}]},{"Text":"D","Patterns":[{"y":1,"Data":[16,18,144115188075855871,-576322213309839392,35465982357528577,-8935157122074672196,133695487]}]},{"Text":"E","Patterns":[{"y":1,"Data":[13,18,-2161727821137838081,-560559554484271136,4070706641703002337,3848305435128]},{"y":0,"Data":[11,16,-2195504818343116801,-2195538319599214201,246324453171591]}]},{"Text":"F","Patterns":[{"y":1,"Data":[12,18,-2161727821137838081,-4595800213829744896,4066765976996610273,448]}]},{"Text":"G","Patterns":[{"y":1,"Data":[14,18,544935288621768672,-576321113827570052,35465982357528577,1148453072303817208]}]},{"Text":"H","Patterns":[{"y":1,"Data":[16,18,-2287828610704211969,15762658825568256,4035240659345473760,-4383014068224,4294967295]}]},{"Text":"I","Patterns":[{"y":1,"Data":[3,18,18014398509481983]}]},{"Text":"J","Patterns":[{"y":1,"Data":[7,18,15762658825568256,288217181978623856]}]},{"Text":"K","Patterns":[{"y":1,"Data":[17,18,18014398509481983,15762598695796736,-8952890114301754376,4539663471578187655,562953174677504]}]},{"Text":"L","Patterns":[{"y":1,"Data":[11,18,18014398509481983,4035240659345473760,3940664706392064,56]},{"y":0,"Data":[9,16,-2305561534236983297,-2305596714850918400,57344]},{"y":0,"Data":[10,16,-4611404543450807296,-4611474908973580288,3221274624]}]},{"Text":"M","Patterns":[{"y":1,"Data":[19,18,1152921504606846975,141863455907970048,4362879184674688,17733194124034110,-4293951457,4194303]},{"y":1,"Data":[17,16,16888636041592831,-576391482806631952,279257265985351680,-4293000968,32767]}]},{"Text":"N","Patterns":[{"y":1,"Data":[16,18,576460752303423487,4222132703739392,-4611549678859714320,-2267740766205,4294967295]}]},{"Text":"O","Patterns":[{"y":1,"Data":[17,18,544935288621768672,-576322213339197572,35465982357528577,-1765274989098958344,70301098381311]}]},{"Text":"P","Patterns":[{"y":1,"Data":[14,18,144115188075855871,-4584541274891090176,4391042742412050881,527774137778048]}]},{"Text":"Q","Patterns":[{"y":1,"Data":[17,22,1152851273268076512,-2305348503606935432,-9221386318381580176,8435455118803395,-5497524924182530,70300091806239]}]},{"Text":"R","Patterns":[{"y":1,"Data":[15,18,144115188075855871,-4580037675263719680,4391570508932907969,864941546506059743,8192]}]},{"Text":"S","Patterns":[{"y":1,"Data":[13,18,-2163911528271986180,-560559554484271136,-1117141061865053983,1091030729182]},{"y":1,"Data":[13,16,-2177665249145257968,-2196699421590953529,4541738951479910787,7680]},{"y":3,"Data":[9,12,4351539558966616088,8531888333766]}]},{"Text":"T","Patterns":[{"y":1,"Data":[13,18,126101270604546055,-67107072,31525317651202047,117440960]},{"y":0,"Data":[9,13,-549554462717,3298937602047]},{"y":1,"Data":[12,16,844437815230467,2251799813619715,844437815230467]},{"y":4,"Data":[9,11,72057585452189697,16785412]}]},{"Text":"U","Patterns":[{"y":1,"Data":[16,18,4503539497568255,4035240659349667964,3940664706392064,-864693464901615560,67094527]}]},{"Text":"V","Patterns":[{"y":1,"Data":[18,18,9187351967213289475,1148419000197183488,-9219009158072697344,-2296870857963749313,3377764146069519,0]},{"y":0,"Data":[16,16,142989833631891459,-1152644426611290144,283761688132515840,281539405349118]}]},{"Text":"W","Patterns":[{"y":1,"Data":[23,18,-285978644923547641,1134924148594442495,139615917841582048,2234209758348224,-4610564516032282370,-285979126106427377,4096]}]},{"Text":"X","Patterns":[{"y":1,"Data":[18,18,285979108914888705,274442371254468344,-144045918579062792,-594342142184309247,1970341480102912,8]}]},{"Text":"Y","Patterns":[{"y":1,"Data":[16,18,1116893738381869057,34902930398182400,4472072248118804416,8070586873770180096,16384]}]},{"Text":"Z","Patterns":[{"y":1,"Data":[13,18,143834260709539847,-542544975582459906,287669485667082481,3848557037560]}]},{"Text":"[","Patterns":[{"y":1,"Data":[6,22,-1,545357897400351,12]}]},{"Text":"\\","Patterns":[{"y":1,"Data":[12,18,2269816342500343809,141863523553769472,4362870594740096,8388664]}]},{"Text":"]","Patterns":[{"y":1,"Data":[6,22,136339474350087,-4194273,15]}]},{"Text":"^","Patterns":[{"y":1,"Data":[12,9,270464346063307008,8821925771295]}]},{"Text":"_","Patterns":[{"y":19,"Data":[12,3,68719476735]}]},{"Text":"`","Patterns":[{"y":1,"Data":[5,3,20441]}]},{"Text":"a","Patterns":[{"y":6,"Data":[11,13,-8773520101673996352,-13511472200486713,32755]},{"y":5,"Data":[10,12,4351539642671965120,72004810608894914]},{"y":4,"Data":[8,9,9201541476357498866,254]}]},{"Text":"b","Patterns":[{"y":1,"Data":[12,18,3476778912330022911,4036929515648245984,-285979109972975560,2080783]},{"y":0,"Data":[9,13,218451384737988606,1056076742799457]}]},{"Text":"c","Patterns":[{"y":6,"Data":[11,13,-2272189569753448352,-9188464878614939633,28703]}]},{"Text":"d","Patterns":[{"y":1,"Data":[11,18,4043737719489200000,4036929515648246000,-2132746184,31]},{"y":0,"Data":[9,13,-9003794678155574400,9006099710353505]}]},{"Text":"e","Patterns":[{"y":6,"Data":[11,13,-3585300985993509892,-6927398350325483065,29683]},{"y":4,"Data":[9,9,4963654244503518264,7375]},{"y":5,"Data":[11,12,3919106358481240160,8703184834156848070,0]}]},{"Text":"f","Patterns":[{"y":0,"Data":[9,19,-7061644490596417544,224054508811743233,100663520]},{"y":0,"Data":[5,13,229711622032064508,0]},{"y":0,"Data":[6,17,234187163443265528,207619632]}]},{"Text":"g","Patterns":[{"y":6,"Data":[12,17,-1135403539355663364,137079359490605180,-288230376152889402,255]},{"y":5,"Data":[11,16,-4105374115425419168,-1872435300412439033,70362301691655]}]},{"Text":"h","Patterns":[{"y":1,"Data":[12,18,3476778912330022911,1688856302764032,-283727326265475048,16769087]}]},{"Text":"i","Patterns":[{"y":1,"Data":[3,18,18012749235748839]},{"y":1,"Data":[3,16,140677358026739]},{"y":0,"Data":[2,13,67010546]},{"y":1,"Data":[2,16,4294180851]}]},{"Text":"j","Patterns":[{"y":1,"Data":[4,22,-422212566777856,8388511]}]},{"Text":"k","Patterns":[{"y":1,"Data":[13,18,3476778912330022911,217861638416556032,-139766061361783272,2199035965496]},{"y":1,"Data":[11,16,27303072740933631,8948683452206547040,215370730370672]}]},{"Text":"l","Patterns":[{"y":1,"Data":[3,18,18014398509481983]},{"y":1,"Data":[2,16,4294967295]}]},{"Text":"m","Patterns":[{"y":6,"Data":[19,13,31529045615181823,-1098572054522,54049794477490171,36024398972387384]},{"y":7,"Data":[12,8,107803820880396031,4278124801]}]},{"Text":"n","Patterns":[{"y":6,"Data":[12,13,27025445987811327,-8999502270644218,268337147]},{"y":7,"Data":[8,8,-72337965189759223]}]},{"Text":"o","Patterns":[{"y":6,"Data":[12,13,-4594230461768678404,-1117240732616697,33300473]},{"y":4,"Data":[9,9,7057263864975326460,31871]}]},{"Text":"p","Patterns":[{"y":6,"Data":[12,17,6926536226895822847,254172743642234928,-4602687477891856626,31]},{"y":5,"Data":[11,16,433330726646054910,506107431554845699,412383709182]},{"y":7,"Data":[8,11,2417326350311358463,229884]}]},{"Text":"q","Patterns":[{"y":6,"Data":[12,17,-2290013906707675140,110057555566379120,-32766194,4095]}]},{"Text":"r","Patterns":[{"y":6,"Data":[6,13,31533443661692927,6]},{"y":4,"Data":[5,9,69122916351]},{"y":4,"Data":[4,9,403439615]}]},{"Text":"s","Patterns":[{"y":6,"Data":[10,13,-3585302962172334978,-508933149943072313,1]},{"y":5,"Data":[10,12,4351539911567073304,16932358779069382]}]},{"Text":"t","Patterns":[{"y":4,"Data":[6,15,-3602422308280483841,58746624]},{"y":3,"Data":[5,14,918791497648693247,48]}]},{"Text":"u","Patterns":[{"y":6,"Data":[12,13,-4607744819031186433,-7317937027270655,268435455]},{"y":5,"Data":[10,12,864902294825596927,72057591889789024]}]},{"Text":"v","Patterns":[{"y":6,"Data":[13,13,-143554428622610429,2297954004820311553,268664956]}]},{"Text":"w","Patterns":[{"y":6,"Data":[19,13,-1148422234373103613,135177291909578241,-9205919497360375556,4414723063783]}]},{"Text":"x","Patterns":[{"y":6,"Data":[13,13,9207485709806497793,-4472182045208214544,1099981451295]}]},{"Text":"y","Patterns":[{"y":6,"Data":[13,17,2297963900303179779,-2296976410543129076,4035361614088894479,4096]},{"y":5,"Data":[12,16,-2018526881273413629,283761412197613536,281505045610748]}]},{"Text":"z","Patterns":[{"y":6,"Data":[10,13,-2431976792454562813,-9152422883697427993,3]}]},{"Text":"{","Patterns":[{"y":1,"Data":[7,22,1150669737005423616,1125779647750136,30]}]},{"Text":"|","Patterns":[{"y":1,"Data":[3,22,-1,3]}]},{"Text":"}","Patterns":[{"y":1,"Data":[7,22,-126105187583524863,1116901503563456511,114688]}]},{"Text":"~","Patterns":[{"y":11,"Data":[9,3,131856091]}]},{"Text":"♂","Patterns":[{"y":0,"Data":[27,23,-1123701151957248,284835151957982979,1143914579693173728,-576458621999386624,30786333442048,2111062576988190,142989305080447968,-4499238087823872,-8070451356881715709,133156700131]}]},{"Text":"♀","Patterns":[{"y":0,"Data":[29,23,1152851170214019580,-2303573626071285792,2216615573716999,1292533238815785952,-144106409162115072,-4611405093173002237,5048957996630143,8866462806575228,-9151350718244714528,144080072419065855,8128]}]}],"TrainingSettings":{"IsTrainingEnabled":false,"SkipName":false,"SkipTribe":false,"SkipOwner":false}},"labelRectangles":["1294, 679, 195, 18","1294, 736, 195, 18","1294, 793, 195, 18","1294, 851, 195, 18","1294, 908, 195, 18","1294, 965, 195, 18","1294, 1023, 195, 18","1294, 1080, 195, 18","1294, 1137, 195, 18","1166, 265, 231, 20","1125, 218, 308, 23","1179, 311, 216, 18","1212, 357, 150, 18"]}
\ No newline at end of file
+{"Version":"2.0","description":null,"resize":1.0,"resolutionWidth":2560,"resolutionHeight":1440,"statDistance":0,"guiZoom":100,"RecognitionPatterns":{"Texts":[{"Text":"!","Patterns":[{"y":1,"Data":[3,18,16325542206742527]}]},{"Text":"\"","Patterns":[{"y":1,"Data":[7,5,34326184959]}]},{"Text":"#","Patterns":[{"y":1,"Data":[21,18,1730233282148184064,287684887449722892,432558372080782590,-9151450814992345085,-4503546425407192193,105553519117824]}]},{"Text":"$","Patterns":[{"y":1,"Data":[10,18,-4103278981860531728,1022826792737775416,273643088650183]}]},{"Text":"%","Patterns":[{"y":1,"Data":[16,18,4106163815056277566,137325641983386488,-8680719338870668825,2049171967118085937,1006657408]},{"y":0,"Data":[12,14,-7053536677925691362,-932582802203840509,481169521857]},{"y":0,"Data":[12,14,4483561862185410590,-6693201297471932665,515452713155]},{"y":1,"Data":[15,16,8079985718278946828,270224490505649185,-4174900503865950992,61574731646467]}]},{"Text":"&","Patterns":[{"y":1,"Data":[15,18,-2170735123539362692,-560559554484271135,-286244522801241887,3941197286469663,56]}]},{"Text":"'","Patterns":[{"y":1,"Data":[2,5,1023]}]},{"Text":"(","Patterns":[{"y":1,"Data":[5,22,-8796109668416,35184438149247]}]},{"Text":")","Patterns":[{"y":1,"Data":[5,22,-549488427005,1097368338403]},{"y":4,"Data":[3,14,272864638983]}]},{"Text":"*","Patterns":[{"y":1,"Data":[7,7,21318136116748]}]},{"Text":"+","Patterns":[{"y":8,"Data":[9,9,1010811825620545592,14364]}]},{"Text":",","Patterns":[{"y":17,"Data":[5,5,1310680]},{"y":12,"Data":[3,4,2044]}]},{"Text":"-","Patterns":[{"y":11,"Data":[6,3,262143]}]},{"Text":".","Patterns":[{"y":16,"Data":[3,3,511]},{"y":12,"Data":[2,2,15]},{"y":12,"Data":[2,1,3]}]},{"Text":"/","Patterns":[{"y":1,"Data":[12,18,17451508685733888,35466388239679614,31525729975795838,64]},{"y":0,"Data":[9,14,-2297396698093182976,281595267259905]},{"y":0,"Data":[9,13,2234876663345188864,1100451660024]},{"y":0,"Data":[8,14,-572096859246413824,51555340160]}]},{"Text":"0","Patterns":[{"y":1,"Data":[15,18,549439034279084016,-576322213305643144,35465982357528577,288214982963234748,1023]},{"y":0,"Data":[12,14,531453342862213312,-5185965275232861960,136935630595]},{"y":0,"Data":[13,16,-1150819108452032520,-2304787461407776761,4610696728277934087,8184]}]},{"Text":"1","Patterns":[{"y":1,"Data":[5,18,-68717903866,67108863]},{"y":0,"Data":[3,14,4398046494722]},{"y":0,"Data":[4,16,-131070]},{"y":0,"Data":[5,14,-144115188344258558,31]}]},{"Text":"2","Patterns":[{"y":1,"Data":[12,18,142989833631924238,-306105273587595272,2300811624938727297,14687800]},{"y":0,"Data":[9,14,276988695431673862,3465733197579215095]},{"y":0,"Data":[10,16,-575352410490806266,-2031150885676778493,3766280702]}]},{"Text":"3","Patterns":[{"y":1,"Data":[11,18,-2163917507132424185,-560559554484271136,-3474527130504666655,15]},{"y":0,"Data":[8,14,-4340609070631161853,137413182501360]},{"y":0,"Data":[10,16,-4502507245899620345,-33226378460797,1044152190]}]},{"Text":"4","Patterns":[{"y":1,"Data":[14,18,-2304734697466349568,-4357302029505535985,-139365245363745273,54043401703651391]},{"y":0,"Data":[11,14,4331267114076734976,4607463637696742278,4194688]},{"y":0,"Data":[13,16,2296870445095328768,2019613877842222320,1729663598741028835,4096]},{"y":0,"Data":[10,13,7053547462563727232,4620676722868667406,0]},{"y":0,"Data":[11,14,4326763239554679552,4607322899134579650,2099196]}]},{"Text":"5","Patterns":[{"y":1,"Data":[12,18,7059427591953679328,-569566788098881568,-1119148769023631135,2031631]},{"y":0,"Data":[9,14,7188183737201324287,504541764850036976]},{"y":0,"Data":[10,16,-4556586399423274498,-899627269675040573,1057193859]},{"y":0,"Data":[9,13,439154572344160256,4365052808814787]}]},{"Text":"6","Patterns":[{"y":1,"Data":[13,18,9088262965693546368,-568317737051243280,-572504694404685711,541174251551]},{"y":0,"Data":[10,14,7404405454224101344,2288078762587986160,480]},{"y":0,"Data":[12,16,-2243794301736697920,-2250743424589840178,864760949582651840]}]},{"Text":"7","Patterns":[{"y":1,"Data":[12,18,141863903660081159,-4327833965794162696,283731157457503217,960]},{"y":0,"Data":[9,14,-4360593020886654973,1970857541925063]},{"y":0,"Data":[11,16,-574244103575371769,71780409994067463,30066802751]},{"y":0,"Data":[10,14,-8937376417146945533,-4607462811190103857,0]},{"y":1,"Data":[10,13,8655637970969174017,9014899998868418,0]}]},{"Text":"8","Patterns":[{"y":1,"Data":[13,18,-1018095025189749700,-560559554484271135,-528729742253855,1083346763679]},{"y":0,"Data":[11,14,-4340449831568833024,-5044098038478655248,15730671]},{"y":0,"Data":[13,16,-2022257527479334912,-4484527756880387641,4556657105958855111,3072]}]},{"Text":"9","Patterns":[{"y":1,"Data":[13,18,-4485444628543700488,-2566983514540603583,-873139651416196736,34226044803]},{"y":0,"Data":[10,14,-8951452811812437764,287700518790717689,62]},{"y":0,"Data":[12,16,4829833003767038204,4252368931551175427,27025978899177351]}]},{"Text":":","Patterns":[{"y":6,"Data":[3,13,481564883975]},{"y":4,"Data":[2,12,14712327]},{"y":5,"Data":[2,11,3153411]}]},{"Text":";","Patterns":[{"y":6,"Data":[5,16,4037468304070197248,2055]}]},{"Text":"<","Patterns":[{"y":7,"Data":[11,11,-1288660680781348752,126655199102223928]}]},{"Text":"=","Patterns":[{"y":9,"Data":[9,7,8351872316837001715]}]},{"Text":">","Patterns":[{"y":7,"Data":[11,11,-1288901282071298297,7885151801377648]}]},{"Text":"?","Patterns":[{"y":1,"Data":[11,18,-4469276791359668217,-4598052022172842009,558455115594203361,0]}]},{"Text":"@","Patterns":[{"y":1,"Data":[24,22,-139638043770944,1015949255508464,-222989876083621778,3571126657511528947,-3571245546502069492,-4357232883757245416,8950904744193352703,18012208076031744,508]}]},{"Text":"A","Patterns":[{"y":1,"Data":[19,18,17732987957411840,-4602749052621193153,-4327835838431952865,35747459213246209,1090719796170720,2097166]},{"y":1,"Data":[16,16,2287967153330118656,1010776774528467952,1143923067194377743,-4611422131408846976]}]},{"Text":"B","Patterns":[{"y":1,"Data":[14,18,144115188075855871,-562811414427727904,7997845516770074817,135215734493003772]},{"y":1,"Data":[12,16,-2304717109306851329,-2178649838201872381,4475592036103184835]}]},{"Text":"C","Patterns":[{"y":1,"Data":[14,18,544935288621768672,-576321113827570052,35465982357528577,1008840951279387128]},{"y":0,"Data":[11,13,-9192401818209025568,24773646711058439,24587]}]},{"Text":"D","Patterns":[{"y":1,"Data":[16,18,144115188075855871,-576322213309839392,35465982357528577,-8935157122074672196,133695487]}]},{"Text":"E","Patterns":[{"y":1,"Data":[13,18,-2161727821137838081,-560559554484271136,4070706641703002337,3848305435128]},{"y":0,"Data":[11,16,-2195504818343116801,-2195538319599214201,246324453171591]}]},{"Text":"F","Patterns":[{"y":1,"Data":[12,18,-2161727821137838081,-4595800213829744896,4066765976996610273,448]}]},{"Text":"G","Patterns":[{"y":1,"Data":[14,18,544935288621768672,-576321113827570052,35465982357528577,1148453072303817208]}]},{"Text":"H","Patterns":[{"y":1,"Data":[16,18,-2287828610704211969,15762658825568256,4035240659345473760,-4383014068224,4294967295]}]},{"Text":"I","Patterns":[{"y":1,"Data":[3,18,18014398509481983]}]},{"Text":"J","Patterns":[{"y":1,"Data":[7,18,15762658825568256,288217181978623856]}]},{"Text":"K","Patterns":[{"y":1,"Data":[17,18,18014398509481983,15762598695796736,-8952890114301754376,4539663471578187655,562953174677504]}]},{"Text":"L","Patterns":[{"y":1,"Data":[11,18,18014398509481983,4035240659345473760,3940664706392064,56]},{"y":0,"Data":[9,16,-2305561534236983297,-2305596714850918400,57344]},{"y":0,"Data":[10,16,-4611404543450807296,-4611474908973580288,3221274624]}]},{"Text":"M","Patterns":[{"y":1,"Data":[19,18,1152921504606846975,141863455907970048,4362879184674688,17733194124034110,-4293951457,4194303]},{"y":1,"Data":[17,16,16888636041592831,-576391482806631952,279257265985351680,-4293000968,32767]}]},{"Text":"N","Patterns":[{"y":1,"Data":[16,18,576460752303423487,4222132703739392,-4611549678859714320,-2267740766205,4294967295]}]},{"Text":"O","Patterns":[{"y":1,"Data":[17,18,544935288621768672,-576322213339197572,35465982357528577,-1765274989098958344,70301098381311]}]},{"Text":"P","Patterns":[{"y":1,"Data":[14,18,144115188075855871,-4584541274891090176,4391042742412050881,527774137778048]}]},{"Text":"Q","Patterns":[{"y":1,"Data":[17,22,1152851273268076512,-2305348503606935432,-9221386318381580176,8435455118803395,-5497524924182530,70300091806239]}]},{"Text":"R","Patterns":[{"y":1,"Data":[15,18,144115188075855871,-4580037675263719680,4391570508932907969,864941546506059743,8192]},{"y":1,"Data":[13,16,1125899906842623,1117745391757099011,-4594533093838209597,32768]},{"y":1,"Data":[12,16,844442110001151,2288681294915371267,-4611439184761176857]},{"y":1,"Data":[12,16,844442110001151,2270666896405889027,-4604683785185837881]}]},{"Text":"S","Patterns":[{"y":1,"Data":[13,18,-2163911528271986180,-560559554484271136,-1117141061865053983,1091030729182]},{"y":1,"Data":[13,16,-2177665249145257968,-2196699421590953529,4541738951479910787,7680]},{"y":3,"Data":[9,12,4351539558966616088,8531888333766]}]},{"Text":"T","Patterns":[{"y":1,"Data":[13,18,126101270604546055,-67107072,31525317651202047,117440960]},{"y":0,"Data":[9,13,-549554462717,3298937602047]},{"y":1,"Data":[12,16,844437815230467,2251799813619715,844437815230467]},{"y":4,"Data":[9,11,72057585452189697,16785412]},{"y":0,"Data":[9,13,-7146624229373,2199291740167]}]},{"Text":"U","Patterns":[{"y":1,"Data":[16,18,4503539497568255,4035240659349667964,3940664706392064,-864693464901615560,67094527]}]},{"Text":"V","Patterns":[{"y":1,"Data":[18,18,9187351967213289475,1148419000197183488,-9219009158072697344,-2296870857963749313,3377764146069519,0]},{"y":0,"Data":[16,16,142989833631891459,-1152644426611290144,283761688132515840,281539405349118]}]},{"Text":"W","Patterns":[{"y":1,"Data":[23,18,-285978644923547641,1134924148594442495,139615917841582048,2234209758348224,-4610564516032282370,-285979126106427377,4096]}]},{"Text":"X","Patterns":[{"y":1,"Data":[18,18,285979108914888705,274442371254468344,-144045918579062792,-594342142184309247,1970341480102912,8]}]},{"Text":"Y","Patterns":[{"y":1,"Data":[16,18,1116893738381869057,34902930398182400,4472072248118804416,8070586873770180096,16384]}]},{"Text":"Z","Patterns":[{"y":1,"Data":[13,18,143834260709539847,-542544975582459906,287669485667082481,3848557037560]}]},{"Text":"[","Patterns":[{"y":1,"Data":[6,22,-1,545357897400351,12]}]},{"Text":"\\","Patterns":[{"y":1,"Data":[12,18,2269816342500343809,141863523553769472,4362870594740096,8388664]}]},{"Text":"]","Patterns":[{"y":1,"Data":[6,22,136339474350087,-4194273,15]}]},{"Text":"^","Patterns":[{"y":1,"Data":[12,9,270464346063307008,8821925771295]}]},{"Text":"_","Patterns":[{"y":19,"Data":[12,3,68719476735]},{"y":17,"Data":[10,2,1048575]}]},{"Text":"`","Patterns":[{"y":1,"Data":[5,3,20441]}]},{"Text":"a","Patterns":[{"y":6,"Data":[11,13,-8773520101673996352,-13511472200486713,32755]},{"y":5,"Data":[10,12,4351539642671965120,72004810608894914]},{"y":4,"Data":[8,9,9201541476357498866,254]}]},{"Text":"b","Patterns":[{"y":1,"Data":[12,18,3476778912330022911,4036929515648245984,-285979109972975560,2080783]},{"y":0,"Data":[9,13,218451384737988606,1056076742799457]}]},{"Text":"c","Patterns":[{"y":6,"Data":[11,13,-2272189569753448352,-9188464878614939633,28703]}]},{"Text":"d","Patterns":[{"y":1,"Data":[11,18,4043737719489200000,4036929515648246000,-2132746184,31]},{"y":0,"Data":[9,13,-9003794678155574400,9006099710353505]}]},{"Text":"e","Patterns":[{"y":6,"Data":[11,13,-3585300985993509892,-6927398350325483065,29683]},{"y":4,"Data":[9,9,4963654244503518264,7375]},{"y":5,"Data":[11,12,3919106358481240160,8703184834156848070,0]}]},{"Text":"f","Patterns":[{"y":0,"Data":[9,19,-7061644490596417544,224054508811743233,100663520]},{"y":0,"Data":[5,13,229711622032064508,0]},{"y":0,"Data":[6,17,234187163443265528,207619632]}]},{"Text":"g","Patterns":[{"y":6,"Data":[12,17,-1135403539355663364,137079359490605180,-288230376152889402,255]},{"y":5,"Data":[11,16,-4105374115425419168,-1872435300412439033,70362301691655]}]},{"Text":"h","Patterns":[{"y":1,"Data":[12,18,3476778912330022911,1688856302764032,-283727326265475048,16769087]}]},{"Text":"i","Patterns":[{"y":1,"Data":[3,18,18012749235748839]},{"y":1,"Data":[3,16,140677358026739]},{"y":0,"Data":[2,13,67010546]},{"y":1,"Data":[2,16,4294180851]}]},{"Text":"j","Patterns":[{"y":1,"Data":[4,22,-422212566777856,8388511]}]},{"Text":"k","Patterns":[{"y":1,"Data":[13,18,3476778912330022911,217861638416556032,-139766061361783272,2199035965496]},{"y":1,"Data":[11,16,27303072740933631,8948683452206547040,215370730370672]}]},{"Text":"l","Patterns":[{"y":1,"Data":[3,18,18014398509481983]},{"y":1,"Data":[2,16,4294967295]}]},{"Text":"m","Patterns":[{"y":6,"Data":[19,13,31529045615181823,-1098572054522,54049794477490171,36024398972387384]},{"y":7,"Data":[12,8,107803820880396031,4278124801]},{"y":5,"Data":[17,12,3459327807354566655,504350373133157120,-8999501867843488,4094]}]},{"Text":"n","Patterns":[{"y":6,"Data":[12,13,27025445987811327,-8999502270644218,268337147]},{"y":7,"Data":[8,8,-72337965189759223]}]},{"Text":"o","Patterns":[{"y":6,"Data":[12,13,-4594230461768678404,-1117240732616697,33300473]},{"y":4,"Data":[9,9,7057263864975326460,31871]},{"y":5,"Data":[11,12,4324406131666445308,-558472749044071488,1]}]},{"Text":"p","Patterns":[{"y":6,"Data":[12,17,6926536226895822847,254172743642234928,-4602687477891856626,31]},{"y":5,"Data":[11,16,433330726646054910,506107431554845699,412383709182]},{"y":7,"Data":[8,11,2417326350311358463,229884]}]},{"Text":"q","Patterns":[{"y":6,"Data":[12,17,-2290013906707675140,110057555566379120,-32766194,4095]}]},{"Text":"r","Patterns":[{"y":6,"Data":[6,13,31533443661692927,6]},{"y":4,"Data":[5,9,69122916351]},{"y":4,"Data":[4,9,403439615]}]},{"Text":"s","Patterns":[{"y":6,"Data":[10,13,-3585302962172334978,-508933149943072313,1]},{"y":5,"Data":[10,12,4351539911567073304,16932358779069382]}]},{"Text":"t","Patterns":[{"y":4,"Data":[6,15,-3602422308280483841,58746624]},{"y":3,"Data":[5,14,918791497648693247,48]}]},{"Text":"u","Patterns":[{"y":6,"Data":[12,13,-4607744819031186433,-7317937027270655,268435455]},{"y":5,"Data":[10,12,864902294825596927,72057591889789024]}]},{"Text":"v","Patterns":[{"y":6,"Data":[13,13,-143554428622610429,2297954004820311553,268664956]}]},{"Text":"w","Patterns":[{"y":6,"Data":[19,13,-1148422234373103613,135177291909578241,-9205919497360375556,4414723063783]}]},{"Text":"x","Patterns":[{"y":6,"Data":[13,13,9207485709806497793,-4472182045208214544,1099981451295]}]},{"Text":"y","Patterns":[{"y":6,"Data":[13,17,2297963900303179779,-2296976410543129076,4035361614088894479,4096]},{"y":5,"Data":[12,16,-2018526881273413629,283761412197613536,281505045610748]}]},{"Text":"z","Patterns":[{"y":6,"Data":[10,13,-2431976792454562813,-9152422883697427993,3]}]},{"Text":"{","Patterns":[{"y":1,"Data":[7,22,1150669737005423616,1125779647750136,30]}]},{"Text":"|","Patterns":[{"y":1,"Data":[3,22,-1,3]}]},{"Text":"}","Patterns":[{"y":1,"Data":[7,22,-126105187583524863,1116901503563456511,114688]}]},{"Text":"~","Patterns":[{"y":11,"Data":[9,3,131856091]}]},{"Text":"♂","Patterns":[{"y":0,"Data":[27,23,-1123701151957248,284835151957982979,1143914579693173728,-576458621999386624,30786333442048,2111062576988190,142989305080447968,-4499238087823872,-8070451356881715709,133156700131]}]},{"Text":"♀","Patterns":[{"y":0,"Data":[29,23,1152851170214019580,-2303573626071285792,2216615573716999,1292533238815785952,-144106409162115072,-4611405093173002237,5048957996630143,8866462806575228,-9151350718244714528,144080072419065855,8128]}]}],"TrainingSettings":{"IsTrainingEnabled":false,"SkipName":false,"SkipTribe":false,"SkipOwner":false}},"LabelRectangles":{"default":["1294, 679, 195, 18","1294, 736, 195, 18","1294, 793, 195, 18","1294, 851, 195, 18","1294, 908, 195, 18","1375, 965, 114, 18","1375, 1023, 114, 18","1294, 1080, 195, 18","1294, 1137, 195, 18","1166, 265, 231, 20","1125, 218, 308, 23","1179, 311, 216, 18","1212, 357, 150, 18"]},"SelectedLabelSetName":"default"}
\ No newline at end of file
diff --git a/ARKBreedingStats/json/values/_manifest.json b/ARKBreedingStats/json/values/_manifest.json
index 693318b24..21f4bd4b9 100644
--- a/ARKBreedingStats/json/values/_manifest.json
+++ b/ARKBreedingStats/json/values/_manifest.json
@@ -67,7 +67,7 @@
"mod": { "id": "1356703358", "tag": "Primal_Fear_Noxious_Creatures", "title": "Primal Fear Noxious Creatures" }
},
"1373744537-AC2.json": {
- "version": "358.17.1700355462",
+ "version": "358.17.1705110964",
"mod": { "id": "1373744537", "tag": "AC2", "title": "Additional Creatures 2: Wild Ark" }
},
"1379111008-RealismPlus.json": {
@@ -242,7 +242,7 @@
"mod": { "id": "1934081600", "tag": "SoloFarmAnky", "title": "Solo Farm Mod" }
},
"1979037318-IceWyverns.json": {
- "version": "358.17.1696373342",
+ "version": "358.17.1705110815",
"mod": { "id": "1979037318", "tag": "IceWyverns", "title": "Shads Critter Reworks" }
},
"1984129536-MTSMod.json": {
@@ -258,7 +258,7 @@
"mod": { "id": "2000326197", "tag": "ExtraResources", "title": "Event Assets" }
},
"2003934830-Beasts.json": {
- "version": "358.17.1699137788",
+ "version": "358.17.1705183647",
"mod": { "id": "2003934830", "tag": "Beasts", "title": "Prehistoric Beasts" }
},
"2019846325-ApexMod.json": {
@@ -310,7 +310,7 @@
"mod": { "id": "2362246280", "tag": "GigaFullTame", "title": "Giga Full Tame" }
},
"2447186973-ArkOmega.json": {
- "version": "358.17.1701673974",
+ "version": "358.17.1705727328",
"mod": { "id": "2447186973", "tag": "ArkOmega", "title": "Ark Omega" }
},
"2453342929-MoreDragonsMod.json": {
diff --git a/ARKBreedingStats/library/Creature.cs b/ARKBreedingStats/library/Creature.cs
index 070070897..b06215bbe 100644
--- a/ARKBreedingStats/library/Creature.cs
+++ b/ARKBreedingStats/library/Creature.cs
@@ -42,15 +42,43 @@ public class Creature : IEquatable
public double[] valuesBreeding;
public double[] valuesDom;
+
///
- /// Indices of stats that are top for that species in the creatureCollection
+ /// Set a stat index to a top stat or not for that species in the creatureCollection.
///
- public bool[] topBreedingStats;
- public short topStatsCount;
+ public void SetTopStat(int statIndex, bool isTopStat) =>
+ _topBreedingStatIndices = (isTopStat ? _topBreedingStatIndices | (1 << statIndex) : _topBreedingStatIndices & ~(1 << statIndex));
+
///
- /// topStatCount with all stats (regardless of considerStatHighlight[]) and without torpor (for breedingPlanner)
+ /// Returns if a stat index is a top stat for that species in the creatureCollection.
///
- public short topStatsCountBP;
+ public bool IsTopStat(int statIndex) => (_topBreedingStatIndices & (1 << statIndex)) != 0;
+
+ public void ResetTopStats() => _topBreedingStatIndices = 0;
+ private int _topBreedingStatIndices; // bit flags if a stat index is a top stat
+
+ ///
+ /// Number of top stats that are considered in the library.
+ ///
+ public byte topStatsConsideredCount;
+
+ ///
+ /// Set a stat index to a top mutation stat or not for that species in the creatureCollection.
+ ///
+ public void SetTopMutationStat(int statIndex, bool isTopMutationStat) =>
+ _topMutationStatIndices = (isTopMutationStat ? _topMutationStatIndices | (1 << statIndex) : _topMutationStatIndices & ~(1 << statIndex));
+
+ ///
+ /// Returns if a stat index is a top mutation stat for that species in the creatureCollection.
+ ///
+ public bool IsTopMutationStat(int statIndex) => (_topMutationStatIndices & (1 << statIndex)) != 0;
+ public void ResetTopMutationStats() => _topMutationStatIndices = 0;
+ private int _topMutationStatIndices; // bit flags if a stat index is a top mutation stat
+
+ ///
+ /// topStatCount with all stats (regardless of considerStatHighlight[]) and without torpor (for breeding planner)
+ ///
+ public byte topStatsCountBP;
///
/// True if it has some topBreedingStats and if it's male, no other male has more topBreedingStats.
///
@@ -391,6 +419,7 @@ public Creature Mother
motherGuid = mother?.guid ?? Guid.Empty;
}
}
+
public Creature Father
{
get => father;
@@ -412,13 +441,11 @@ public void SetTopStatCount(bool[] considerStatHighlight, bool considerWastedSta
|| flags.HasFlag(CreatureFlags.Placeholder))
return;
- if (topBreedingStats == null) topBreedingStats = new bool[Stats.StatsCount];
-
- short c = 0, cBP = 0;
+ byte c = 0, cBP = 0;
onlyTopConsideredStats = true;
for (int s = 0; s < Stats.StatsCount; s++)
{
- if (topBreedingStats[s])
+ if (IsTopStat(s))
{
if (s != Stats.Torpidity)
cBP++;
@@ -430,7 +457,7 @@ public void SetTopStatCount(bool[] considerStatHighlight, bool considerWastedSta
onlyTopConsideredStats = false;
}
}
- topStatsCount = c;
+ topStatsConsideredCount = c;
topStatsCountBP = cBP;
}
@@ -558,7 +585,6 @@ private void InitializeArrays()
if (levelsDom == null) levelsDom = new int[Stats.StatsCount];
if (valuesBreeding == null) valuesBreeding = new double[Stats.StatsCount];
if (valuesDom == null) valuesDom = new double[Stats.StatsCount];
- if (topBreedingStats == null) topBreedingStats = new bool[Stats.StatsCount];
}
///
diff --git a/ARKBreedingStats/library/CreatureCollection.cs b/ARKBreedingStats/library/CreatureCollection.cs
index f7ef4908d..4ec8be9b5 100644
--- a/ARKBreedingStats/library/CreatureCollection.cs
+++ b/ARKBreedingStats/library/CreatureCollection.cs
@@ -620,6 +620,7 @@ public string Game
switch (value)
{
case Ark.Asa:
+ Ark.SetUndefinedColorId(true);
if (modIDs == null) modIDs = new List();
if (!modIDs.Contains(Ark.Asa))
{
@@ -629,6 +630,7 @@ public string Game
break;
default:
// non ASA
+ Ark.SetUndefinedColorId(false);
if (modIDs == null) return;
ModList.RemoveAll(m => m.id == Ark.Asa);
if (modIDs.Remove(Ark.Asa))
diff --git a/ARKBreedingStats/library/CreatureInfoGraphic.cs b/ARKBreedingStats/library/CreatureInfoGraphic.cs
index 8766a3b2b..25aa16e7e 100644
--- a/ARKBreedingStats/library/CreatureInfoGraphic.cs
+++ b/ARKBreedingStats/library/CreatureInfoGraphic.cs
@@ -126,7 +126,7 @@ public static Bitmap InfoGraphic(this Creature creature, CreatureCollection cc,
// levels
double meanLetterWidth = fontSize * 7d / 10;
int xStatName = (int)meanLetterWidth;
- var displayMutatedLevels = creature.levelsMutated != null;
+ var displayMutatedLevels = creature.levelsMutated != null && cc?.Game == Ark.Asa;
// x position of level number. torpor is the largest level number.
int xRightLevelValue = (int)(xStatName + ((displayWithDomLevels ? 6 : 5) + creature.levelsWild[Stats.Torpidity].ToString().Length) * meanLetterWidth);
int xRightLevelMutValue = xRightLevelValue + (!displayMutatedLevels ? 0 : (int)((creature.levelsMutated.Max().ToString().Length + 3) * meanLetterWidth));
@@ -342,7 +342,7 @@ private static int MaxCharLength(double[] values)
///
///
/// CreatureCollection for server settings.
- public static void ExportInfoGraphicToClipboard(this Creature creature, CreatureCollection cc = null)
+ public static void ExportInfoGraphicToClipboard(this Creature creature, CreatureCollection cc)
{
if (creature == null) return;
diff --git a/ARKBreedingStats/library/DummyCreatures.cs b/ARKBreedingStats/library/DummyCreatures.cs
index 52d7323cd..ecae6f389 100644
--- a/ARKBreedingStats/library/DummyCreatures.cs
+++ b/ARKBreedingStats/library/DummyCreatures.cs
@@ -244,7 +244,7 @@ private static List BreedCreatures(Creature[] creatures, Species speci
var allCreaturesArray = noGender ? allCreatures.ToArray() : null;
var pairs = BreedingScore.CalculateBreedingScores(noGender ? allCreaturesArray : femalesMales[Sex.Female].ToArray(),
noGender ? allCreaturesArray : femalesMales[Sex.Male].ToArray(), species, bestPossibleLevels, statWeights, bestLevels,
- BreedingPlan.BreedingMode.TopStatsConservative, false, false, 0, ref filteredOutByMutationLimit);
+ BreedingScore.BreedingMode.TopStatsConservative, false, false, 0, ref filteredOutByMutationLimit);
var pairsCount = Math.Min(usePairsPerGeneration, pairs.Count);
for (int i = 0; i < pairsCount; i++)
diff --git a/ARKBreedingStats/library/LevelStatusFlags.cs b/ARKBreedingStats/library/LevelStatusFlags.cs
new file mode 100644
index 000000000..72b45e315
--- /dev/null
+++ b/ARKBreedingStats/library/LevelStatusFlags.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ARKBreedingStats.species;
+using ARKBreedingStats.uiControls;
+
+namespace ARKBreedingStats.library
+{
+ ///
+ /// Level status flags of the current extracted or to be added creature.
+ /// E.g. if a level is a new top stat or has a new mutations.
+ ///
+ public static class LevelStatusFlags
+ {
+ ///
+ /// The level status of the currently to be added creature.
+ ///
+ public static readonly LevelStatus[] LevelStatusFlagsCurrentNewCreature = new LevelStatus[Stats.StatsCount];
+ public static LevelStatus CombinedLevelStatusFlags;
+
+ ///
+ /// Determines if the wild and mutated levels of a creature are equal or higher than the current top levels of that species.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Adds text for each stat
+ public static void DetermineLevelStatus(Species species, int[] highSpeciesLevels, int[] lowSpeciesLevels, int[] highSpeciesMutationLevels,
+ (double[], byte[]) statWeights, int[] levelsWild, int[] levelsMutated, double[] valuesBreeding,
+ out List topStatsText, out List newTopStatsText, StringBuilder sbStatInfoText = null)
+ {
+ // if there are no creatures of the species yet, assume 0 levels to be the current best and worst
+ if (highSpeciesLevels == null) highSpeciesLevels = new int[Stats.StatsCount];
+ if (lowSpeciesLevels == null) lowSpeciesLevels = new int[Stats.StatsCount];
+ if (highSpeciesMutationLevels == null) highSpeciesMutationLevels = new int[Stats.StatsCount];
+
+ newTopStatsText = new List();
+ topStatsText = new List();
+
+ foreach (var s in Stats.DisplayOrder)
+ {
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.Neutral;
+
+ if (s == Stats.Torpidity
+ || levelsWild[s] < 0
+ || !species.UsesStat(s))
+ continue;
+
+ var statName = Utils.StatName(s, false, species.statNames);
+ var statNameAbb = Utils.StatName(s, true, species.statNames);
+ var weighting = statWeights.Item1 == null || statWeights.Item1[s] == 0
+ ? StatWeighting.StatValuePreference.Indifferent
+ : statWeights.Item1[s] > 0 ? StatWeighting.StatValuePreference.High
+ : StatWeighting.StatValuePreference.Low;
+
+ sbStatInfoText?.Append($"{statNameAbb}: {levelsWild[s]} | {levelsMutated[s]} ({valuesBreeding[s]})");
+
+ if (weighting == StatWeighting.StatValuePreference.High)
+ {
+ // higher stats are considered to be good. If no custom weightings are available, consider higher levels to be better.
+
+ // check if higher level is only considered if even or odd
+ if ((statWeights.Item2?[s] ?? 0) == 0 // even/odd doesn't matter
+ || (statWeights.Item2[s] == 1 && levelsWild[s] % 2 == 1)
+ || (statWeights.Item2[s] == 2 && levelsWild[s] % 2 == 0)
+ )
+ {
+ if (levelsWild[s] == highSpeciesLevels[s])
+ {
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.TopLevel;
+ CombinedLevelStatusFlags |= LevelStatus.TopLevel;
+ topStatsText.Add(statName);
+ sbStatInfoText?.Append($" {Loc.S("topLevel")}");
+ }
+ else if (highSpeciesLevels[s] != -1 && levelsWild[s] > highSpeciesLevels[s])
+ {
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.NewTopLevel;
+ CombinedLevelStatusFlags |= LevelStatus.NewTopLevel;
+ newTopStatsText.Add(statName);
+ sbStatInfoText?.Append($" {Loc.S("newTopLevel")}");
+ }
+ }
+ }
+ else if (weighting == StatWeighting.StatValuePreference.Low)
+ {
+ // lower stats are considered to be good
+ if (levelsWild[s] == lowSpeciesLevels[s])
+ {
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.TopLevel;
+ CombinedLevelStatusFlags |= LevelStatus.TopLevel;
+ topStatsText.Add(statName);
+ sbStatInfoText?.Append($" {Loc.S("topLevel")}");
+ }
+ else if (levelsWild[s] < lowSpeciesLevels[s])
+ {
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.NewTopLevel;
+ CombinedLevelStatusFlags |= LevelStatus.NewTopLevel;
+ newTopStatsText.Add(statName);
+ sbStatInfoText?.Append($" {Loc.S("newTopLevel")}");
+ }
+ }
+
+ if (weighting == StatWeighting.StatValuePreference.High
+ && levelsMutated[s] > highSpeciesMutationLevels[s])
+ {
+ LevelStatusFlagsCurrentNewCreature[s] |= LevelStatus.NewMutation;
+ CombinedLevelStatusFlags |= LevelStatus.NewMutation;
+ sbStatInfoText?.Append($" {Loc.S("new mutation")}");
+ }
+ sbStatInfoText?.AppendLine();
+ }
+ }
+
+ public static void Clear()
+ {
+ for (var s = 0; s < Stats.StatsCount; s++)
+ LevelStatusFlagsCurrentNewCreature[s] = LevelStatus.Neutral;
+ CombinedLevelStatusFlags = LevelStatus.Neutral;
+ }
+
+ ///
+ /// Status of wild levels, e.g. top level, max level.
+ ///
+ [Flags]
+ public enum LevelStatus
+ {
+ Neutral = 0,
+ ///
+ /// wild level is equal to the current top-level
+ ///
+ TopLevel = 1,
+ ///
+ /// wild level is higher than the current top-level
+ ///
+ NewTopLevel = 2,
+ ///
+ /// Max level to apply domesticated levels.
+ ///
+ MaxLevelForLevelUp = 4,
+ ///
+ /// Max level that can be saved.
+ ///
+ MaxLevel = 8,
+ ///
+ /// Level too high to be saved, rollover will happen.
+ ///
+ UltraMaxLevel = 16,
+ ///
+ /// Stat has new mutation.
+ ///
+ NewMutation = 32
+ }
+ }
+}
diff --git a/ARKBreedingStats/local/strings.de.resx b/ARKBreedingStats/local/strings.de.resx
index 9e65eabfc..86fb44e33 100644
--- a/ARKBreedingStats/local/strings.de.resx
+++ b/ARKBreedingStats/local/strings.de.resx
@@ -1331,4 +1331,10 @@ Es ist auch möglich Tiere mit einer Farbe in mehreren möglichen Regionen zu fi
Klicken um in die Zwischenablage zu kopieren
+
+ Aktualisiert
+
+
+ Dieser Ton wird abgespielt, wenn eine Kreatur aktualisiert wird, d.h. erneut importiert wird
+
\ No newline at end of file
diff --git a/ARKBreedingStats/local/strings.resx b/ARKBreedingStats/local/strings.resx
index e32916878..ea5a75c37 100644
--- a/ARKBreedingStats/local/strings.resx
+++ b/ARKBreedingStats/local/strings.resx
@@ -1343,4 +1343,10 @@ It's also possible to filter for creatures with a color in one of multiple possi
Click to copy to clipboard
+
+ Updated
+
+
+ This sound is played if a creature is updated, i.e. imported again
+
\ No newline at end of file
diff --git a/ARKBreedingStats/ocr/OCRControl.cs b/ARKBreedingStats/ocr/OCRControl.cs
index fcfff40f2..3136bc763 100644
--- a/ARKBreedingStats/ocr/OCRControl.cs
+++ b/ARKBreedingStats/ocr/OCRControl.cs
@@ -590,7 +590,7 @@ private void btUnloadOCR_Click(object sender, EventArgs e)
private void BtNewOcrConfig_Click(object sender, EventArgs e)
{
var currentOcrConfig = ArkOcr.Ocr.ocrConfig;
- ArkOcr.Ocr.ocrConfig = new OcrTemplate();
+ ArkOcr.Ocr.ocrConfig = new OcrTemplate(true);
if (SaveOcrFileAs()) return;
// user doesn't want to create new config, reset to old one
diff --git a/ARKBreedingStats/ocr/OCRTemplate.cs b/ARKBreedingStats/ocr/OCRTemplate.cs
index 20b73bffc..3da6faf23 100644
--- a/ARKBreedingStats/ocr/OCRTemplate.cs
+++ b/ARKBreedingStats/ocr/OCRTemplate.cs
@@ -40,7 +40,7 @@ public class OcrTemplate
///
/// Coordinates of the rectangles to read. Kept for backwards compatibility, now uses LabelRectangles.
///
- [JsonProperty]
+ [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public Rectangle[] labelRectangles;
///
@@ -61,10 +61,11 @@ public class OcrTemplate
public List> reducedIndices = new List>(); // indices of letters for reduced set (only [0-9\.,/%:])
- public OcrTemplate()
+ public OcrTemplate(bool initialize)
{
Version = new Version(CurrentVersion);
- InitializeOcrTemplate();
+ if (initialize)
+ InitializeOcrTemplate();
}
public void InitializeOcrTemplate()
diff --git a/ARKBreedingStats/settings/Settings.Designer.cs b/ARKBreedingStats/settings/Settings.Designer.cs
index 6f48f8a70..497fdd264 100644
--- a/ARKBreedingStats/settings/Settings.Designer.cs
+++ b/ARKBreedingStats/settings/Settings.Designer.cs
@@ -124,6 +124,10 @@ private void InitializeComponent()
this.checkBoxDisplayHiddenStats = new System.Windows.Forms.CheckBox();
this.tabControlSettings = new System.Windows.Forms.TabControl();
this.tabPageMultipliers = new System.Windows.Forms.TabPage();
+ this.TbRemoteServerSettingsUri = new System.Windows.Forms.TextBox();
+ this.BtSettingsToClipboard = new System.Windows.Forms.Button();
+ this.btExportMultipliers = new System.Windows.Forms.Button();
+ this.BtRemoteServerSettingsUri = new System.Windows.Forms.Button();
this.CbKeepMultipliersForNewLibrary = new System.Windows.Forms.CheckBox();
this.BtAutoImportLocalSettings = new System.Windows.Forms.Button();
this.panel3 = new System.Windows.Forms.Panel();
@@ -131,12 +135,10 @@ private void InitializeComponent()
this.RbGameAse = new System.Windows.Forms.RadioButton();
this.BtImportSettingsSelectFile = new System.Windows.Forms.Button();
this.CbAtlasSettings = new System.Windows.Forms.CheckBox();
- this.BtSettingsToClipboard = new System.Windows.Forms.Button();
this.groupBox29 = new System.Windows.Forms.GroupBox();
this.CbAllowSpeedLeveling = new System.Windows.Forms.CheckBox();
this.CbAllowFlyerSpeedLeveling = new System.Windows.Forms.CheckBox();
this.label34 = new System.Windows.Forms.Label();
- this.btExportMultipliers = new System.Windows.Forms.Button();
this.groupBox18 = new System.Windows.Forms.GroupBox();
this.btApplyPreset = new System.Windows.Forms.Button();
this.cbbStatMultiplierPresets = new System.Windows.Forms.ComboBox();
@@ -162,6 +164,7 @@ private void InitializeComponent()
this.GbImgCacheLocalAppData = new System.Windows.Forms.GroupBox();
this.CbImgCacheUseLocalAppData = new System.Windows.Forms.CheckBox();
this.groupBox16 = new System.Windows.Forms.GroupBox();
+ this.CbStreamerMode = new System.Windows.Forms.CheckBox();
this.cbDevTools = new System.Windows.Forms.CheckBox();
this.GbSpecies = new System.Windows.Forms.GroupBox();
this.LbSpeciesSelectorCountLastUsed = new System.Windows.Forms.Label();
@@ -214,14 +217,14 @@ private void InitializeComponent()
this.CbInfoGraphicDisplayMaxWildLevel = new System.Windows.Forms.CheckBox();
this.label50 = new System.Windows.Forms.Label();
this.tabPageImportSavegame = new System.Windows.Forms.TabPage();
- this.groupBox12 = new System.Windows.Forms.GroupBox();
this.label68 = new System.Windows.Forms.Label();
this.CbImportUnclaimedBabies = new System.Windows.Forms.CheckBox();
this.cbSaveImportCryo = new System.Windows.Forms.CheckBox();
+ this.label24 = new System.Windows.Forms.Label();
this.cbIgnoreUnknownBPOnSaveImport = new System.Windows.Forms.CheckBox();
+ this.groupBox14 = new System.Windows.Forms.GroupBox();
+ this.fileSelectorExtractedSaveFolder = new ARKBreedingStats.uiControls.FileSelector();
this.textBoxImportTribeNameFilter = new System.Windows.Forms.TextBox();
- this.label_Filter = new System.Windows.Forms.Label();
- this.cbImportUpdateCreatureStatus = new System.Windows.Forms.CheckBox();
this.groupBox15 = new System.Windows.Forms.GroupBox();
this.dataGridView_FileLocations = new System.Windows.Forms.DataGridView();
this.convenientNameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
@@ -233,9 +236,8 @@ private void InitializeComponent()
this.aTImportFileLocationBindingSource = new System.Windows.Forms.BindingSource(this.components);
this.btAddSavegameFileLocation = new System.Windows.Forms.Button();
this.labelSavegameFileLocationHint = new System.Windows.Forms.Label();
- this.groupBox14 = new System.Windows.Forms.GroupBox();
- this.fileSelectorExtractedSaveFolder = new ARKBreedingStats.uiControls.FileSelector();
- this.label24 = new System.Windows.Forms.Label();
+ this.label_Filter = new System.Windows.Forms.Label();
+ this.cbImportUpdateCreatureStatus = new System.Windows.Forms.CheckBox();
this.tabPageImportExported = new System.Windows.Forms.TabPage();
this.BtGetExportFolderAutomatically = new System.Windows.Forms.Button();
this.groupBox27 = new System.Windows.Forms.GroupBox();
@@ -254,6 +256,7 @@ private void InitializeComponent()
this.CbExportFileRenameAfterImport = new System.Windows.Forms.CheckBox();
this.BtImportArchiveFolder = new System.Windows.Forms.Button();
this.panel2 = new System.Windows.Forms.Panel();
+ this.BtBeepUpdated = new System.Windows.Forms.Button();
this.BtBeepNewTop = new System.Windows.Forms.Button();
this.BtBeepTop = new System.Windows.Forms.Button();
this.BtBeepSuccess = new System.Windows.Forms.Button();
@@ -351,8 +354,7 @@ private void InitializeComponent()
this.label1 = new System.Windows.Forms.Label();
this.panel1 = new System.Windows.Forms.Panel();
this.colorDialog1 = new System.Windows.Forms.ColorDialog();
- this.BtRemoteServerSettingsUri = new System.Windows.Forms.Button();
- this.TbRemoteServerSettingsUri = new System.Windows.Forms.TextBox();
+ this.CbLibraryDisplayZeroMutationLevels = new System.Windows.Forms.CheckBox();
this.groupBoxMultiplier.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudTamedDinoCharacterFoodDrain)).BeginInit();
@@ -422,11 +424,10 @@ private void InitializeComponent()
((System.ComponentModel.ISupportInitialize)(this.nudInfoGraphicHeight)).BeginInit();
this.groupBox28.SuspendLayout();
this.tabPageImportSavegame.SuspendLayout();
- this.groupBox12.SuspendLayout();
+ this.groupBox14.SuspendLayout();
this.groupBox15.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView_FileLocations)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.aTImportFileLocationBindingSource)).BeginInit();
- this.groupBox14.SuspendLayout();
this.tabPageImportExported.SuspendLayout();
this.groupBox27.SuspendLayout();
this.groupBox23.SuspendLayout();
@@ -1900,6 +1901,43 @@ private void InitializeComponent()
this.tabPageMultipliers.DragDrop += new System.Windows.Forms.DragEventHandler(this.tabPage2_DragDrop);
this.tabPageMultipliers.DragEnter += new System.Windows.Forms.DragEventHandler(this.tabPage2_DragEnter);
//
+ // TbRemoteServerSettingsUri
+ //
+ this.TbRemoteServerSettingsUri.Location = new System.Drawing.Point(407, 659);
+ this.TbRemoteServerSettingsUri.Name = "TbRemoteServerSettingsUri";
+ this.TbRemoteServerSettingsUri.Size = new System.Drawing.Size(152, 20);
+ this.TbRemoteServerSettingsUri.TabIndex = 20;
+ //
+ // BtSettingsToClipboard
+ //
+ this.BtSettingsToClipboard.Location = new System.Drawing.Point(600, 713);
+ this.BtSettingsToClipboard.Name = "BtSettingsToClipboard";
+ this.BtSettingsToClipboard.Size = new System.Drawing.Size(142, 23);
+ this.BtSettingsToClipboard.TabIndex = 13;
+ this.BtSettingsToClipboard.Text = "Copy settings to clipboard";
+ this.BtSettingsToClipboard.UseVisualStyleBackColor = true;
+ this.BtSettingsToClipboard.Click += new System.EventHandler(this.BtSettingsToClipboard_Click);
+ //
+ // btExportMultipliers
+ //
+ this.btExportMultipliers.Location = new System.Drawing.Point(407, 713);
+ this.btExportMultipliers.Name = "btExportMultipliers";
+ this.btExportMultipliers.Size = new System.Drawing.Size(187, 23);
+ this.btExportMultipliers.TabIndex = 11;
+ this.btExportMultipliers.Text = "Export multiplier settings to file…";
+ this.btExportMultipliers.UseVisualStyleBackColor = true;
+ this.btExportMultipliers.Click += new System.EventHandler(this.btExportMultipliers_Click);
+ //
+ // BtRemoteServerSettingsUri
+ //
+ this.BtRemoteServerSettingsUri.Location = new System.Drawing.Point(565, 657);
+ this.BtRemoteServerSettingsUri.Name = "BtRemoteServerSettingsUri";
+ this.BtRemoteServerSettingsUri.Size = new System.Drawing.Size(167, 23);
+ this.BtRemoteServerSettingsUri.TabIndex = 19;
+ this.BtRemoteServerSettingsUri.Text = "Import remote settings";
+ this.BtRemoteServerSettingsUri.UseVisualStyleBackColor = true;
+ this.BtRemoteServerSettingsUri.Click += new System.EventHandler(this.BtRemoteServerSettingsUri_Click);
+ //
// CbKeepMultipliersForNewLibrary
//
this.CbKeepMultipliersForNewLibrary.AutoSize = true;
@@ -1940,6 +1978,7 @@ private void InitializeComponent()
this.RbGameAsa.TabStop = true;
this.RbGameAsa.Text = "ASA";
this.RbGameAsa.UseVisualStyleBackColor = true;
+ this.RbGameAsa.CheckedChanged += new System.EventHandler(this.RbGameAsa_CheckedChanged);
//
// RbGameAse
//
@@ -1973,16 +2012,6 @@ private void InitializeComponent()
this.CbAtlasSettings.Text = "ATLAS settings";
this.CbAtlasSettings.UseVisualStyleBackColor = true;
//
- // BtSettingsToClipboard
- //
- this.BtSettingsToClipboard.Location = new System.Drawing.Point(600, 713);
- this.BtSettingsToClipboard.Name = "BtSettingsToClipboard";
- this.BtSettingsToClipboard.Size = new System.Drawing.Size(142, 23);
- this.BtSettingsToClipboard.TabIndex = 13;
- this.BtSettingsToClipboard.Text = "Copy settings to clipboard";
- this.BtSettingsToClipboard.UseVisualStyleBackColor = true;
- this.BtSettingsToClipboard.Click += new System.EventHandler(this.BtSettingsToClipboard_Click);
- //
// groupBox29
//
this.groupBox29.Controls.Add(this.CbAllowSpeedLeveling);
@@ -2023,16 +2052,6 @@ private void InitializeComponent()
this.label34.TabIndex = 10;
this.label34.Text = "You can export the settings on this page to a file or the clipboard to share it w" +
"ith tribe members or for bug reports.";
- //
- // btExportMultipliers
- //
- this.btExportMultipliers.Location = new System.Drawing.Point(407, 713);
- this.btExportMultipliers.Name = "btExportMultipliers";
- this.btExportMultipliers.Size = new System.Drawing.Size(187, 23);
- this.btExportMultipliers.TabIndex = 11;
- this.btExportMultipliers.Text = "Export multiplier settings to file…";
- this.btExportMultipliers.UseVisualStyleBackColor = true;
- this.btExportMultipliers.Click += new System.EventHandler(this.btExportMultipliers_Click);
//
// groupBox18
//
@@ -2192,7 +2211,7 @@ private void InitializeComponent()
// CbAskSaveSettingsOnClose
//
this.CbAskSaveSettingsOnClose.AutoSize = true;
- this.CbAskSaveSettingsOnClose.Location = new System.Drawing.Point(329, 699);
+ this.CbAskSaveSettingsOnClose.Location = new System.Drawing.Point(435, 721);
this.CbAskSaveSettingsOnClose.Name = "CbAskSaveSettingsOnClose";
this.CbAskSaveSettingsOnClose.Size = new System.Drawing.Size(309, 17);
this.CbAskSaveSettingsOnClose.TabIndex = 15;
@@ -2204,7 +2223,7 @@ private void InitializeComponent()
this.groupBox31.Controls.Add(this.CbColorIdOnColorRegionButton);
this.groupBox31.Controls.Add(this.CbAlwaysShowAllColorRegions);
this.groupBox31.Controls.Add(this.CbHideInvisibleColorRegions);
- this.groupBox31.Location = new System.Drawing.Point(329, 283);
+ this.groupBox31.Location = new System.Drawing.Point(329, 319);
this.groupBox31.Name = "groupBox31";
this.groupBox31.Size = new System.Drawing.Size(413, 66);
this.groupBox31.TabIndex = 14;
@@ -2247,9 +2266,9 @@ private void InitializeComponent()
this.groupBox30.Controls.Add(this.BExportSpreadsheetMoveDown);
this.groupBox30.Controls.Add(this.BExportSpreadsheetMoveUp);
this.groupBox30.Controls.Add(this.ClbExportSpreadsheetFields);
- this.groupBox30.Location = new System.Drawing.Point(329, 355);
+ this.groupBox30.Location = new System.Drawing.Point(329, 391);
this.groupBox30.Name = "groupBox30";
- this.groupBox30.Size = new System.Drawing.Size(413, 281);
+ this.groupBox30.Size = new System.Drawing.Size(413, 268);
this.groupBox30.TabIndex = 13;
this.groupBox30.TabStop = false;
this.groupBox30.Text = "Info to export for spreadsheet";
@@ -2288,9 +2307,9 @@ private void InitializeComponent()
// ClbExportSpreadsheetFields
//
this.ClbExportSpreadsheetFields.FormattingEnabled = true;
- this.ClbExportSpreadsheetFields.Location = new System.Drawing.Point(36, 41);
+ this.ClbExportSpreadsheetFields.Location = new System.Drawing.Point(36, 42);
this.ClbExportSpreadsheetFields.Name = "ClbExportSpreadsheetFields";
- this.ClbExportSpreadsheetFields.Size = new System.Drawing.Size(371, 229);
+ this.ClbExportSpreadsheetFields.Size = new System.Drawing.Size(371, 214);
this.ClbExportSpreadsheetFields.TabIndex = 12;
//
// GbImgCacheLocalAppData
@@ -2315,18 +2334,27 @@ private void InitializeComponent()
//
// groupBox16
//
+ this.groupBox16.Controls.Add(this.CbStreamerMode);
this.groupBox16.Controls.Add(this.cbDevTools);
this.groupBox16.Location = new System.Drawing.Point(329, 234);
this.groupBox16.Name = "groupBox16";
- this.groupBox16.Size = new System.Drawing.Size(413, 43);
+ this.groupBox16.Size = new System.Drawing.Size(413, 79);
this.groupBox16.TabIndex = 10;
this.groupBox16.TabStop = false;
- this.groupBox16.Text = "Dev-Tools";
+ this.groupBox16.Text = "Application";
+ //
+ // CbStreamerMode
+ //
+ this.CbStreamerMode.Location = new System.Drawing.Point(6, 19);
+ this.CbStreamerMode.Name = "CbStreamerMode";
+ this.CbStreamerMode.Size = new System.Drawing.Size(407, 24);
+ this.CbStreamerMode.TabIndex = 1;
+ this.CbStreamerMode.Text = "Streamer mode (hide confidential info, e.g. ASB server tag)";
+ this.CbStreamerMode.UseVisualStyleBackColor = true;
//
// cbDevTools
//
- this.cbDevTools.Dock = System.Windows.Forms.DockStyle.Fill;
- this.cbDevTools.Location = new System.Drawing.Point(3, 16);
+ this.cbDevTools.Location = new System.Drawing.Point(6, 44);
this.cbDevTools.Name = "cbDevTools";
this.cbDevTools.Size = new System.Drawing.Size(407, 24);
this.cbDevTools.TabIndex = 0;
@@ -2486,7 +2514,7 @@ private void InitializeComponent()
this.groupBox17.Controls.Add(this.LbLanguage2);
this.groupBox17.Controls.Add(this.CbbLanguage2);
this.groupBox17.Controls.Add(this.CbbLanguage);
- this.groupBox17.Location = new System.Drawing.Point(329, 642);
+ this.groupBox17.Location = new System.Drawing.Point(329, 665);
this.groupBox17.Name = "groupBox17";
this.groupBox17.Size = new System.Drawing.Size(413, 51);
this.groupBox17.TabIndex = 5;
@@ -2522,6 +2550,7 @@ private void InitializeComponent()
//
// groupBox9
//
+ this.groupBox9.Controls.Add(this.CbLibraryDisplayZeroMutationLevels);
this.groupBox9.Controls.Add(this.CbDisplayLibraryCreatureIndex);
this.groupBox9.Controls.Add(this.CbNaturalSortIgnoreSpaces);
this.groupBox9.Controls.Add(this.CbNaturalSorting);
@@ -2533,7 +2562,7 @@ private void InitializeComponent()
this.groupBox9.Controls.Add(this.cbCreatureColorsLibrary);
this.groupBox9.Location = new System.Drawing.Point(6, 509);
this.groupBox9.Name = "groupBox9";
- this.groupBox9.Size = new System.Drawing.Size(317, 207);
+ this.groupBox9.Size = new System.Drawing.Size(317, 229);
this.groupBox9.TabIndex = 4;
this.groupBox9.TabStop = false;
this.groupBox9.Text = "Library";
@@ -2893,7 +2922,16 @@ private void InitializeComponent()
// tabPageImportSavegame
//
this.tabPageImportSavegame.AutoScroll = true;
- this.tabPageImportSavegame.Controls.Add(this.groupBox12);
+ this.tabPageImportSavegame.Controls.Add(this.label68);
+ this.tabPageImportSavegame.Controls.Add(this.CbImportUnclaimedBabies);
+ this.tabPageImportSavegame.Controls.Add(this.cbSaveImportCryo);
+ this.tabPageImportSavegame.Controls.Add(this.label24);
+ this.tabPageImportSavegame.Controls.Add(this.cbIgnoreUnknownBPOnSaveImport);
+ this.tabPageImportSavegame.Controls.Add(this.groupBox14);
+ this.tabPageImportSavegame.Controls.Add(this.textBoxImportTribeNameFilter);
+ this.tabPageImportSavegame.Controls.Add(this.groupBox15);
+ this.tabPageImportSavegame.Controls.Add(this.label_Filter);
+ this.tabPageImportSavegame.Controls.Add(this.cbImportUpdateCreatureStatus);
this.tabPageImportSavegame.Location = new System.Drawing.Point(4, 22);
this.tabPageImportSavegame.Name = "tabPageImportSavegame";
this.tabPageImportSavegame.Padding = new System.Windows.Forms.Padding(3);
@@ -2902,30 +2940,11 @@ private void InitializeComponent()
this.tabPageImportSavegame.Text = "Import Savegame";
this.tabPageImportSavegame.UseVisualStyleBackColor = true;
//
- // groupBox12
- //
- this.groupBox12.Controls.Add(this.label68);
- this.groupBox12.Controls.Add(this.CbImportUnclaimedBabies);
- this.groupBox12.Controls.Add(this.cbSaveImportCryo);
- this.groupBox12.Controls.Add(this.cbIgnoreUnknownBPOnSaveImport);
- this.groupBox12.Controls.Add(this.textBoxImportTribeNameFilter);
- this.groupBox12.Controls.Add(this.label_Filter);
- this.groupBox12.Controls.Add(this.cbImportUpdateCreatureStatus);
- this.groupBox12.Controls.Add(this.groupBox15);
- this.groupBox12.Controls.Add(this.groupBox14);
- this.groupBox12.Controls.Add(this.label24);
- this.groupBox12.Location = new System.Drawing.Point(3, 3);
- this.groupBox12.Name = "groupBox12";
- this.groupBox12.Size = new System.Drawing.Size(739, 667);
- this.groupBox12.TabIndex = 0;
- this.groupBox12.TabStop = false;
- this.groupBox12.Text = "Import Data from Save-File";
- //
// label68
//
this.label68.AutoSize = true;
this.label68.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label68.Location = new System.Drawing.Point(6, 16);
+ this.label68.Location = new System.Drawing.Point(8, 3);
this.label68.Name = "label68";
this.label68.Size = new System.Drawing.Size(506, 20);
this.label68.TabIndex = 1;
@@ -2934,7 +2953,7 @@ private void InitializeComponent()
// CbImportUnclaimedBabies
//
this.CbImportUnclaimedBabies.AutoSize = true;
- this.CbImportUnclaimedBabies.Location = new System.Drawing.Point(9, 176);
+ this.CbImportUnclaimedBabies.Location = new System.Drawing.Point(11, 163);
this.CbImportUnclaimedBabies.Name = "CbImportUnclaimedBabies";
this.CbImportUnclaimedBabies.Size = new System.Drawing.Size(140, 17);
this.CbImportUnclaimedBabies.TabIndex = 8;
@@ -2944,57 +2963,66 @@ private void InitializeComponent()
// cbSaveImportCryo
//
this.cbSaveImportCryo.AutoSize = true;
- this.cbSaveImportCryo.Location = new System.Drawing.Point(9, 153);
+ this.cbSaveImportCryo.Location = new System.Drawing.Point(11, 140);
this.cbSaveImportCryo.Name = "cbSaveImportCryo";
this.cbSaveImportCryo.Size = new System.Drawing.Size(216, 17);
this.cbSaveImportCryo.TabIndex = 3;
this.cbSaveImportCryo.Text = "Import creatures in cryopods or soultraps";
this.cbSaveImportCryo.UseVisualStyleBackColor = true;
//
+ // label24
+ //
+ this.label24.Location = new System.Drawing.Point(8, 39);
+ this.label24.Name = "label24";
+ this.label24.Size = new System.Drawing.Size(730, 38);
+ this.label24.TabIndex = 0;
+ this.label24.Text = resources.GetString("label24.Text");
+ //
// cbIgnoreUnknownBPOnSaveImport
//
this.cbIgnoreUnknownBPOnSaveImport.AutoSize = true;
- this.cbIgnoreUnknownBPOnSaveImport.Location = new System.Drawing.Point(9, 130);
+ this.cbIgnoreUnknownBPOnSaveImport.Location = new System.Drawing.Point(11, 117);
this.cbIgnoreUnknownBPOnSaveImport.Name = "cbIgnoreUnknownBPOnSaveImport";
this.cbIgnoreUnknownBPOnSaveImport.Size = new System.Drawing.Size(334, 17);
this.cbIgnoreUnknownBPOnSaveImport.TabIndex = 2;
this.cbIgnoreUnknownBPOnSaveImport.Text = "Ignore unknown species on import and don\'t show a messagebox";
this.cbIgnoreUnknownBPOnSaveImport.UseVisualStyleBackColor = true;
//
- // textBoxImportTribeNameFilter
+ // groupBox14
//
- this.textBoxImportTribeNameFilter.Location = new System.Drawing.Point(3, 215);
- this.textBoxImportTribeNameFilter.Name = "textBoxImportTribeNameFilter";
- this.textBoxImportTribeNameFilter.Size = new System.Drawing.Size(730, 20);
- this.textBoxImportTribeNameFilter.TabIndex = 5;
+ this.groupBox14.Controls.Add(this.fileSelectorExtractedSaveFolder);
+ this.groupBox14.Location = new System.Drawing.Point(8, 236);
+ this.groupBox14.Name = "groupBox14";
+ this.groupBox14.Size = new System.Drawing.Size(730, 47);
+ this.groupBox14.TabIndex = 6;
+ this.groupBox14.TabStop = false;
+ this.groupBox14.Text = "Target folder for save-game working copy (user\'s temp dir if empty). It\'s recomme" +
+ "nded to leave this setting empty.";
//
- // label_Filter
+ // fileSelectorExtractedSaveFolder
//
- this.label_Filter.AutoSize = true;
- this.label_Filter.Location = new System.Drawing.Point(3, 199);
- this.label_Filter.Name = "label_Filter";
- this.label_Filter.Size = new System.Drawing.Size(487, 13);
- this.label_Filter.TabIndex = 4;
- this.label_Filter.Text = "Import only tribes with names containing at least one of these comma separated va" +
- "lues, case sensitive";
+ this.fileSelectorExtractedSaveFolder.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.fileSelectorExtractedSaveFolder.Link = "filename";
+ this.fileSelectorExtractedSaveFolder.Location = new System.Drawing.Point(3, 16);
+ this.fileSelectorExtractedSaveFolder.Name = "fileSelectorExtractedSaveFolder";
+ this.fileSelectorExtractedSaveFolder.Size = new System.Drawing.Size(724, 28);
+ this.fileSelectorExtractedSaveFolder.TabIndex = 0;
//
- // cbImportUpdateCreatureStatus
+ // textBoxImportTribeNameFilter
//
- this.cbImportUpdateCreatureStatus.Location = new System.Drawing.Point(9, 87);
- this.cbImportUpdateCreatureStatus.Name = "cbImportUpdateCreatureStatus";
- this.cbImportUpdateCreatureStatus.Size = new System.Drawing.Size(727, 37);
- this.cbImportUpdateCreatureStatus.TabIndex = 1;
- this.cbImportUpdateCreatureStatus.Text = "Update Available/Unavailable Status on Import for disappeared or reappeared creat" +
- "ures (disable this if you will import savegames from multiple servers). This set" +
- "ting is saved per library.";
- this.cbImportUpdateCreatureStatus.UseVisualStyleBackColor = true;
+ this.textBoxImportTribeNameFilter.Location = new System.Drawing.Point(5, 202);
+ this.textBoxImportTribeNameFilter.Name = "textBoxImportTribeNameFilter";
+ this.textBoxImportTribeNameFilter.Size = new System.Drawing.Size(730, 20);
+ this.textBoxImportTribeNameFilter.TabIndex = 5;
//
// groupBox15
//
+ this.groupBox15.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox15.Controls.Add(this.dataGridView_FileLocations);
this.groupBox15.Controls.Add(this.btAddSavegameFileLocation);
this.groupBox15.Controls.Add(this.labelSavegameFileLocationHint);
- this.groupBox15.Location = new System.Drawing.Point(6, 302);
+ this.groupBox15.Location = new System.Drawing.Point(8, 289);
this.groupBox15.Name = "groupBox15";
this.groupBox15.Size = new System.Drawing.Size(730, 386);
this.groupBox15.TabIndex = 7;
@@ -3108,33 +3136,26 @@ private void InitializeComponent()
this.labelSavegameFileLocationHint.Text = "Location example for The Island: ...\\Steam\\steamapps\\common\\ARK\\ShooterGame\\Saved" +
"\\SavedArksLocal\\TheIsland.ark";
//
- // groupBox14
- //
- this.groupBox14.Controls.Add(this.fileSelectorExtractedSaveFolder);
- this.groupBox14.Location = new System.Drawing.Point(6, 249);
- this.groupBox14.Name = "groupBox14";
- this.groupBox14.Size = new System.Drawing.Size(730, 47);
- this.groupBox14.TabIndex = 6;
- this.groupBox14.TabStop = false;
- this.groupBox14.Text = "Target folder for save-game working copy (user\'s temp dir if empty). It\'s recomme" +
- "nded to leave this setting empty.";
- //
- // fileSelectorExtractedSaveFolder
+ // label_Filter
//
- this.fileSelectorExtractedSaveFolder.Dock = System.Windows.Forms.DockStyle.Fill;
- this.fileSelectorExtractedSaveFolder.Link = "filename";
- this.fileSelectorExtractedSaveFolder.Location = new System.Drawing.Point(3, 16);
- this.fileSelectorExtractedSaveFolder.Name = "fileSelectorExtractedSaveFolder";
- this.fileSelectorExtractedSaveFolder.Size = new System.Drawing.Size(724, 28);
- this.fileSelectorExtractedSaveFolder.TabIndex = 0;
+ this.label_Filter.AutoSize = true;
+ this.label_Filter.Location = new System.Drawing.Point(5, 186);
+ this.label_Filter.Name = "label_Filter";
+ this.label_Filter.Size = new System.Drawing.Size(487, 13);
+ this.label_Filter.TabIndex = 4;
+ this.label_Filter.Text = "Import only tribes with names containing at least one of these comma separated va" +
+ "lues, case sensitive";
//
- // label24
+ // cbImportUpdateCreatureStatus
//
- this.label24.Location = new System.Drawing.Point(6, 52);
- this.label24.Name = "label24";
- this.label24.Size = new System.Drawing.Size(730, 38);
- this.label24.TabIndex = 0;
- this.label24.Text = resources.GetString("label24.Text");
+ this.cbImportUpdateCreatureStatus.Location = new System.Drawing.Point(11, 74);
+ this.cbImportUpdateCreatureStatus.Name = "cbImportUpdateCreatureStatus";
+ this.cbImportUpdateCreatureStatus.Size = new System.Drawing.Size(727, 37);
+ this.cbImportUpdateCreatureStatus.TabIndex = 1;
+ this.cbImportUpdateCreatureStatus.Text = "Update Available/Unavailable Status on Import for disappeared or reappeared creat" +
+ "ures (disable this if you will import savegames from multiple servers). This set" +
+ "ting is saved per library.";
+ this.cbImportUpdateCreatureStatus.UseVisualStyleBackColor = true;
//
// tabPageImportExported
//
@@ -3333,6 +3354,7 @@ private void InitializeComponent()
//
// panel2
//
+ this.panel2.Controls.Add(this.BtBeepUpdated);
this.panel2.Controls.Add(this.BtBeepNewTop);
this.panel2.Controls.Add(this.BtBeepTop);
this.panel2.Controls.Add(this.BtBeepSuccess);
@@ -3340,12 +3362,22 @@ private void InitializeComponent()
this.panel2.Controls.Add(this.BtBeepFailure);
this.panel2.Location = new System.Drawing.Point(285, 11);
this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(121, 131);
+ this.panel2.Size = new System.Drawing.Size(121, 148);
this.panel2.TabIndex = 7;
//
+ // BtBeepUpdated
+ //
+ this.BtBeepUpdated.Location = new System.Drawing.Point(3, 122);
+ this.BtBeepUpdated.Name = "BtBeepUpdated";
+ this.BtBeepUpdated.Size = new System.Drawing.Size(115, 23);
+ this.BtBeepUpdated.TabIndex = 5;
+ this.BtBeepUpdated.Text = "updated";
+ this.BtBeepUpdated.UseVisualStyleBackColor = true;
+ this.BtBeepUpdated.Click += new System.EventHandler(this.BtBeepUpdated_Click);
+ //
// BtBeepNewTop
//
- this.BtBeepNewTop.Location = new System.Drawing.Point(3, 105);
+ this.BtBeepNewTop.Location = new System.Drawing.Point(3, 96);
this.BtBeepNewTop.Name = "BtBeepNewTop";
this.BtBeepNewTop.Size = new System.Drawing.Size(115, 23);
this.BtBeepNewTop.TabIndex = 4;
@@ -3355,7 +3387,7 @@ private void InitializeComponent()
//
// BtBeepTop
//
- this.BtBeepTop.Location = new System.Drawing.Point(3, 76);
+ this.BtBeepTop.Location = new System.Drawing.Point(3, 70);
this.BtBeepTop.Name = "BtBeepTop";
this.BtBeepTop.Size = new System.Drawing.Size(115, 23);
this.BtBeepTop.TabIndex = 3;
@@ -3365,7 +3397,7 @@ private void InitializeComponent()
//
// BtBeepSuccess
//
- this.BtBeepSuccess.Location = new System.Drawing.Point(3, 47);
+ this.BtBeepSuccess.Location = new System.Drawing.Point(3, 44);
this.BtBeepSuccess.Name = "BtBeepSuccess";
this.BtBeepSuccess.Size = new System.Drawing.Size(115, 23);
this.BtBeepSuccess.TabIndex = 2;
@@ -3549,6 +3581,8 @@ private void InitializeComponent()
//
// groupBox13
//
+ this.groupBox13.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox13.Controls.Add(this.dataGridViewExportFolders);
this.groupBox13.Controls.Add(this.btAddExportFolder);
this.groupBox13.Location = new System.Drawing.Point(6, 112);
@@ -4486,22 +4520,15 @@ private void InitializeComponent()
this.panel1.Size = new System.Drawing.Size(758, 30);
this.panel1.TabIndex = 12;
//
- // BtRemoteServerSettingsUri
- //
- this.BtRemoteServerSettingsUri.Location = new System.Drawing.Point(565, 657);
- this.BtRemoteServerSettingsUri.Name = "BtRemoteServerSettingsUri";
- this.BtRemoteServerSettingsUri.Size = new System.Drawing.Size(167, 23);
- this.BtRemoteServerSettingsUri.TabIndex = 19;
- this.BtRemoteServerSettingsUri.Text = "Import remote settings";
- this.BtRemoteServerSettingsUri.UseVisualStyleBackColor = true;
- this.BtRemoteServerSettingsUri.Click += new System.EventHandler(this.BtRemoteServerSettingsUri_Click);
- //
- // TbRemoteServerSettingsUri
+ // CbLibraryDisplayZeroMutationLevels
//
- this.TbRemoteServerSettingsUri.Location = new System.Drawing.Point(407, 659);
- this.TbRemoteServerSettingsUri.Name = "TbRemoteServerSettingsUri";
- this.TbRemoteServerSettingsUri.Size = new System.Drawing.Size(152, 20);
- this.TbRemoteServerSettingsUri.TabIndex = 20;
+ this.CbLibraryDisplayZeroMutationLevels.AutoSize = true;
+ this.CbLibraryDisplayZeroMutationLevels.Location = new System.Drawing.Point(6, 203);
+ this.CbLibraryDisplayZeroMutationLevels.Name = "CbLibraryDisplayZeroMutationLevels";
+ this.CbLibraryDisplayZeroMutationLevels.Size = new System.Drawing.Size(156, 17);
+ this.CbLibraryDisplayZeroMutationLevels.TabIndex = 9;
+ this.CbLibraryDisplayZeroMutationLevels.Text = "Display zero mutation levels";
+ this.CbLibraryDisplayZeroMutationLevels.UseVisualStyleBackColor = true;
//
// Settings
//
@@ -4611,13 +4638,12 @@ private void InitializeComponent()
this.groupBox28.ResumeLayout(false);
this.groupBox28.PerformLayout();
this.tabPageImportSavegame.ResumeLayout(false);
- this.groupBox12.ResumeLayout(false);
- this.groupBox12.PerformLayout();
+ this.tabPageImportSavegame.PerformLayout();
+ this.groupBox14.ResumeLayout(false);
this.groupBox15.ResumeLayout(false);
this.groupBox15.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dataGridView_FileLocations)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.aTImportFileLocationBindingSource)).EndInit();
- this.groupBox14.ResumeLayout(false);
this.tabPageImportExported.ResumeLayout(false);
this.tabPageImportExported.PerformLayout();
this.groupBox27.ResumeLayout(false);
@@ -4745,7 +4771,6 @@ private void InitializeComponent()
private System.Windows.Forms.GroupBox groupBox9;
private System.Windows.Forms.CheckBox cbCreatureColorsLibrary;
private System.Windows.Forms.TabPage tabPageImportSavegame;
- private System.Windows.Forms.GroupBox groupBox12;
private System.Windows.Forms.Label label24;
private System.Windows.Forms.GroupBox groupBox15;
private System.Windows.Forms.GroupBox groupBox14;
@@ -4994,5 +5019,8 @@ private void InitializeComponent()
private System.Windows.Forms.Label label69;
private System.Windows.Forms.Button BtRemoteServerSettingsUri;
private System.Windows.Forms.TextBox TbRemoteServerSettingsUri;
+ private System.Windows.Forms.Button BtBeepUpdated;
+ private System.Windows.Forms.CheckBox CbStreamerMode;
+ private System.Windows.Forms.CheckBox CbLibraryDisplayZeroMutationLevels;
}
}
\ No newline at end of file
diff --git a/ARKBreedingStats/settings/Settings.cs b/ARKBreedingStats/settings/Settings.cs
index ecac9b50f..480349793 100644
--- a/ARKBreedingStats/settings/Settings.cs
+++ b/ARKBreedingStats/settings/Settings.cs
@@ -5,7 +5,6 @@
using System.Drawing;
using System.IO;
using System.Linq;
-using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -215,8 +214,15 @@ private void LoadSettings(CreatureCollection cc)
}
cbSingleplayerSettings.Checked = cc.singlePlayerSettings;
CbAtlasSettings.Checked = _cc.AtlasSettings;
- if (_cc.Game == Ark.Asa) RbGameAsa.Checked = true;
- else RbGameAse.Checked = true;
+ if (_cc.Game == Ark.Asa)
+ {
+ RbGameAsa.Checked = true;
+ }
+ else
+ {
+ RbGameAse.Checked = true;
+ CbAllowSpeedLeveling.Visible = false;
+ }
nudMaxDomLevels.ValueSave = cc.maxDomLevel;
numericUpDownMaxBreedingSug.ValueSave = cc.maxBreedingSuggestions;
@@ -360,6 +366,7 @@ private void LoadSettings(CreatureCollection cc)
CbNaturalSortIgnoreSpaces.Enabled = Properties.Settings.Default.UseNaturalSort;
CbNaturalSortIgnoreSpaces.Checked = Properties.Settings.Default.NaturalSortIgnoreSpaces;
CbDisplayLibraryCreatureIndex.Checked = Properties.Settings.Default.DisplayLibraryCreatureIndex;
+ CbLibraryDisplayZeroMutationLevels.Checked = Properties.Settings.Default.LibraryDisplayZeroMutationLevels;
#endregion
@@ -432,6 +439,7 @@ private void LoadSettings(CreatureCollection cc)
NudSpeciesSelectorCountLastUsed.ValueSave = Properties.Settings.Default.SpeciesSelectorCountLastSpecies;
+ CbStreamerMode.Checked = Properties.Settings.Default.StreamerMode;
cbDevTools.Checked = Properties.Settings.Default.DevTools;
cbPrettifyJSON.Checked = Properties.Settings.Default.prettifyCollectionJson;
@@ -614,6 +622,7 @@ private void SaveSettings()
Properties.Settings.Default.UseNaturalSort = CbNaturalSorting.Checked;
Properties.Settings.Default.NaturalSortIgnoreSpaces = CbNaturalSortIgnoreSpaces.Checked;
Properties.Settings.Default.DisplayLibraryCreatureIndex = CbDisplayLibraryCreatureIndex.Checked;
+ Properties.Settings.Default.LibraryDisplayZeroMutationLevels = CbLibraryDisplayZeroMutationLevels.Checked;
#endregion
@@ -670,6 +679,7 @@ private void SaveSettings()
Properties.Settings.Default.SpeciesSelectorCountLastSpecies = (int)NudSpeciesSelectorCountLastUsed.Value;
+ Properties.Settings.Default.StreamerMode = CbStreamerMode.Checked;
Properties.Settings.Default.DevTools = cbDevTools.Checked;
Properties.Settings.Default.prettifyCollectionJson = cbPrettifyJSON.Checked;
@@ -1296,6 +1306,7 @@ private void Localization()
Loc.ControlText(BtBeepSuccess, _tt);
Loc.ControlText(BtBeepTop, _tt);
Loc.ControlText(BtBeepNewTop, _tt);
+ Loc.ControlText(BtBeepUpdated, _tt);
Loc.ControlText(BtGetExportFolderAutomatically);
}
@@ -1335,6 +1346,11 @@ private void BtBeepNewTop_Click(object sender, EventArgs e)
SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.Great);
}
+ private void BtBeepUpdated_Click(object sender, EventArgs e)
+ {
+ SoundFeedback.BeepSignal(SoundFeedback.FeedbackSounds.Updated);
+ }
+
private void BtImportArchiveFolder_Click(object sender, EventArgs e)
{
// get folder of first export path
@@ -1776,5 +1792,13 @@ private async void BtRemoteServerSettingsUri_Click(object sender, EventArgs e)
BtRemoteServerSettingsUri.Text = "Load remote settings";
}
}
+
+ private void RbGameAsa_CheckedChanged(object sender, EventArgs e)
+ {
+ var isAsa = RbGameAsa.Checked;
+ CbAllowSpeedLeveling.Visible = isAsa;
+ if (!isAsa)
+ CbAllowSpeedLeveling.Checked = true;
+ }
}
}
diff --git a/ARKBreedingStats/settings/Settings.resx b/ARKBreedingStats/settings/Settings.resx
index 05c9ce312..ba4bd8b0e 100644
--- a/ARKBreedingStats/settings/Settings.resx
+++ b/ARKBreedingStats/settings/Settings.resx
@@ -120,6 +120,10 @@
If you have the files Game.ini or GameUserSettings.ini from your server, you can drag&&drop them on this window to insert their values.
You can also select the text of the settings and drag&&drop the selection.
+
+
+ The creature data can be directly imported from the save-game, if you have access to that. This is also possible via an ftp-adress.
+If you set the according files below, you can start the process automatically from the file-menu.
True
@@ -133,10 +137,6 @@ You can also select the text of the settings and drag&&drop the selectio
17, 17
-
- The creature data can be directly imported from the save-game, if you have access to that. This is also possible via an ftp-adress.
-If you set the according files below, you can start the process automatically from the file-menu.
-
True
diff --git a/ARKBreedingStats/species/Species.cs b/ARKBreedingStats/species/Species.cs
index 658ccaac9..47051e221 100644
--- a/ARKBreedingStats/species/Species.cs
+++ b/ARKBreedingStats/species/Species.cs
@@ -107,7 +107,7 @@ public class Species
///
/// The used multipliers for each stat applied to the imprinting-bonus, affected by custom overrides and global leveling settings.
- ///
+ ///
public double[] StatImprintMultipliers;
[JsonProperty]
@@ -436,7 +436,7 @@ public void LoadOverrides(Species overrides)
if (overrides.DisplayedStats != 0) DisplayedStats = overrides.DisplayedStats;
if (overrides.skipWildLevelStats != 0) skipWildLevelStats = overrides.skipWildLevelStats;
if (overrides.TamedBaseHealthMultiplier != null) TamedBaseHealthMultiplier = overrides.TamedBaseHealthMultiplier;
- if (overrides.statImprintMult != null) statImprintMult = overrides.statImprintMult.ToArray();
+ if (overrides.statImprintMult != null && overrides.statImprintMult != StatImprintMultipliersDefaultAse) statImprintMult = overrides.statImprintMult.ToArray();
if (overrides.mutationMult != null) mutationMult = overrides.mutationMult;
if (overrides.colors != null) colors = overrides.colors;
if (overrides.taming != null) taming = overrides.taming;
diff --git a/ARKBreedingStats/uiControls/CreatureAnalysis.cs b/ARKBreedingStats/uiControls/CreatureAnalysis.cs
index e6aeaa14f..969c3abc0 100644
--- a/ARKBreedingStats/uiControls/CreatureAnalysis.cs
+++ b/ARKBreedingStats/uiControls/CreatureAnalysis.cs
@@ -1,5 +1,6 @@
using System.Drawing;
using System.Windows.Forms;
+using ARKBreedingStats.library;
namespace ARKBreedingStats.uiControls
{
@@ -10,10 +11,10 @@ public CreatureAnalysis()
InitializeComponent();
}
- private LevelStatus _statsStatus;
- private LevelStatus _colorStatus;
+ private LevelStatusFlags.LevelStatus _statsStatus;
+ private LevelStatusFlags.LevelStatus _colorStatus;
- public void SetStatsAnalysis(LevelStatus statsStatus, string statsAnalysis)
+ public void SetStatsAnalysis(LevelStatusFlags.LevelStatus statsStatus, string statsAnalysis)
{
_statsStatus = statsStatus;
SetStatus(LbStatsStatus, statsStatus);
@@ -21,7 +22,7 @@ public void SetStatsAnalysis(LevelStatus statsStatus, string statsAnalysis)
LbStatAnalysis.Text = statsAnalysis;
var generalStatus = statsStatus;
- if (generalStatus != LevelStatus.NewTopLevel && _colorStatus != LevelStatus.Neutral)
+ if (!generalStatus.HasFlag(LevelStatusFlags.LevelStatus.NewTopLevel) && _colorStatus != LevelStatusFlags.LevelStatus.Neutral)
{
generalStatus = _colorStatus;
}
@@ -32,7 +33,7 @@ public void SetStatsAnalysis(LevelStatus statsStatus, string statsAnalysis)
///
/// Set the color status and uses the earlier set statsStatus.
///
- public void SetColorAnalysis(LevelStatus colorStatus, string colorAnalysis)
+ public void SetColorAnalysis(LevelStatusFlags.LevelStatus colorStatus, string colorAnalysis)
{
_colorStatus = colorStatus;
SetStatus(LbColorStatus, colorStatus);
@@ -40,7 +41,7 @@ public void SetColorAnalysis(LevelStatus colorStatus, string colorAnalysis)
LbColorAnalysis.Text = colorAnalysis;
var generalStatus = _statsStatus;
- if (generalStatus != LevelStatus.NewTopLevel && colorStatus != LevelStatus.Neutral)
+ if (generalStatus != LevelStatusFlags.LevelStatus.NewTopLevel && colorStatus != LevelStatusFlags.LevelStatus.Neutral)
{
generalStatus = colorStatus;
}
@@ -48,36 +49,36 @@ public void SetColorAnalysis(LevelStatus colorStatus, string colorAnalysis)
SetStatus(LbIcon, generalStatus, LbConclusion);
}
- private void SetStatus(Label labelIcon, LevelStatus status, Label labelText = null)
+ private void SetStatus(Label labelIcon, LevelStatusFlags.LevelStatus status, Label labelText = null)
{
- switch (status)
+ if (status.HasFlag(LevelStatusFlags.LevelStatus.NewTopLevel))
{
- case LevelStatus.TopLevel:
- labelIcon.BackColor = Color.LightGreen;
- labelIcon.ForeColor = Color.DarkGreen;
- labelIcon.Text = "✓";
- if (labelText != null)
- labelText.Text = "Keep this creature!";
- break;
- case LevelStatus.NewTopLevel:
- labelIcon.BackColor = Color.LightYellow;
- labelIcon.ForeColor = Color.Gold;
- labelIcon.Text = "★";
- if (labelText != null)
- labelText.Text = "Keep this creature, it adds new traits to your library!";
- break;
- default:
- labelIcon.BackColor = Color.LightGray;
- labelIcon.ForeColor = Color.Gray;
- labelIcon.Text = "-";
- if (labelText != null)
- labelText.Text = "This creature adds nothing new to your library.";
- break;
+ labelIcon.BackColor = Color.LightYellow;
+ labelIcon.ForeColor = Color.Gold;
+ labelIcon.Text = "★";
+ if (labelText != null)
+ labelText.Text = "Keep this creature, it adds new traits to your library!";
+ }
+ else if (status.HasFlag(LevelStatusFlags.LevelStatus.TopLevel))
+ {
+ labelIcon.BackColor = Color.LightGreen;
+ labelIcon.ForeColor = Color.DarkGreen;
+ labelIcon.Text = "✓";
+ if (labelText != null)
+ labelText.Text = "Keep this creature!";
+ }
+ else
+ {
+ labelIcon.BackColor = Color.LightGray;
+ labelIcon.ForeColor = Color.Gray;
+ labelIcon.Text = "-";
+ if (labelText != null)
+ labelText.Text = "This creature adds nothing new to your library.";
}
}
///
- /// Colors are not cleared, they are set independently from the stats if the colors are changed.
+ /// Colors are not cleared, they are set independent of the stats if the colors are changed.
///
public void Clear()
{
diff --git a/ARKBreedingStats/uiControls/MyColorPicker.cs b/ARKBreedingStats/uiControls/MyColorPicker.cs
index fbd865823..2cc3edbce 100644
--- a/ARKBreedingStats/uiControls/MyColorPicker.cs
+++ b/ARKBreedingStats/uiControls/MyColorPicker.cs
@@ -29,10 +29,7 @@ public MyColorPicker()
BtNoColor.Text = Loc.S("noColor");
LbAlternativeColor.Text = Loc.S("LbAlternativeColor");
_tt.SetToolTip(BtNoColor, "0: no color");
-
- BtUndefinedColor.Tag = Ark.UndefinedColorId; // one possible id of undefined color, currently used by Ark
- _tt.SetToolTip(BtUndefinedColor, $"{Ark.UndefinedColorId}: undefined color");
-
+ SetUndefinedColorId();
buttonCancel.Text = Loc.S("Cancel");
Disposed += MyColorPicker_Disposed;
@@ -48,6 +45,12 @@ private void MyColorPicker_Disposed(object sender, EventArgs e)
_tt.Dispose();
}
+ public void SetUndefinedColorId()
+ {
+ BtUndefinedColor.Tag = Ark.UndefinedColorId; // one possible id of undefined color, currently used by Ark
+ _tt.SetToolTip(BtUndefinedColor, $"{Ark.UndefinedColorId}: undefined color");
+ }
+
///
/// Clears color buttons. Call if color definitions changed, e.g. when a mod with colors is loaded or unloaded.
///
@@ -60,6 +63,7 @@ private void ResetColors()
c.Dispose();
}
flowLayoutPanel1.Controls.Clear();
+ SetUndefinedColorId();
}
public void PickColor(byte selectedColorId, string headerText, List naturalColors = null, byte selectedColorIdAlternative = 0)
diff --git a/ARKBreedingStats/uiControls/PopupMessage.cs b/ARKBreedingStats/uiControls/PopupMessage.cs
new file mode 100644
index 000000000..daad7823d
--- /dev/null
+++ b/ARKBreedingStats/uiControls/PopupMessage.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace ARKBreedingStats.uiControls
+{
+ internal class PopupMessage : Form
+ {
+ private Label _label;
+
+ public PopupMessage()
+ {
+ Width = 500;
+ Height = 400;
+ FormBorderStyle = FormBorderStyle.None;
+ ShowInTaskbar = false;
+ BackColor = Color.LightGray;
+ Padding = new Padding(2);
+ StartPosition = FormStartPosition.CenterParent;
+
+ var lClose = new Label
+ {
+ Text = Loc.S("click to close"),
+ Dock = DockStyle.Bottom,
+ TextAlign = ContentAlignment.MiddleCenter,
+ BackColor = Color.LightSalmon
+ };
+ Controls.Add(lClose);
+ lClose.Click += CloseClick;
+
+ _label = new Label
+ {
+ Dock = DockStyle.Fill,
+ ForeColor = Color.Gainsboro,
+ BackColor = Color.Black,
+ TextAlign = ContentAlignment.MiddleCenter
+ };
+ Controls.Add(_label);
+ _label.Click += CloseClick;
+ }
+
+ public PopupMessage(string message, float fontSize = 8.25f) : this()
+ {
+ if (fontSize != 8.25f)
+ _label.Font = new Font(_label.Font.FontFamily, fontSize);
+ _label.Text = message;
+ }
+
+ public static void Show(Form parent, string message, float fontSize = 8.25f)
+ {
+ new PopupMessage(message, fontSize).ShowDialog(parent);
+ }
+
+ private void CloseClick(object sender, EventArgs e) => Close();
+ }
+}
diff --git a/ARKBreedingStats/uiControls/StatIO.Designer.cs b/ARKBreedingStats/uiControls/StatIO.Designer.cs
index 2de2bc5f3..3cd396701 100644
--- a/ARKBreedingStats/uiControls/StatIO.Designer.cs
+++ b/ARKBreedingStats/uiControls/StatIO.Designer.cs
@@ -1,4 +1,4 @@
-namespace ARKBreedingStats
+namespace ARKBreedingStats.uiControls
{
partial class StatIO
{
diff --git a/ARKBreedingStats/uiControls/StatIO.cs b/ARKBreedingStats/uiControls/StatIO.cs
index 728364f63..f0110925c 100644
--- a/ARKBreedingStats/uiControls/StatIO.cs
+++ b/ARKBreedingStats/uiControls/StatIO.cs
@@ -3,10 +3,11 @@
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Threading;
+using ARKBreedingStats.library;
using ARKBreedingStats.utils;
using Cursors = System.Windows.Forms.Cursors;
-namespace ARKBreedingStats
+namespace ARKBreedingStats.uiControls
{
public partial class StatIO : UserControl
{
@@ -188,43 +189,44 @@ public StatIOStatus Status
}
}
- private LevelStatus _topLevel;
- public LevelStatus TopLevel
+ private LevelStatusFlags.LevelStatus _topLevel;
+ public LevelStatusFlags.LevelStatus TopLevel
{
get => _topLevel;
set
{
+ if (_topLevel == value) return;
_topLevel = value;
- if (_topLevel == LevelStatus.Neutral)
+ if (_topLevel == LevelStatusFlags.LevelStatus.Neutral)
{
labelWildLevel.BackColor = Color.Transparent;
_tt.SetToolTip(labelWildLevel, null);
return;
}
- if (_topLevel.HasFlag(LevelStatus.TopLevel))
+ if (_topLevel.HasFlag(LevelStatusFlags.LevelStatus.TopLevel))
{
labelWildLevel.BackColor = Color.LightGreen;
_tt.SetToolTip(labelWildLevel, Loc.S("topLevel"));
}
- else if (_topLevel.HasFlag(LevelStatus.NewTopLevel))
+ else if (_topLevel.HasFlag(LevelStatusFlags.LevelStatus.NewTopLevel))
{
labelWildLevel.BackColor = Color.Gold;
_tt.SetToolTip(labelWildLevel, Loc.S("newTopLevel"));
}
- if (_topLevel.HasFlag(LevelStatus.MaxLevelForLevelUp))
+ if (_topLevel.HasFlag(LevelStatusFlags.LevelStatus.MaxLevelForLevelUp))
{
labelWildLevel.BackColor = Color.DeepSkyBlue;
_tt.SetToolTip(labelWildLevel, Loc.S("maxLevelForLevelUp"));
}
- else if (_topLevel.HasFlag(LevelStatus.MaxLevel))
+ else if (_topLevel.HasFlag(LevelStatusFlags.LevelStatus.MaxLevel))
{
labelWildLevel.BackColor = Color.Orange;
_tt.SetToolTip(labelWildLevel, Loc.S("maxLevelSaved"));
}
- else if (_topLevel.HasFlag(LevelStatus.UltraMaxLevel))
+ else if (_topLevel.HasFlag(LevelStatusFlags.LevelStatus.UltraMaxLevel))
{
labelWildLevel.BackColor = Color.LightCoral;
_tt.SetToolTip(labelWildLevel, Loc.S("ultraMaxLevel"));
@@ -267,7 +269,7 @@ public bool IsActive
public void Clear()
{
Status = StatIOStatus.Neutral;
- TopLevel = LevelStatus.Neutral;
+ TopLevel = LevelStatusFlags.LevelStatus.Neutral;
numLvW.Value = 0;
nudLvM.Value = 0;
numLvD.Value = 0;
@@ -280,18 +282,7 @@ public void Clear()
private void numLvW_ValueChanged(object sender, EventArgs e)
{
- int lengthPercentage = 100 * (int)numLvW.Value / barMaxLevel; // in percentage of the max bar width
-
- if (lengthPercentage > 100)
- {
- lengthPercentage = 100;
- }
- if (lengthPercentage < 0)
- {
- lengthPercentage = 0;
- }
- panelBarWildLevels.Width = lengthPercentage * MaxBarLength / 100;
- panelBarWildLevels.BackColor = Utils.GetColorFromPercent(lengthPercentage);
+ SetLevelBar(panelBarWildLevels, numLvW.Value);
_tt.SetToolTip(panelBarWildLevels, Utils.LevelPercentile((int)numLvW.Value));
if (_linkWildMutated && _wildMutatedSum != -1)
@@ -305,18 +296,7 @@ private void numLvW_ValueChanged(object sender, EventArgs e)
private void nudLvM_ValueChanged(object sender, EventArgs e)
{
- int lengthPercentage = 100 * (int)nudLvM.Value / barMaxLevel; // in percentage of the max bar width
-
- if (lengthPercentage > 100)
- {
- lengthPercentage = 100;
- }
- if (lengthPercentage < 0)
- {
- lengthPercentage = 0;
- }
- panelBarMutLevels.Width = lengthPercentage * MaxBarLength / 100;
- panelBarMutLevels.BackColor = Utils.GetColorFromPercent(lengthPercentage);
+ SetLevelBar(panelBarMutLevels, nudLvM.Value);
if (_linkWildMutated && _wildMutatedSum != -1)
{
@@ -329,23 +309,23 @@ private void nudLvM_ValueChanged(object sender, EventArgs e)
private void numLvD_ValueChanged(object sender, EventArgs e)
{
- int lengthPercentage = 100 * (int)numLvD.Value / barMaxLevel; // in percentage of the max bar width
-
- if (lengthPercentage > 100)
- {
- lengthPercentage = 100;
- }
- if (lengthPercentage < 0)
- {
- lengthPercentage = 0;
- }
- panelBarDomLevels.Width = lengthPercentage * MaxBarLength / 100;
- panelBarDomLevels.BackColor = Utils.GetColorFromPercent(lengthPercentage);
+ SetLevelBar(panelBarDomLevels, numLvD.Value);
if (_inputType != StatIOInputType.FinalValueInputType)
LevelChangedDebouncer();
}
+ private void SetLevelBar(Panel panel, decimal level)
+ {
+ var lengthPercentage = 100 * (int)level / barMaxLevel; // in percentage of the max bar width
+
+ if (lengthPercentage > 100) lengthPercentage = 100;
+ else if (lengthPercentage < 0) lengthPercentage = 0;
+
+ panel.Width = lengthPercentage * MaxBarLength / 100;
+ panel.BackColor = Utils.GetColorFromPercent(lengthPercentage);
+ }
+
private readonly Debouncer _levelChangedDebouncer = new Debouncer();
private void LevelChangedDebouncer() => _levelChangedDebouncer.Debounce(200, FireLevelChanged, Dispatcher.CurrentDispatcher);
@@ -453,35 +433,6 @@ public enum StatIOStatus
Error
}
- ///
- /// Status of wild levels, e.g. top level, max level.
- ///
- [Flags]
- public enum LevelStatus
- {
- Neutral = 0,
- ///
- /// wild level is equal to the current top-level
- ///
- TopLevel = 1,
- ///
- /// wild level is higher than the current top-level
- ///
- NewTopLevel = 2,
- ///
- /// Max level to apply domesticated levels.
- ///
- MaxLevelForLevelUp = 4,
- ///
- /// Max level that can be saved.
- ///
- MaxLevel = 8,
- ///
- /// Level too high to be saved, rollover will happen.
- ///
- UltraMaxLevel = 16
- }
-
public enum StatIOInputType
{
FinalValueInputType,
diff --git a/ARKBreedingStats/uiControls/StatWeighting.cs b/ARKBreedingStats/uiControls/StatWeighting.cs
index 21a2f449c..089ac36ed 100644
--- a/ARKBreedingStats/uiControls/StatWeighting.cs
+++ b/ARKBreedingStats/uiControls/StatWeighting.cs
@@ -385,5 +385,25 @@ private void SetState(byte state)
}
}
}
+
+ ///
+ /// Describes if a stat level is desired to be high or low or if it doesn't matter.
+ ///
+ public enum StatValuePreference
+ {
+ Indifferent,
+ Low,
+ High
+ }
+
+ ///
+ /// Describes if a stat level should be even or odd or if it doesn't matter.
+ ///
+ public enum StatValueEvenOdd
+ {
+ Indifferent,
+ Odd,
+ Even
+ }
}
}
diff --git a/ARKBreedingStats/utils/CreatureListSorter.cs b/ARKBreedingStats/utils/CreatureListSorter.cs
index 0a7e44b8d..4a6ddd004 100644
--- a/ARKBreedingStats/utils/CreatureListSorter.cs
+++ b/ARKBreedingStats/utils/CreatureListSorter.cs
@@ -136,7 +136,7 @@ private IEnumerable OrderList(IEnumerable list, IComparer c.sex,
c => c.domesticatedAt,
c => c.topness,
- c => c.topStatsCount,
+ c => c.topStatsConsideredCount,
c => c.generation,
c => c.levelFound,
c => c.Mutations,
diff --git a/ARKBreedingStats/utils/SoundFeedback.cs b/ARKBreedingStats/utils/SoundFeedback.cs
index a4d9217dd..4a66f6384 100644
--- a/ARKBreedingStats/utils/SoundFeedback.cs
+++ b/ARKBreedingStats/utils/SoundFeedback.cs
@@ -13,10 +13,12 @@ internal enum FeedbackSounds
Success,
Good,
Great,
- Indifferent
+ Indifferent,
+ Updated,
+ NewMutation
}
- private static readonly SoundPlayer _sp = new SoundPlayer();
+ private static readonly SoundPlayer Sp = new SoundPlayer();
///
/// Beeps.
@@ -25,25 +27,33 @@ public static void BeepSignal(FeedbackSounds kind)
{
switch (kind)
{
+ case FeedbackSounds.Updated:
+ Sp.Stream = Properties.Resources.updated;
+ Sp.Play();
+ return;
case FeedbackSounds.Indifferent:
- _sp.Stream = Properties.Resources.indifferent;
- _sp.Play();
+ Sp.Stream = Properties.Resources.indifferent;
+ Sp.Play();
return;
case FeedbackSounds.Failure:
- _sp.Stream = Properties.Resources.failure;
- _sp.Play();
+ Sp.Stream = Properties.Resources.failure;
+ Sp.Play();
return;
case FeedbackSounds.Success:
- _sp.Stream = Properties.Resources.success;
- _sp.Play();
+ Sp.Stream = Properties.Resources.success;
+ Sp.Play();
return;
case FeedbackSounds.Good:
- _sp.Stream = Properties.Resources.topstat;
- _sp.Play();
+ Sp.Stream = Properties.Resources.topstat;
+ Sp.Play();
return;
case FeedbackSounds.Great:
- _sp.Stream = Properties.Resources.newtopstat;
- _sp.Play();
+ Sp.Stream = Properties.Resources.newtopstat;
+ Sp.Play();
+ return;
+ case FeedbackSounds.NewMutation:
+ Sp.Stream = Properties.Resources.newMutation;
+ Sp.Play();
return;
}
}