diff --git a/ARKBreedingStats/CreatureInfoInput.cs b/ARKBreedingStats/CreatureInfoInput.cs index 80b5e926..b55307df 100644 --- a/ARKBreedingStats/CreatureInfoInput.cs +++ b/ARKBreedingStats/CreatureInfoInput.cs @@ -15,7 +15,7 @@ public partial class CreatureInfoInput : UserControl public event Save2LibraryClickedEventHandler Save2Library_Clicked; public delegate void RequestParentListEventHandler(CreatureInfoInput sender); public event RequestParentListEventHandler ParentListRequested; - public delegate void RequestCreatureDataEventHandler(CreatureInfoInput sender, bool patternEditor); + public delegate void RequestCreatureDataEventHandler(CreatureInfoInput sender, bool patternEditor, bool showDuplicateNameWarning); public event RequestCreatureDataEventHandler CreatureDataRequested; public bool extractor; private Sex sex; @@ -426,7 +426,7 @@ private void btnGenerateUniqueName_Click(object sender, EventArgs e) { if (selectedSpecies != null) { - CreatureDataRequested?.Invoke(this, false); + CreatureDataRequested?.Invoke(this, false, true); } } @@ -434,17 +434,17 @@ private void btnGenerateUniqueName_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { - CreatureDataRequested?.Invoke(this, true); // TODO doesn't get called when right-clicking. Why? + CreatureDataRequested?.Invoke(this, true, true); } } /// /// Generates a creature name with a given pattern /// - public void generateCreatureName(Creature creature) + public void generateCreatureName(Creature creature, bool showDuplicateNameWarning) { setCreatureData(creature); - CreatureName = uiControls.NamePatterns.generateCreatureName(creature, _females, _males); + CreatureName = uiControls.NamePatterns.generateCreatureName(creature, _females, _males, showDuplicateNameWarning); } public void openNamePatternEditor(Creature creature) diff --git a/ARKBreedingStats/Extraction.cs b/ARKBreedingStats/Extraction.cs index c4bd1568..a0e50aab 100644 --- a/ARKBreedingStats/Extraction.cs +++ b/ARKBreedingStats/Extraction.cs @@ -142,6 +142,7 @@ public void ExtractLevels(Species species, int level, List statIOs, doub // Pteranodon (Lvl 34, TE: 80%): HP: 415.9 (6, 0); St: 195 (6, 0); Ox: 240 (6, 0); Fo: 2150.4 (6, 0); We: 134.4 (6, 0); Dm: 141.6% (3, 0); Sp: 135% (0, 0); To: 358.1 (33); // will fail the extraction with a lowerTEBound of 0.8, it only extracts with a lowerTEBound of 0.79, then displays 0.8 as result for the TE. Adding these margins make it work as expected. lowerTEBound -= 0.0006; + if (lowerTEBound < 0) lowerTEBound = 0; upperTEBound += 0.0006; } diff --git a/ARKBreedingStats/Form1.cs b/ARKBreedingStats/Form1.cs index 02a9cbe4..959dbe0d 100644 --- a/ARKBreedingStats/Form1.cs +++ b/ARKBreedingStats/Form1.cs @@ -2787,7 +2787,7 @@ private void UpdateTempCreatureDropDown() /// /// /// - private void CreatureInfoInput_CreatureDataRequested(CreatureInfoInput sender, bool openPatternEditor) + private void CreatureInfoInput_CreatureDataRequested(CreatureInfoInput sender, bool openPatternEditor, bool showDuplicateNameWarning) { Creature cr = new Creature { @@ -2819,7 +2819,7 @@ private void CreatureInfoInput_CreatureDataRequested(CreatureInfoInput sender, b if (openPatternEditor) sender.openNamePatternEditor(cr); else - sender.generateCreatureName(cr); + sender.generateCreatureName(cr, showDuplicateNameWarning); } private void ExtractionTestControl1_CopyToTester(string speciesBP, int[] wildLevels, int[] domLevels, bool postTamed, bool bred, double te, double imprintingBonus, bool gotoTester, testCases.TestCaseControl tcc) diff --git a/ARKBreedingStats/Form1.extractor.cs b/ARKBreedingStats/Form1.extractor.cs index 26dc5fe7..ca70e097 100644 --- a/ARKBreedingStats/Form1.extractor.cs +++ b/ARKBreedingStats/Form1.extractor.cs @@ -167,7 +167,8 @@ private void ClearAll(bool clearExtraCreatureData = true) exportedCreatureControl = null; creatureInfoInputExtractor.SetArkId(0, false); } - DisplayIfCreatureAlreadyInLibrary(); + + creatureInfoInputExtractor.UpdateExistingCreature = false; } private void buttonExtract_Click(object sender, EventArgs e) @@ -181,7 +182,7 @@ private void buttonExtract_Click(object sender, EventArgs e) /// /// Set to true if the data is from an export file which has a higher precision for stat-values so the tolerance of calculations can be smaller. /// - private bool ExtractLevels(bool autoExtraction = false, bool statInputsHighPrecision = false, bool showLevelsInOverlay = false) + private bool ExtractLevels(bool autoExtraction = false, bool statInputsHighPrecision = false, bool showLevelsInOverlay = false, Creature existingCreature = null) { SuspendLayout(); int activeStatKeeper = activeStatIndex; @@ -245,15 +246,34 @@ private bool ExtractLevels(bool autoExtraction = false, bool statInputsHighPreci } else if (extractor.results[s].Count > 0) { - // choose the most probable wild-level, aka the level nearest to the mean of the wild levels. - int r = 0; - for (int b = 1; b < extractor.results[s].Count; b++) + if (existingCreature != null) { - if (Math.Abs(meanWildLevel - extractor.results[s][b].levelWild) < Math.Abs(meanWildLevel - extractor.results[s][r].levelWild)) - r = b; + // set the wild levels to the existing ones + int r = 0; + for (int b = 1; b < extractor.results[s].Count; b++) + { + if (extractor.results[s][b].levelWild == existingCreature.levelsWild[s] + && extractor.results[s][b].levelDom >= existingCreature.levelsDom[s] + && extractor.results[s][b].TE.Includes(existingCreature.tamingEff)) + { + r = b; + break; + } + } + SetLevelCombination(s, r == -1 ? 0 : r); } + else + { + // choose the most probable wild-level, aka the level nearest to the mean of the wild levels. + int r = 0; + for (int b = 1; b < extractor.results[s].Count; b++) + { + if (Math.Abs(meanWildLevel - extractor.results[s][b].levelWild) < Math.Abs(meanWildLevel - extractor.results[s][r].levelWild)) + r = b; + } - SetLevelCombination(s, r); + SetLevelCombination(s, r); + } if (extractor.results[s].Count > 1) { statIOs[s].Status = StatIOStatus.Nonunique; @@ -746,26 +766,19 @@ private bool ExtractExportedFileInExtractor(string exportFile) return false; } - SetCreatureValuesToExtractor(cv, false); - // exported stat-files have values for all stats, so activate all stats the species uses - SetStatsActiveAccordingToUsage(cv.Species); - - ExtractLevels(autoExtraction: true, statInputsHighPrecision: true); - UpdateParentListInput(creatureInfoInputExtractor); // this function is only used for single-creature extractions, e.g. LastExport - SetCreatureValuesToInfoInput(cv, creatureInfoInputExtractor); + bool creatureExists = ExtractValuesInExtractor(cv, exportFile, true); if (Properties.Settings.Default.applyNamePatternOnImportIfEmptyName && string.IsNullOrEmpty(creatureInfoInputExtractor.CreatureName)) { - CreatureInfoInput_CreatureDataRequested(creatureInfoInputExtractor, false); + CreatureInfoInput_CreatureDataRequested(creatureInfoInputExtractor, false, false); if (Properties.Settings.Default.copyNameToClipboardOnImportWhenAutoNameApplied) Clipboard.SetText(creatureInfoInputExtractor.CreatureName); } tabControlMain.SelectedTab = tabPageExtractor; - SetMessageLabelText("Creature of the exported file\n" + exportFile); - return DisplayIfCreatureAlreadyInLibrary(); + return creatureExists; } /// @@ -778,25 +791,30 @@ private void ExtractExportedFileInExtractor(importExported.ExportedCreatureContr if (ecc == null) return; - SetCreatureValuesToExtractor(ecc.creatureValues, false); + bool creatureExists = ExtractValuesInExtractor(ecc.creatureValues, exportedCreatureControl.exportedFile, false); - // exported stat-files have values for all stats, so activate all stats the species uses - SetStatsActiveAccordingToUsage(ecc.creatureValues.Species); - - ExtractLevels(autoExtraction: false, statInputsHighPrecision: true); // gets deleted in extractLevels() exportedCreatureControl = ecc; - // not for batch-extractions, only for single creatures - //if (updateParentVisuals) // TODO parents need to be updated always to be able to select the correct parent. Change GetParent from parentCombobox so that it only returns a guid? - UpdateParentListInput(creatureInfoInputExtractor); - - SetCreatureValuesToInfoInput(exportedCreatureControl.creatureValues, creatureInfoInputExtractor); if (exportedCreatureList != null && exportedCreatureList.ownerSuffix != null) creatureInfoInputExtractor.CreatureOwner += exportedCreatureList.ownerSuffix; + } + + private bool ExtractValuesInExtractor(CreatureValues cv, string filePath, bool autoExtraction) + { + SetCreatureValuesToExtractor(cv, false); + + // exported stat-files have values for all stats, so activate all stats the species uses + SetStatsActiveAccordingToUsage(cv.Species); - SetMessageLabelText("Creature of the exported file\n" + exportedCreatureControl.exportedFile); - DisplayIfCreatureAlreadyInLibrary(); + bool creatureExists = IsCreatureAlreadyInLibrary(cv.guid, cv.ARKID, out Creature existingCreature); + + ExtractLevels(autoExtraction: autoExtraction, statInputsHighPrecision: true, existingCreature: existingCreature); + UpdateParentListInput(creatureInfoInputExtractor); // this function is only used for single-creature extractions, e.g. LastExport + SetCreatureValuesToInfoInput(cv, creatureInfoInputExtractor); + creatureInfoInputExtractor.UpdateExistingCreature = creatureExists; + SetMessageLabelText("Creature of the exported file\n" + filePath); + return creatureExists; } /// @@ -870,14 +888,19 @@ private void SetCreatureValuesToExtractor(CreatureValues cv, bool setInfoInput = /// Gives feedback to the user if the current creature in the extractor is already in the library. /// This uses the ARK-ID and only works if exported creatures are imported /// - private bool DisplayIfCreatureAlreadyInLibrary() + private bool IsCreatureAlreadyInLibrary(Guid creatureGuid, long arkId, out Creature existingCreature) { - bool creatureAlreadyExistsInLibrary = creatureInfoInputExtractor.CreatureGuid != Guid.Empty - && Utils.IsArkIdImported(creatureInfoInputExtractor.ArkId, creatureInfoInputExtractor.CreatureGuid) - && creatureCollection.creatures.Any(c => c.guid == creatureInfoInputExtractor.CreatureGuid - && !c.flags.HasFlag(CreatureFlags.Placeholder) - ); - creatureInfoInputExtractor.UpdateExistingCreature = creatureAlreadyExistsInLibrary; + existingCreature = null; + bool creatureAlreadyExistsInLibrary = false; + if (creatureGuid != Guid.Empty + && Utils.IsArkIdImported(arkId, creatureGuid)) + { + existingCreature = creatureCollection.creatures.FirstOrDefault(c => c.guid == creatureGuid + && !c.flags.HasFlag(CreatureFlags.Placeholder) + ); + if (existingCreature != null) + creatureAlreadyExistsInLibrary = true; + } return creatureAlreadyExistsInLibrary; } } diff --git a/ARKBreedingStats/Form1.importExported.cs b/ARKBreedingStats/Form1.importExported.cs index 7305b12e..b8e431dd 100644 --- a/ARKBreedingStats/Form1.importExported.cs +++ b/ARKBreedingStats/Form1.importExported.cs @@ -113,10 +113,12 @@ private void ExportedCreatureList_CopyValuesToExtractor(importExported.ExportedC private void ImportExportedAddIfPossible_WatcherThread(string filePath) { // wait a moment until the file is readable. why is this necessary? blocked by fileWatcher? - System.Threading.Thread.Sleep(100); + System.Threading.Thread.Sleep(200); - // filewatcher is on another thread, invoke ui-thread to work with ui - Invoke(new Action(delegate () { ImportExportedAddIfPossible(filePath); })); + // moving to the archived folder can trigger another fileWatcherEvent, first check if the file is still there + if (File.Exists(filePath)) + // filewatcher is on another thread, invoke ui-thread to work with ui + Invoke(new Action(delegate () { ImportExportedAddIfPossible(filePath); })); } /// @@ -128,7 +130,8 @@ private void ImportExportedAddIfPossible(string filePath) bool alreadyExists = ExtractExportedFileInExtractor(filePath); bool added = false; - if (extractor.uniqueResults) + if (extractor.uniqueResults + || (alreadyExists && extractor.validResults)) { AddCreatureToCollection(true, goToLibraryTab: false); added = true; diff --git a/ARKBreedingStats/settings/Settings.Designer.cs b/ARKBreedingStats/settings/Settings.Designer.cs index a2e94794..917bfe67 100644 --- a/ARKBreedingStats/settings/Settings.Designer.cs +++ b/ARKBreedingStats/settings/Settings.Designer.cs @@ -157,6 +157,8 @@ private void InitializeComponent() this.label24 = new System.Windows.Forms.Label(); this.tabPageImportExported = new System.Windows.Forms.TabPage(); this.groupBox22 = new System.Windows.Forms.GroupBox(); + this.cbDeleteAutoImportedFile = new System.Windows.Forms.CheckBox(); + this.cbMoveImportedFileToSubFolder = new System.Windows.Forms.CheckBox(); this.label28 = new System.Windows.Forms.Label(); this.cbAutoImportExported = new System.Windows.Forms.CheckBox(); this.groupBox21 = new System.Windows.Forms.GroupBox(); @@ -175,8 +177,6 @@ private void InitializeComponent() this.aTExportFolderLocationsBindingSource = new System.Windows.Forms.BindingSource(this.components); this.btAddExportFolder = new System.Windows.Forms.Button(); this.label25 = new System.Windows.Forms.Label(); - this.cbMoveImportedFileToSubFolder = new System.Windows.Forms.CheckBox(); - this.cbDeleteAutoImportedFile = new System.Windows.Forms.CheckBox(); this.groupBoxMultiplier.SuspendLayout(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nudWaitBeforeScreenCapture)).BeginInit(); @@ -1621,7 +1621,7 @@ private void InitializeComponent() this.customSCCustom.Location = new System.Drawing.Point(6, 139); this.customSCCustom.Name = "customSCCustom"; this.customSCCustom.Size = new System.Drawing.Size(401, 23); - this.customSCCustom.SoundFile = ""; + this.customSCCustom.SoundFile = null; this.customSCCustom.TabIndex = 7; // // customSCWakeup @@ -1629,7 +1629,7 @@ private void InitializeComponent() this.customSCWakeup.Location = new System.Drawing.Point(6, 81); this.customSCWakeup.Name = "customSCWakeup"; this.customSCWakeup.Size = new System.Drawing.Size(401, 23); - this.customSCWakeup.SoundFile = null; + this.customSCWakeup.SoundFile = ""; this.customSCWakeup.TabIndex = 6; // // customSCBirth @@ -1637,7 +1637,7 @@ private void InitializeComponent() this.customSCBirth.Location = new System.Drawing.Point(6, 110); this.customSCBirth.Name = "customSCBirth"; this.customSCBirth.Size = new System.Drawing.Size(401, 23); - this.customSCBirth.SoundFile = null; + this.customSCBirth.SoundFile = ""; this.customSCBirth.TabIndex = 5; // // customSCStarving @@ -1645,7 +1645,7 @@ private void InitializeComponent() this.customSCStarving.Location = new System.Drawing.Point(6, 52); this.customSCStarving.Name = "customSCStarving"; this.customSCStarving.Size = new System.Drawing.Size(401, 23); - this.customSCStarving.SoundFile = ""; + this.customSCStarving.SoundFile = null; this.customSCStarving.TabIndex = 4; // // label20 @@ -1867,6 +1867,28 @@ private void InitializeComponent() this.groupBox22.TabStop = false; this.groupBox22.Text = "Auto import"; // + // cbDeleteAutoImportedFile + // + this.cbDeleteAutoImportedFile.AutoSize = true; + this.cbDeleteAutoImportedFile.Location = new System.Drawing.Point(29, 78); + this.cbDeleteAutoImportedFile.Name = "cbDeleteAutoImportedFile"; + this.cbDeleteAutoImportedFile.Size = new System.Drawing.Size(116, 17); + this.cbDeleteAutoImportedFile.TabIndex = 3; + this.cbDeleteAutoImportedFile.Text = "Delete imported file"; + this.cbDeleteAutoImportedFile.UseVisualStyleBackColor = true; + this.cbDeleteAutoImportedFile.CheckedChanged += new System.EventHandler(this.cbDeleteAutoImportedFile_CheckedChanged); + // + // cbMoveImportedFileToSubFolder + // + this.cbMoveImportedFileToSubFolder.AutoSize = true; + this.cbMoveImportedFileToSubFolder.Location = new System.Drawing.Point(29, 55); + this.cbMoveImportedFileToSubFolder.Name = "cbMoveImportedFileToSubFolder"; + this.cbMoveImportedFileToSubFolder.Size = new System.Drawing.Size(223, 17); + this.cbMoveImportedFileToSubFolder.TabIndex = 2; + this.cbMoveImportedFileToSubFolder.Text = "Move imported file to \"imported\" subfolder"; + this.cbMoveImportedFileToSubFolder.UseVisualStyleBackColor = true; + this.cbMoveImportedFileToSubFolder.CheckedChanged += new System.EventHandler(this.cbMoveImportedFileToSubFolder_CheckedChanged); + // // label28 // this.label28.AutoSize = true; @@ -1953,9 +1975,9 @@ private void InitializeComponent() // this.groupBox13.Controls.Add(this.dataGridViewExportFolders); this.groupBox13.Controls.Add(this.btAddExportFolder); - this.groupBox13.Location = new System.Drawing.Point(6, 93); + this.groupBox13.Location = new System.Drawing.Point(6, 111); this.groupBox13.Name = "groupBox13"; - this.groupBox13.Size = new System.Drawing.Size(736, 373); + this.groupBox13.Size = new System.Drawing.Size(736, 355); this.groupBox13.TabIndex = 5; this.groupBox13.TabStop = false; this.groupBox13.Text = "ARK export folders"; @@ -1973,7 +1995,7 @@ private void InitializeComponent() this.dataGridViewExportFolders.Dock = System.Windows.Forms.DockStyle.Fill; this.dataGridViewExportFolders.Location = new System.Drawing.Point(3, 16); this.dataGridViewExportFolders.Name = "dataGridViewExportFolders"; - this.dataGridViewExportFolders.Size = new System.Drawing.Size(730, 354); + this.dataGridViewExportFolders.Size = new System.Drawing.Size(730, 336); this.dataGridViewExportFolders.TabIndex = 5; this.dataGridViewExportFolders.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridViewExportFolders_CellClick); // @@ -2041,32 +2063,10 @@ private void InitializeComponent() this.label25.AutoSize = true; this.label25.Location = new System.Drawing.Point(6, 19); this.label25.Name = "label25"; - this.label25.Size = new System.Drawing.Size(579, 52); + this.label25.Size = new System.Drawing.Size(579, 78); this.label25.TabIndex = 0; this.label25.Text = resources.GetString("label25.Text"); // - // cbMoveImportedFileToSubFolder - // - this.cbMoveImportedFileToSubFolder.AutoSize = true; - this.cbMoveImportedFileToSubFolder.Location = new System.Drawing.Point(29, 55); - this.cbMoveImportedFileToSubFolder.Name = "cbMoveImportedFileToSubFolder"; - this.cbMoveImportedFileToSubFolder.Size = new System.Drawing.Size(223, 17); - this.cbMoveImportedFileToSubFolder.TabIndex = 2; - this.cbMoveImportedFileToSubFolder.Text = "Move imported file to \"imported\" subfolder"; - this.cbMoveImportedFileToSubFolder.UseVisualStyleBackColor = true; - this.cbMoveImportedFileToSubFolder.CheckedChanged += new System.EventHandler(this.cbMoveImportedFileToSubFolder_CheckedChanged); - // - // cbDeleteAutoImportedFile - // - this.cbDeleteAutoImportedFile.AutoSize = true; - this.cbDeleteAutoImportedFile.Location = new System.Drawing.Point(29, 78); - this.cbDeleteAutoImportedFile.Name = "cbDeleteAutoImportedFile"; - this.cbDeleteAutoImportedFile.Size = new System.Drawing.Size(116, 17); - this.cbDeleteAutoImportedFile.TabIndex = 3; - this.cbDeleteAutoImportedFile.Text = "Delete imported file"; - this.cbDeleteAutoImportedFile.UseVisualStyleBackColor = true; - this.cbDeleteAutoImportedFile.CheckedChanged += new System.EventHandler(this.cbDeleteAutoImportedFile_CheckedChanged); - // // Settings // this.AcceptButton = this.buttonOK; diff --git a/ARKBreedingStats/settings/Settings.resx b/ARKBreedingStats/settings/Settings.resx index 526c28d9..db13c6d0 100644 --- a/ARKBreedingStats/settings/Settings.resx +++ b/ARKBreedingStats/settings/Settings.resx @@ -121,12 +121,6 @@ Enables a OCR-feature, that tries to read the values from the screen by creating a screenshot and extracting the numbers from that (i.e. does not trigger BattlEye). It does only work with the resolutions 1920×1080 and 1680×1050, and sometimes does make mistakes. It works with the window-mode "Fullscreen-Windowed" and sometimes does not work when multiple screens are used. - - - In ARK you can export a creature (hold use while looking at a creature, then choose "Options" - "Export" from the wheel). - -The exported creatures are saved as a file. Select the folder to import these files. Usually the folder is -...\Steam\steamapps\common\ARK\ShooterGame\Saved\DinoExports\<ID> True @@ -137,15 +131,6 @@ The exported creatures are saved as a file. Select the folder to import these fi 17, 17 - - True - - - True - - - 17, 17 - The creature data can be imported from the save-game, if it is available. If you set the according files below, you can start the process automatically from the file-menu. Make sure the folders are correct. @@ -159,13 +144,12 @@ If you set the according files below, you can start the process automatically fr 262, 17 - - True - - - True - - - 262, 17 - + + In ARK you can export a creature (hold use while looking at a creature, then choose "Options" - "Export" from the wheel). + +The exported creatures are saved as a file. Select the folder to import these files. Usually the folder is +...\Steam\steamapps\common\ARK\ShooterGame\Saved\DinoExports\<ID> + +The first entry is the default export folder and is used for 'Import last exported' and the Auto Import. + \ No newline at end of file diff --git a/ARKBreedingStats/uiControls/NamePatterns.cs b/ARKBreedingStats/uiControls/NamePatterns.cs index d6eb0df9..bb2e9bc2 100644 --- a/ARKBreedingStats/uiControls/NamePatterns.cs +++ b/ARKBreedingStats/uiControls/NamePatterns.cs @@ -13,7 +13,7 @@ public static class NamePatterns /// /// Generates a creature name with a given pattern /// - public static string generateCreatureName(Creature creature, List females, List males) + public static string generateCreatureName(Creature creature, List females, List males, bool showDuplicateNameWarning) { //try //{ @@ -42,13 +42,13 @@ public static string generateCreatureName(Creature creature, List fema } while (creatureNames.Contains(name, StringComparer.OrdinalIgnoreCase)); } - if (creatureNames.Contains(name, StringComparer.OrdinalIgnoreCase)) + if (showDuplicateNameWarning && creatureNames.Contains(name, StringComparer.OrdinalIgnoreCase)) { MessageBox.Show("WARNING: The generated name for the creature already exists in the database."); } else if (name.Length > 24) { - MessageBox.Show("WARNING: The generated name is longer than 24 characters, ingame-preview:" + name.Substring(0, 24)); + MessageBox.Show("WARNING: The generated name is longer than 24 characters, ingame-preview:\n" + name.Substring(0, 24), "Name too long for game", MessageBoxButtons.OK, MessageBoxIcon.Warning); } return name;