Skip to content

Commit 70ba61d

Browse files
committed
Allow customizing game settings
1 parent e69530b commit 70ba61d

File tree

9 files changed

+194
-12
lines changed

9 files changed

+194
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
obj/
33
bin/
44
cache/
5+
data/
56
Level.sav.json
67

78
character*.json

PalCalc.UI/MainWindow.xaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,22 @@
1515
d:DataContext="{d:DesignInstance vm:MainWindowViewModel, IsDesignTimeCreatable=True}">
1616
<Grid>
1717
<Grid.ColumnDefinitions>
18-
<ColumnDefinition Width="200"/>
18+
<ColumnDefinition MinWidth="220"/>
1919
<ColumnDefinition Width="Auto"/>
2020
<ColumnDefinition Width="232*"/>
2121
<ColumnDefinition Width="Auto"/>
2222
<ColumnDefinition Width="43*"/>
2323
</Grid.ColumnDefinitions>
2424
<DockPanel Grid.Column="0" Margin="10,10,10,10" IsEnabled="{Binding IsEditable}">
25-
<GroupBox Header="Save File" DockPanel.Dock="Top">
26-
<v:SaveSelectorView DataContext="{Binding SaveSelection}" />
27-
</GroupBox>
25+
<StackPanel DockPanel.Dock="Top">
26+
<GroupBox Header="Save File">
27+
<v:SaveSelectorView DataContext="{Binding SaveSelection}" />
28+
</GroupBox>
29+
30+
<GroupBox Header="Game Settings">
31+
<v:GameSettingsView DataContext="{Binding GameSettings}" />
32+
</GroupBox>
33+
</StackPanel>
2834

2935
<GroupBox Header="Target Pals">
3036
<v:PalTargetListView DataContext="{Binding PalTargetList}" />

PalCalc.UI/Model/Storage.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.IO;
8+
using System.IO.Enumeration;
89
using System.Linq;
910
using System.Text;
1011
using System.Threading.Tasks;
@@ -23,7 +24,10 @@ internal static class Storage
2324
public static string SaveCachePathFor(SaveGame forSaveFile) => $"{SaveCachePath}/{CachedSaveGame.IdentifierFor(forSaveFile)}.json";
2425

2526
// path for storing data associated with a specific save file
26-
public static string SaveFileDataPath(SaveGame forSaveFile) => $"{DataPath}/results/{CachedSaveGame.IdentifierFor(forSaveFile)}";
27+
public static string SaveFileDataPath(SaveGame forSaveFile) => $"{DataPath}/{CachedSaveGame.IdentifierFor(forSaveFile)}";
28+
29+
// path for storing game-specific game settings (breeding time, etc.)
30+
public static string GameSettingsPath(SaveGame forSaveFile) => SaveFileDataPath(forSaveFile) + "/game-settings.json";
2731

2832
public static string AppSettingsPath => $"{DataPath}/settings.json";
2933

@@ -36,6 +40,25 @@ public static void Init()
3640
if (!Directory.Exists(SaveCachePath)) Directory.CreateDirectory(SaveCachePath);
3741
if (!Directory.Exists(DataPath)) Directory.CreateDirectory(DataPath);
3842

43+
// migrate file locations from before beta-v0.5
44+
if (Directory.Exists($"{DataPath}/results"))
45+
{
46+
foreach (var entry in Directory.EnumerateFileSystemEntries($"{DataPath}/results"))
47+
{
48+
var newPath = $"{DataPath}/{Path.GetFileName(entry)}";
49+
if (File.GetAttributes(entry).HasFlag(FileAttributes.Directory))
50+
{
51+
Directory.Move(entry, newPath);
52+
}
53+
else
54+
{
55+
File.Move(entry, newPath);
56+
}
57+
}
58+
59+
Directory.Delete($"{DataPath}/results");
60+
}
61+
3962
didInit = true;
4063
}
4164

@@ -70,7 +93,7 @@ public static void ClearForSave(SaveGame save)
7093

7194
var dataPath = SaveFileDataPath(save);
7295
if (Directory.Exists(dataPath))
73-
Directory.Delete(dataPath);
96+
Directory.Delete(dataPath, true);
7497
}
7598

7699
#region Cached Game Save Files

PalCalc.UI/PalCalc.UI.csproj.user

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
<Compile Update="View\BreedingResultView.xaml.cs">
1414
<SubType>Code</SubType>
1515
</Compile>
16+
<Compile Update="View\GameSettingsView.xaml.cs">
17+
<SubType>Code</SubType>
18+
</Compile>
1619
<Compile Update="View\LoadingSaveFileModal.xaml.cs">
1720
<SubType>Code</SubType>
1821
</Compile>
@@ -45,6 +48,9 @@
4548
<Page Update="View\BreedingResultView.xaml">
4649
<SubType>Designer</SubType>
4750
</Page>
51+
<Page Update="View\GameSettingsView.xaml">
52+
<SubType>Designer</SubType>
53+
</Page>
4854
<Page Update="View\LoadingSaveFileModal.xaml">
4955
<SubType>Designer</SubType>
5056
</Page>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<UserControl x:Class="PalCalc.UI.View.GameSettingsView"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:local="clr-namespace:PalCalc.UI.View"
7+
xmlns:mvm="clr-namespace:PalCalc.UI.ViewModel.Mapped"
8+
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
9+
mc:Ignorable="d"
10+
d:Background="White"
11+
d:DataContext="{d:DesignInstance mvm:GameSettingsViewModel, IsDesignTimeCreatable=True}"
12+
d:DesignHeight="146.283" d:DesignWidth="622.784">
13+
<Grid>
14+
<Grid.ColumnDefinitions>
15+
<ColumnDefinition Width="Auto"/>
16+
<ColumnDefinition Width="*"/>
17+
</Grid.ColumnDefinitions>
18+
19+
<Label Grid.Column="0" Content="Breeding Time (Mins)" HorizontalAlignment="Left" VerticalAlignment="Top" />
20+
<xctk:IntegerUpDown Grid.Column="1" Value="{Binding BreedingTimeMinutes}" Minimum="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,3,0,0" />
21+
22+
<Label Grid.Column="0" Content="Multiple Breeding Farms" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,26,0,0" />
23+
<CheckBox Grid.Column="1" IsChecked="{Binding MultipleBreedingFarms}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,31,0,0" />
24+
</Grid>
25+
</UserControl>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
using System.Windows.Controls;
8+
using System.Windows.Data;
9+
using System.Windows.Documents;
10+
using System.Windows.Input;
11+
using System.Windows.Media;
12+
using System.Windows.Media.Imaging;
13+
using System.Windows.Navigation;
14+
using System.Windows.Shapes;
15+
16+
namespace PalCalc.UI.View
17+
{
18+
/// <summary>
19+
/// Interaction logic for GameSettingsView.xaml
20+
/// </summary>
21+
public partial class GameSettingsView : UserControl
22+
{
23+
public GameSettingsView()
24+
{
25+
InitializeComponent();
26+
}
27+
}
28+
}

PalCalc.UI/ViewModel/MainWindowViewModel.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public MainWindowViewModel(Dispatcher dispatcher)
124124
SaveSelection.PropertyChanged += SaveSelection_PropertyChanged;
125125
SaveSelection.NewCustomSaveSelected += SaveSelection_CustomSaveAdded;
126126

127-
UpdateTargetsList();
127+
UpdateFromSaveProperties();
128128
}
129129

130130
private void SaveSelection_CustomSaveAdded(ManualSavesLocationViewModel manualSaves, SaveGame save)
@@ -172,21 +172,26 @@ private void CachedSaveGame_SaveFileLoadError(SaveGame obj, Exception ex)
172172
MessageBox.Show("An error occurred when loading the save file");
173173
}
174174

175-
private void UpdateTargetsList()
175+
private void UpdateFromSaveProperties()
176176
{
177177
if (PalTargetList != null) PalTargetList.PropertyChanged -= PalTargetList_PropertyChanged;
178+
if (GameSettings != null) GameSettings.PropertyChanged -= GameSettings_PropertyChanged;
178179

179180
if (SaveSelection.SelectedGame?.Value == null)
180181
{
181182
PalTargetList = null;
182183
PalTarget = null;
184+
GameSettings = null;
183185
}
184186
else
185187
{
186188
CrashSupport.ReferencedSave(SaveSelection.SelectedGame.Value);
187189

188190
PalTargetList = targetsBySaveFile[SaveSelection.SelectedGame.Value];
189191
PalTargetList.PropertyChanged += PalTargetList_PropertyChanged;
192+
193+
GameSettings = GameSettingsViewModel.Load(SaveSelection.SelectedGame.Value);
194+
GameSettings.PropertyChanged += GameSettings_PropertyChanged;
190195
}
191196

192197
UpdatePalTarget();
@@ -200,11 +205,21 @@ private void UpdatePalTarget()
200205
PalTarget = null;
201206
}
202207

208+
private void GameSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
209+
{
210+
var saveGame = SaveSelection.SelectedGame?.Value;
211+
if (saveGame != null)
212+
{
213+
var settings = sender as GameSettingsViewModel;
214+
settings.Save(saveGame);
215+
}
216+
}
217+
203218
private void SaveSelection_PropertyChanged(object sender, PropertyChangedEventArgs e)
204219
{
205220
if (e.PropertyName == nameof(SaveSelection.SelectedGame))
206221
{
207-
UpdateTargetsList();
222+
UpdateFromSaveProperties();
208223
}
209224
}
210225

@@ -224,7 +239,7 @@ public void RunSolver()
224239
var cachedData = SaveSelection.SelectedGame.CachedValue;
225240
if (cachedData == null) return;
226241

227-
var solver = SolverControls.ConfiguredSolver(cachedData.OwnedPals);
242+
var solver = SolverControls.ConfiguredSolver(GameSettings.ModelObject, cachedData.OwnedPals);
228243
solver.SolverStateUpdated += Solver_SolverStateUpdated;
229244

230245
Task.Factory.StartNew(() =>
@@ -322,6 +337,8 @@ private void Solver_SolverStateUpdated(SolverStatus obj)
322337
[ObservableProperty]
323338
private SaveSelectorViewModel saveSelection;
324339
[ObservableProperty]
340+
private GameSettingsViewModel gameSettings;
341+
[ObservableProperty]
325342
private SolverControlsViewModel solverControls;
326343
[ObservableProperty]
327344
private PalTargetListViewModel palTargetList;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using CommunityToolkit.Mvvm.ComponentModel;
2+
using Newtonsoft.Json;
3+
using PalCalc.Model;
4+
using PalCalc.SaveReader;
5+
using PalCalc.UI.Model;
6+
using Serilog;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.IO;
10+
using System.Linq;
11+
using System.Text;
12+
using System.Threading.Tasks;
13+
using System.Windows.Controls.Primitives;
14+
15+
namespace PalCalc.UI.ViewModel.Mapped
16+
{
17+
public partial class GameSettingsViewModel : ObservableObject
18+
{
19+
private static ILogger logger = Log.ForContext<GameSettingsViewModel>();
20+
21+
// for XAML designer view
22+
public GameSettingsViewModel()
23+
{
24+
BreedingTimeMinutes = 10;
25+
MultipleBreedingFarms = true;
26+
}
27+
28+
public GameSettingsViewModel(GameSettings modelObject)
29+
{
30+
BreedingTimeMinutes = (int)modelObject.BreedingTime.TotalMinutes;
31+
MultipleBreedingFarms = modelObject.MultipleBreedingFarms;
32+
}
33+
34+
[JsonIgnore]
35+
public GameSettings ModelObject => new GameSettings()
36+
{
37+
BreedingTime = TimeSpan.FromMinutes(BreedingTimeMinutes),
38+
MultipleBreedingFarms = MultipleBreedingFarms,
39+
};
40+
41+
[ObservableProperty]
42+
private int breedingTimeMinutes;
43+
44+
[ObservableProperty]
45+
private bool multipleBreedingFarms;
46+
47+
public string ToJson() => JsonConvert.SerializeObject(this);
48+
public static GameSettingsViewModel FromJson(string json) => JsonConvert.DeserializeObject<GameSettingsViewModel>(json);
49+
50+
public void Save(SaveGame forSave)
51+
{
52+
File.WriteAllText(Storage.GameSettingsPath(forSave), ToJson());
53+
}
54+
55+
public static GameSettingsViewModel Load(SaveGame forSave)
56+
{
57+
var path = Storage.GameSettingsPath(forSave);
58+
if (File.Exists(path))
59+
{
60+
try
61+
{
62+
return FromJson(File.ReadAllText(path));
63+
}
64+
catch (Exception ex)
65+
{
66+
logger.Error(ex, "error when loading game settings from {path}", path);
67+
return new GameSettingsViewModel();
68+
}
69+
}
70+
else
71+
{
72+
return new GameSettingsViewModel();
73+
}
74+
}
75+
}
76+
}

PalCalc.UI/ViewModel/SolverControlsViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ public int MaxIrrelevantTraits
4545

4646
public bool CanCancelSolver => !CanRunSolver;
4747

48-
public BreedingSolver ConfiguredSolver(List<PalInstance> pals) => new BreedingSolver(
49-
new GameSettings(),
48+
public BreedingSolver ConfiguredSolver(GameSettings gameSettings, List<PalInstance> pals) => new BreedingSolver(
49+
gameSettings,
5050
PalDB.LoadEmbedded(),
5151
pals,
5252
MaxBreedingSteps,

0 commit comments

Comments
 (0)