//updateCurrentRoute sets up the UI, SAVE and INI files, as well as the selectedRoute when the game route is changed via the UI void updateCurrentRoute() { makeSave(); Routes.GameRoutes selectedRoute = GetSelectedRoute(); thisSave = SAVE.SAVEFile.SetSaveForRoute(thisSave, IDs.Locations.GetRoomID(locationCombo.SelectedItem.ToString()), selectedRoute); thisINI = INI.SetINIForRoute(IDs.Locations.GetRoomID(locationCombo.SelectedItem.ToString()), selectedRoute); loadSAVE(thisSave); loadINI(); LOVEChanged(); }
//We use the loadButton_Click event to open a new folder browser to allow the user to load a save and set up the UI for the loaded save private void loadButton_Click(object sender, RoutedEventArgs e) { FolderBrowser2 directoryFolderBrowser = new FolderBrowser2(); directoryFolderBrowser.ShowDialog(null); if (File.Exists(directoryFolderBrowser.DirectoryPath + "//file0")) { SAVE.SAVEFile saveFile = SAVE.SAVEFile.LoadSaveFile(directoryFolderBrowser.DirectoryPath); loadSAVE(saveFile); thisINI = INI.ReadINI(saveFile); loadINI(); Routes.GameRoutes closestRoute = SAVE.SAVEFile.GetClosestRoute(saveFile); if (closestRoute == Routes.GameRoutes.Genocide) { genocideRadio.IsChecked = true; } else if (closestRoute >= Routes.GameRoutes.TruePacifistDate) { pacifistRadio.IsChecked = true; routeCombo.SelectedItem = Routes.GetEnumDescription(SAVE.SAVEFile.GetClosestRoute(thisSave)); } else { neutralRadio.IsChecked = true; routeCombo.SelectedItem = Routes.GetEnumDescription(SAVE.SAVEFile.GetClosestRoute(thisSave)); } MXA2SE.play_sound(soundEngine, "Assets//Sounds//fileLoaded.wav"); } else { Dictionary <Characters, string> messageDict = new Dictionary <Characters, string>() { { Characters.Alphys, "S-s-sorry, that folder doesn't contain a valid Undertale save file." }, { Characters.Asgore, "Human, I'm sorry, but folder doesn't contain a valid Undertale save file." }, { Characters.Asriel, "I'm really sorry, I tried, but couldn't find a valid Undertale save file in that folder." }, { Characters.Flowey, "YOU. IDIOT! That folder doesn't contain a valid Undertale save file!" }, { Characters.Papyrus, "NYOO HOO HOO. I, THE GREAT PAPYRUS, HAVE FAILED TO FIND A VALID SAVE FILE IN THAT FOLDER." }, { Characters.Sans, "heyo, pal. try again. i couldn't find an Undertale save file in that folder." }, { Characters.Toriel, "My child, I am sorry, but I was unable to find a valid Undertale save file in that folder." }, { Characters.Undyne, "HEY, PUNK! I CAN'T FIND AN UNDERTALE SAVE FILE IN THAT FOLDER!" }, { Characters.None, "The folder specified does not contain a valid Undertale save file!" } }; UTMessageBox.Show(messageDict, Constants.CharacterReactions.Negative, MessageBoxButton.OK); } }
//We use the Window_Loaded event to create new instances of our SAVEFile and INI file classes, as well as populating our UI controls and item dicts private void SharpWindow_Loaded(object sender, RoutedEventArgs e) { loading = true; thisSave = new SAVE.SAVEFile(); thisINI = new INI.INIFile(); IDs.Weapons.populateDictionary(); IDs.Armors.populateDictionary(); IDs.Items.populateDictionary(); IDs.PhoneItems.populateDictionary(); IDs.InventoryItems.populateDictionary(); IDs.Locations.populateDictionary(); Stats.populateDictionary(); populateAllCombos(); setDefaultValues(); thisINI = INI.GetINI(); loadINI(); loading = false; }
//ReadINI reads, well, the INI. public static INIFile ReadINI(SAVE.SAVEFile save) { var iniReader = new Ini.IniFile(Constants.SavesPath + save.SaveName + "//undertale.ini"); staticINIFile.defaultINI = false; staticINIFile.timePlayed = ConvertFramesToTimePlayed(iniReader.IniReadValue("General", "Time")); staticINIFile.deaths = FromININumber(iniReader.IniReadValue("General", "Gameover")); staticINIFile.FUN = FromININumber(iniReader.IniReadValue("General", "fun")); staticINIFile.skipAsrielStory = FromINIBool(iniReader.IniReadValue("General", "Tale")); staticINIFile.beatNeutralRun = FromINIBool(iniReader.IniReadValue("General", "Won")); staticINIFile.trueResetted = FromINIBool(iniReader.IniReadValue("reset", "reset")); staticINIFile.doorUnlocked = FromINIBool(iniReader.IniReadValue("reset", "s_key")); staticINIFile.timesMetFlowey = FromININumber(iniReader.IniReadValue("Flowey", "Met1")); if (FromINIBool(iniReader.IniReadValue("Flowey", "IK"))) { save.floweyState = CharacterStates.Killed; } else { save.floweyState = CharacterStates.Default; } staticINIFile.floweyChatProgress = FromININumber(iniReader.IniReadValue("Flowey", "EX")); staticINIFile.piePreference = FromININumber(iniReader.IniReadValue("Toriel", "Bscotch")); if (FromINIBool(iniReader.IniReadValue("Toriel", "TK"))) { save.torielState = CharacterStates.Killed; } else { save.torielState = CharacterStates.Default; } staticINIFile.timesMetSans = FromININumber(iniReader.IniReadValue("Sans", "M1")); staticINIFile.sansMetInJudgment = FromINIBool(iniReader.IniReadValue("Sans", "EndMet")); staticINIFile.sansPasswordProgress = FromININumber(iniReader.IniReadValue("Sans", "Pass")); staticINIFile.killedSans = FromINIBool(iniReader.IniReadValue("Sans", "SK")); staticINIFile.timesReachedMid = FromININumber(iniReader.IniReadValue("Sans", "MP")); staticINIFile.timesFoughtSans = FromININumber(iniReader.IniReadValue("Sans", "F")); staticINIFile.timesHeardIntro = FromININumber(iniReader.IniReadValue("Sans", "Intro")); staticINIFile.timesMetPapyrus = FromININumber(iniReader.IniReadValue("Papyrus", "M1")); save.papyrusState = FromINICharacterState(iniReader.IniReadValue("Papyrus", "PK")); save.papyrusDated = FromINIDateState(iniReader.IniReadValue("Papyrus", "PD")); save.undyneDated = FromINIDateState(iniReader.IniReadValue("Undyne", "UD")); staticINIFile.mettatonSkip = FromINIBool(iniReader.IniReadValue("Mettaton", "BossMet")); save.alphysDated = FromINIDateState(iniReader.IniReadValue("Alphys", "AD")); staticINIFile.fightStage = FromININumber(iniReader.IniReadValue("FFFFF", "P")); staticINIFile.skipFight = FromINIBool(iniReader.IniReadValue("FFFFF", "E")); staticINIFile.barrierDestroyed = FromINIBool(iniReader.IniReadValue("F7", "F7")); staticINIFile.canTrueReset = FromINIBool(iniReader.IniReadValue("EndF", "EndF")); return(staticINIFile); }
//WriteINI writes, well, the INI. public static bool WriteINI(INIFile INItoWrite, SAVE.SAVEFile save) { try { var iniWriter = new Ini.IniFile(Constants.SavesPath + save.SaveName + "//undertale.ini"); iniWriter.IniWriteValue("General", "Name", save.PlayerName); iniWriter.IniWriteValue("General", "Time", ConvertTimePlayedToFrames(INItoWrite.timePlayed)); iniWriter.IniWriteValue("General", "Room", save.Location.ToString()); iniWriter.IniWriteValue("General", "Gameover", INItoWrite.deaths.ToString()); iniWriter.IniWriteValue("General", "Kills", save.KillCount.ToString()); iniWriter.IniWriteValue("General", "Love", save.LOVE.ToString()); iniWriter.IniWriteValue("General", "fun", INItoWrite.FUN.ToString()); iniWriter.IniWriteValue("General", "Tale", ToINIBool(INItoWrite.skipAsrielStory)); iniWriter.IniWriteValue("General", "Won", ToININumber(Convert.ToInt16(INItoWrite.beatNeutralRun) + Convert.ToInt16(INItoWrite.floweyChatProgress))); iniWriter.IniWriteValue("reset", "reset", ToINIBool(INItoWrite.trueResetted)); iniWriter.IniWriteValue("reset", "s_key", ToINIBool(INItoWrite.doorUnlocked)); iniWriter.IniWriteValue("Flowey", "Met1", ToININumber(INItoWrite.timesMetFlowey)); if (save.floweyState == CharacterStates.Killed) { iniWriter.IniWriteValue("Flowey", "IK", "1.000000"); } else if (INItoWrite.beatNeutralRun) { iniWriter.IniWriteValue("Flowey", "NK", "1.000000"); } iniWriter.IniWriteValue("Flowey", "EX", ToININumber(INItoWrite.floweyChatProgress)); iniWriter.IniWriteValue("Toriel", "Bscotch", ToININumber(INItoWrite.piePreference)); if (save.torielState == CharacterStates.TorielKilled) { iniWriter.IniWriteValue("Toriel", "TK", "1.000000"); } else if (save.torielState == CharacterStates.Spared) { iniWriter.IniWriteValue("Toriel", "TS", "1.000000"); } else if (save.torielState == CharacterStates.Default) { iniWriter.IniWriteValue("Toriel", "TS", "0.000000"); } iniWriter.IniWriteValue("Sans", "M1", ToININumber(INItoWrite.timesMetSans)); iniWriter.IniWriteValue("Sans", "EndMet", ToINIBool(INItoWrite.sansMetInJudgment)); if (save.LOVE == 1) { iniWriter.IniWriteValue("Sans", "MeetLv1", ToININumber(INItoWrite.timesMetSans)); } else { iniWriter.IniWriteValue("Sans", "MeetLv2", ToININumber(INItoWrite.timesMetSans)); } iniWriter.IniWriteValue("Sans", "Pass", ToININumber(INItoWrite.sansPasswordProgress)); iniWriter.IniWriteValue("Sans", "SK", ToINIBool(INItoWrite.killedSans)); iniWriter.IniWriteValue("Sans", "MP", ToININumber(INItoWrite.timesReachedMid)); iniWriter.IniWriteValue("Sans", "F", ToININumber(INItoWrite.timesFoughtSans)); iniWriter.IniWriteValue("Sans", "Intro", ToININumber(INItoWrite.timesHeardIntro)); iniWriter.IniWriteValue("Papyrus", "M1", ToININumber(INItoWrite.timesMetPapyrus)); if (save.papyrusState == CharacterStates.Killed) { iniWriter.IniWriteValue("Papyrus", "PK", "1.000000"); } else if (save.papyrusState == CharacterStates.Spared) { iniWriter.IniWriteValue("Papyrus", "PS", "1.000000"); } else if (save.papyrusState == CharacterStates.Default) { iniWriter.IniWriteValue("Papyrus", "PS", "0.000000"); } iniWriter.IniWriteValue("Papyrus", "PD", ToINIDateState(save.papyrusDated)); iniWriter.IniWriteValue("Undyne", "UD", ToINIDateState(save.undyneDated)); iniWriter.IniWriteValue("Mettaton", "BossMet", ToINIBool(INItoWrite.mettatonSkip)); iniWriter.IniWriteValue("Alphys", "AD", ToINIDateState(save.alphysDated)); iniWriter.IniWriteValue("F7", "F7", ToINIBool(INItoWrite.barrierDestroyed)); iniWriter.IniWriteValue("EndF", "EndF", ToINIBool(INItoWrite.canTrueReset)); iniWriter.IniWriteValue("FFFFF", "F", ToINIBool(INItoWrite.photoshopFight)); iniWriter.IniWriteValue("FFFFF", "P", ToININumber(INItoWrite.fightStage)); iniWriter.IniWriteValue("FFFFF", "E", ToINIBool(INItoWrite.skipFight)); return(true); } catch (Exception ex) { System.Windows.MessageBox.Show("An exception occurred when attempting to write the INI file. Cannot continue. The exception was: \n\n" + ex + "\n\n Please notify me of this issue via reddit or Skype. ", "Error!", MessageBoxButton.OK, MessageBoxImage.Error); return(false); } }
//makeSave loops through all UI controls and converts and casts to thisSave variable types as required to create a new save void makeSave() { thisSave.PlayerName = nameBox.Text; thisSave.Location = IDs.Locations.GetRoomID(locationCombo.SelectedItem.ToString()); thisSave.LOVE = Convert.ToInt16(LOVECombo.Text); thisSave.KillCount = Convert.ToInt16(killsBox.Text); thisSave.GOLD = Convert.ToInt16(GOLDBox.Text); thisSave.Weapon = IDs.GetID(weaponCombo.SelectedItem.ToString()); thisSave.Armor = IDs.GetID(armorCombo.SelectedItem.ToString()); thisSave.HP = Convert.ToInt16(HPBox.Text); thisSave.friskAT = Convert.ToInt16(friskATBox.Text) + 10; //For some reason, the game sets Frisk's base AT to -10 of what is set in the thisSave.friskDF = Convert.ToInt16(friskDFBox.Text) + 10; //save file. Am I missing something regarding the AT/DF system? thisSave.weaponAT = Convert.ToInt16(weaponATBox.Text); thisSave.armorDF = Convert.ToInt16(armorDFBox.Text); int i = 0; Array.Clear(thisSave.inventoryItems, 0, thisSave.inventoryItems.Length); foreach (Grid grid in inventoryGrid.Children.OfType <Grid>()) { foreach (ComboBox comboBox in grid.Children.OfType <ComboBox>()) { thisSave.inventoryItems[i] = IDs.GetID(comboBox.SelectedItem.ToString()); i++; } } i = 0; Array.Clear(thisSave.phoneItems, 0, thisSave.phoneItems.Length); foreach (var checkBox in phoneItemsGrid.Children.OfType <CheckBox>()) { if ((bool)checkBox.IsChecked) { thisSave.phoneItems[i] = IDs.GetID(checkBox.Content.ToString()); i++; } } thisSave.SaveName = saveNameBox.Text; thisINI = INI.GetINI(); thisINI.sansMetInJudgment = MiscFunctions.SetBooleanValueFromLocation(thisSave.Location, 232); if (thisSave.Location == 999) { thisINI.photoshopFight = true; } else { thisINI.skipFight = false; } if (thisSave.Location == 998) { thisSave = SAVE.SAVEFile.SetSaveForRoute(thisSave, thisSave.Location, Routes.GameRoutes.Genocide); genocideRadio.IsChecked = true; } if (GetSelectedRoute() >= Routes.GameRoutes.TruePacifistAsrielTalk) { thisINI.barrierDestroyed = true; } if (GetSelectedRoute() == Routes.GameRoutes.TruePacifistEpilogue) { thisINI.canTrueReset = true; } else if (GetSelectedRoute() == Routes.GameRoutes.Genocide) { thisINI.killedSans = MiscFunctions.SetBooleanValueFromLocation(thisSave.Location, 232); } }
//loadSAVE sets up the UI for the values from the new saveFile void loadSAVE(SAVE.SAVEFile saveFile) { loading = true; nameBox.Text = saveFile.PlayerName; foreach (var thisItem in locationCombo.Items) { if ((string)thisItem == IDs.Locations.GetRoomString(saveFile.Location)) { locationCombo.SelectedIndex = locationCombo.Items.IndexOf(thisItem); } } LOVECombo.SelectedIndex = saveFile.LOVE - 1; killsBox.Text = saveFile.KillCount.ToString(); GOLDBox.Text = saveFile.GOLD.ToString(); setComboIndexFromLoad(weaponCombo, saveFile.Weapon); setComboIndexFromLoad(armorCombo, saveFile.Armor); HPBox.Text = saveFile.HP.ToString(); friskATBox.Text = saveFile.friskAT.ToString(); friskDFBox.Text = saveFile.friskDF.ToString(); weaponATBox.Text = saveFile.weaponAT.ToString(); armorDFBox.Text = saveFile.armorDF.ToString(); for (int i = 0; i < saveFile.inventoryItems.Length; i++) //Can this be improved like how we handle setting the save? { int item = saveFile.inventoryItems[i]; ComboBox currentComboBox = new ComboBox(); switch (i) { case 0: currentComboBox = item1Combo; break; case 1: currentComboBox = item2Combo; break; case 2: currentComboBox = item3Combo; break; case 3: currentComboBox = item4Combo; break; case 4: currentComboBox = item5Combo; break; case 5: currentComboBox = item6Combo; break; case 6: currentComboBox = item7Combo; break; case 7: currentComboBox = item8Combo; break; } foreach (var thisItem in currentComboBox.Items) { if ((string)thisItem == IDs.GetStringValue(item)) { currentComboBox.SelectedIndex = currentComboBox.Items.IndexOf(thisItem); } } } torielCheck.IsChecked = false; papyrusCheck.IsChecked = false; boxACheck.IsChecked = false; boxBCheck.IsChecked = false; foreach (var phoneItem in saveFile.phoneItems) { switch (phoneItem) { case 206: torielCheck.IsChecked = true; break; case 210: papyrusCheck.IsChecked = true; break; case 220: boxACheck.IsChecked = true; break; case 221: boxBCheck.IsChecked = true; break; } } loading = false; saveNameBox.Text = saveFile.SaveName; thisSave = saveFile; }