Read all containers!

This commit is contained in:
Li 2023-02-25 19:46:12 +13:00
parent fcd47415f5
commit 2e0eb65b47
14 changed files with 412 additions and 73 deletions

View File

@ -0,0 +1,44 @@
using LibXom.Data;
using LibXom.Streams;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibW4M.Data.Awards
{
public class TeamAwardsData : SaveDataEntry
{
int[] TeamAwards;
public TeamAwardsData(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
public override void Load()
{
using (XomStreamReader reader = new XomStreamReader(new MemoryStream(this.mainContainer.GetData())))
{
reader.Skip(3);
this.TeamAwards = reader.ReadInt32Array();
}
}
public override void Save()
{
using (MemoryStream ms = new MemoryStream())
{
using (XomStreamWriter writer = new XomStreamWriter(ms))
{
writer.Skip(3);
writer.WriteInt32Array(TeamAwards);
ms.Seek(0x00, SeekOrigin.Begin);
mainContainer.SetData(ms.ToArray());
}
}
}
}
}

View File

@ -34,10 +34,11 @@ namespace LibW4M.Data.Highscores
int[] decompressedCollective = mainContainer.Decompress();
// get total length of teams collective
int teamsLen = decompressedCollective[0];
// Highscore collective starts right *after* the teams collective.
int highscoreStart = teamsLen + 1;
// get the current number of highscores.
int highscoresLen = Length;
int highscoresLen = this.Length;
// copy teams data from collective.
int[] teamsData = new int[teamsLen + 1];

View File

@ -0,0 +1,52 @@
using LibXom.Data;
using LibXom.Streams;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibW4M.Data.InputMapping
{
public class InputDetailsData : SaveDataEntry
{
public InputDetailsData(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
public int Type;
public int Key;
public int JoystickAxis;
public override void Load()
{
using (XomStreamReader reader = new XomStreamReader(new MemoryStream(this.mainContainer.GetData())))
{
reader.Skip(3);
this.Type = reader.ReadInt32();
this.Key = reader.ReadInt32();
this.JoystickAxis = reader.ReadInt32();
}
}
public override void Save()
{
using (MemoryStream ms = new MemoryStream())
{
using (XomStreamWriter writer = new XomStreamWriter(ms))
{
writer.Skip(3);
writer.WriteInt32(this.Type);
writer.WriteInt32(this.Key);
writer.WriteInt32(this.JoystickAxis);
ms.Seek(0x00, SeekOrigin.Begin);
mainContainer.SetData(ms.ToArray());
}
}
}
}
}

View File

@ -0,0 +1,76 @@
using LibXom.Data;
using LibXom.Streams;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibW4M.Data.InputMapping
{
public class InputEventMappingData : SaveDataEntry
{
XomString Message;
XomString FEResourceID;
byte[] AllowedDuplacates;
InputDetailsData[] InputMappings;
int Group;
public InputEventMappingData(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
public override void Load()
{
using (XomStreamReader reader = new XomStreamReader(new MemoryStream(this.mainContainer.GetData())))
{
reader.Skip(3);
this.Message = fileBelongs.LookupStringFromId(reader.ReadCompressedInt());
this.FEResourceID = fileBelongs.LookupStringFromId(reader.ReadCompressedInt());
this.AllowedDuplacates = reader.ReadByteArray();
int[] inputMappingIds = reader.ReadCompressedIntArray();
InputMappings = new InputDetailsData[inputMappingIds.Length];
for(int i = 0; i < inputMappingIds.Length; i++)
{
InputMappings[i] = new InputDetailsData(this.fileBelongs, this.fileBelongs.LookupContainerById(inputMappingIds[i]));
}
this.Group = reader.ReadCompressedInt();
}
}
public override void Save()
{
using (MemoryStream ms = new MemoryStream())
{
using (XomStreamWriter writer = new XomStreamWriter(ms))
{
writer.Skip(3);
writer.WriteCompressedInt(this.Message.Id);
writer.WriteCompressedInt(this.FEResourceID.Id);
writer.WriteByteArray(this.AllowedDuplacates);
int[] inputMappingIds = new int[this.InputMappings.Length];
for (int i = 0; i < inputMappingIds.Length; i++)
{
this.InputMappings[i].Save();
inputMappingIds[i] = this.InputMappings[i].containerId;
}
writer.WriteCompressedIntArray(inputMappingIds);
writer.WriteCompressedInt(this.Group);
ms.Seek(0x00, SeekOrigin.Begin);
mainContainer.SetData(ms.ToArray());
}
}
}
}
}

View File

@ -0,0 +1,43 @@
using LibW4M.Data.WeaponFactory;
using LibXom.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibW4M.Data.InputMapping
{
public class InputMappingCollective : SaveDataCollective
{
public InputMappingCollective(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
public override void Load()
{
int[] collective = mainContainer.Decompress();
for (int i = 0; i < collective[0]; i++)
{
InputEventMappingData eventMappingData = new InputEventMappingData(this.fileBelongs, this.fileBelongs.LookupContainerById(collective[i + 1]));
base.collectiveEntries.Add(eventMappingData);
}
}
public override void Save()
{
int len = this.Length;
int[] collective = new int[len + 1];
collective[0] = len;
for (int i = 0; i < len; i++)
{
InputEventMappingData eventMappingData = collectiveEntries[i] as InputEventMappingData;
if (eventMappingData is null) continue;
eventMappingData.Save();
collective[i + 1] = eventMappingData.mainContainer.Id;
}
mainContainer.CompressAndUpdate(collective);
}
}
}

View File

@ -1,4 +1,5 @@
using LibW4M.Data.Teams;
using LibW4M.Data.Highscores;
using LibW4M.Data.Teams;
using LibXom.Data;
using LibXom.Streams;
using System;
@ -11,8 +12,6 @@ namespace LibW4M.Data.Stats
{
public class StatsCollective : SaveDataCollective
{
private List<StatsContainerData> teamStats = new List<StatsContainerData>();
private List<XomString> teamNames = new List<XomString>();
public StatsCollective(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
@ -27,58 +26,40 @@ namespace LibW4M.Data.Stats
this.collectiveEntries.Add(stat);
}
int teamStatsStart = (1 + numStats) + 1;
int numTeamStats = decompressedCollective[(1 + numStats)];
for (int i = 0; i < numTeamStats; i++)
{
StatsContainerData teamStat = new StatsContainerData(this.fileBelongs, this.fileBelongs.LookupContainerById(decompressedCollective[i + (teamStatsStart)]));
this.teamStats.Add(teamStat);
}
int teamNamesStart = ((((1 + numStats) + 1) + numTeamStats) + 1);
int numTeamNames = decompressedCollective[(((1 + numStats) + 1) + numTeamStats)];
for (int i = 0; i < numTeamNames; i++)
{
this.teamNames.Add(this.fileBelongs.LookupStringFromId(decompressedCollective[i + (teamNamesStart)]));
}
}
public override void Save()
{
int numStats = this.collectiveEntries.Count;
int numTeamStats = this.teamStats.Count;
int numTeamNames = this.teamNames.Count;
// Once again Team17 stores multiple different types of data here
// a generic one i dunno whats for besides to make the filesize huge..
// and one for team stats ..
// to make thins easier im gonna abstract it away as two different collectives
// like i did on the highscores .
// Save regular stats
int statsStart = 1;
int[] collective = new int[(numStats + 1) + (numTeamStats + 1) + (numTeamNames + 1)];
collective[statsStart - 1] = numStats;
int[] decompressedCollective = mainContainer.Decompress();
int oldLen = decompressedCollective[0];
for(int i = 0; i < numStats; i++)
// Copy Team Stats data.
int[] teamStatsData = new int[(decompressedCollective.Length - (oldLen + 1))];
Array.ConstrainedCopy(decompressedCollective, oldLen + 1, teamStatsData, 0, teamStatsData.Length);
// Recalculate collective size and offsets
int sz = this.Length;
int[] collective = new int[(sz + 1) + (teamStatsData.Length)];
collective[0] = sz;
for (int i = 0; i < sz; i++)
{
this.collectiveEntries[i].Save();
collective[statsStart + i] = this.collectiveEntries[i].containerId;
StatsContainerData statsData = collectiveEntries[i] as StatsContainerData;
if (statsData is null) continue;
statsData.Save();
collective[i + 1] = statsData.mainContainer.Id;
}
// Save team stats
int teamStatsStart = (1 + numStats) + 1;
collective[teamStatsStart-1] = numTeamStats;
for (int i = 0; i < numTeamStats; i++)
{
this.teamStats[i].Save();
collective[teamStatsStart + i] = this.teamStats[i].containerId;
}
// Save team names
int teamNamesStart = ((1 + numStats) + (1 + numTeamStats) + 1);
collective[teamNamesStart - 1] = numTeamNames;
for (int i = 0; i < numTeamStats; i++)
{
collective[teamNamesStart + i] = this.teamNames[i].Id;
}
// Copy Team Stats data back to the collective.
Array.ConstrainedCopy(teamStatsData, 0, collective, sz + 1, teamStatsData.Length);
mainContainer.CompressAndUpdate(collective);
}

View File

@ -11,10 +11,20 @@ namespace LibW4M.Data.Stats
public class StatsContainerData : SaveDataEntry
{
int[] Values;
internal XomString? teamName;
public StatsContainerData(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
}
public override string FriendlyName
{
get
{
if (teamName.Value is not null) return teamName.Value;
return base.FriendlyName;
}
}
public override void Load()
{
using (XomStreamReader reader = new XomStreamReader(new MemoryStream(this.mainContainer.GetData())))

View File

@ -0,0 +1,96 @@
using LibW4M.Data.Highscores;
using LibXom.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibW4M.Data.Stats
{
public class TeamStatsCollective : SaveDataCollective
{
public List<XomString> TeamNames;
public TeamStatsCollective(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
{
TeamNames = new List<XomString>();
}
public override void Load()
{
// team stats are stored *after* the regular stats
int[] decompressedCollective = mainContainer.Decompress();
int statsLen = decompressedCollective[0];
int teamStatsStart = statsLen + 1;
int teamStatsLen = decompressedCollective[teamStatsStart];
// And then the team name this is associated with, is after that
int teamNamesStart = (statsLen + 1) + (teamStatsLen + 1);
int teamNamesLen = decompressedCollective[teamNamesStart];
for(int i = 0; i < teamNamesLen; i++)
TeamNames.Add(fileBelongs.LookupStringFromId(decompressedCollective[(teamNamesStart + 1) + i]));
for(int i = 0; i < teamStatsLen; i++)
{
StatsContainerData stats = new StatsContainerData(this.fileBelongs, fileBelongs.LookupContainerById(decompressedCollective[(teamStatsStart + 1) + i]));
if (i < TeamNames.Count)
stats.teamName = TeamNames[i];
this.collectiveEntries.Add(stats);
}
}
public override void Save()
{
// Decompress the collective
int[] decompressedCollective = mainContainer.Decompress();
// get total length of stats
int statsLen = decompressedCollective[0];
// Team Stats collective starts right *after* the stats collective.
int teamStatsStart = statsLen + 1;
int teamStatsLen = this.Length;
int teamNamesStart = (statsLen + 1) + (teamStatsLen + 1);
int teamNamesLen = this.TeamNames.Count;
// copy regular stats data from collective.
int[] statsData = new int[statsLen + 1];
Array.Copy(decompressedCollective, statsData, statsData.Length);
// copy regular stats data back to collective.
int[] newCollective = new int[statsData.Length + (1 + teamStatsLen) + (1 + TeamNames.Count)];
Array.Copy(statsData, newCollective, statsData.Length);
// populate team stats collective
newCollective[teamStatsStart] = teamStatsLen;
for(int i = 0; i < teamStatsLen; i++)
{
StatsContainerData teamStatsData = collectiveEntries[i] as StatsContainerData;
if (teamStatsData is null) continue;
teamStatsData.Save();
newCollective[teamStatsStart + i + 1] = teamStatsData.mainContainer.Id;
}
// add team names too
newCollective[teamStatsStart] = teamNamesLen;
for (int i = 0; i < teamNamesLen; i++)
newCollective[teamNamesStart + i + 1] = this.TeamNames[i].Id;
// Compress whole collective and update the underlying container.
mainContainer.CompressAndUpdate(newCollective);
}
}
}

View File

@ -32,6 +32,8 @@ namespace LibW4M.Data.WeaponFactory
for (int i = 0; i < len; i++)
{
WeaponStore store = collectiveEntries[i] as WeaponStore;
if (store is null) continue;
store.Save();
collective[i + 1] = store.mainContainer.Id;
}

View File

@ -1,5 +1,7 @@
using LibW4M.Data;
using LibW4M.Data.Awards;
using LibW4M.Data.Highscores;
using LibW4M.Data.InputMapping;
using LibW4M.Data.Schemes;
using LibW4M.Data.Stats;
using LibW4M.Data.Teams;
@ -32,7 +34,10 @@ namespace LibW4M
public SchemesCollective SchemesCollective;
public HighscoreCollective HighscoreCollective;
public StatsCollective StatsCollective;
public StatsCollective TeamStatsCollective;
public InputMappingCollective InputMappingCollective;
public TeamAwardsData TeamAwardsContainer;
public UnlockableItemData[] UnlockableItems
{
@ -79,8 +84,14 @@ namespace LibW4M
break;
case "PersistStats":
StatsCollective = new StatsCollective(this, containerResourceDetail.Value);
TeamStatsCollective = new StatsCollective(this, containerResourceDetail.Value);
break;
case "Awards":
TeamAwardsContainer = new TeamAwardsData(this, containerResourceDetail.Value);
break;
case "InputMapping":
InputMappingCollective = new InputMappingCollective(this, containerResourceDetail.Value);
break;
default:
// stupid hack; the only other option is manually hardcoding every unlockable item in the game
@ -96,7 +107,7 @@ namespace LibW4M
}
else
{
Console.Error.WriteLine("Unknown container resource: " + containerResourceDetail.Value);
Console.Error.WriteLine("Unknown container resource: " + containerResourceDetail.Name);
}
break;
@ -109,10 +120,19 @@ namespace LibW4M
XDataBank.Save();
WeaponFactoryCollective.Save();
// Save Teams, Highscores
TeamDataColective.Save();
HighscoreCollective.Save();
SchemesCollective.Save();
// Save Stats, TeamStats
StatsCollective.Save();
TeamStatsCollective.Save();
TeamAwardsContainer.Save();
InputMappingCollective.Save();
foreach (UnlockableItemData unlockableItem in UnlockableItems)
unlockableItem.Save();

View File

@ -40,6 +40,13 @@ namespace LibXom.Streams
{
return XomCompressor.ReadCompressedIntFromStream(xStream);
}
public byte[] ReadByteArray()
{
int len = this.ReadCompressedInt();
return ReadBytes(len);
}
public byte[] ReadBytes(int amt)
{
byte[] buffer = new byte[amt];

View File

@ -72,6 +72,13 @@ namespace LibXom.Streams
{
XomCompressor.compressIntAndWriteToStream(xStream, uncompressedInt);
}
public void WriteByteArray(byte[] data)
{
this.WriteCompressedInt(data.Length);
WriteBytes(data);
}
public void WriteBytes(byte[] bytes)
{
xStream.Write(bytes, 0, bytes.Length);

48
W4Gui/Main.Designer.cs generated
View File

@ -51,7 +51,7 @@ namespace W4Gui
this.unlockItemsTab = new System.Windows.Forms.TabPage();
this.unlockableItemsPanel = new W4Gui.Tabs.UnlockableItemsTab();
this.inputTab = new System.Windows.Forms.TabPage();
this.persistStatsTab = new System.Windows.Forms.TabPage();
this.statsTab = new System.Windows.Forms.TabPage();
this.awardsTab = new System.Windows.Forms.TabPage();
this.variablesTab = new System.Windows.Forms.TabPage();
this.variablesPage = new W4Gui.Tabs.VariablesTab.VariablesTabs();
@ -141,7 +141,7 @@ namespace W4Gui
this.mainTabControl.Controls.Add(this.highscoreTab);
this.mainTabControl.Controls.Add(this.unlockItemsTab);
this.mainTabControl.Controls.Add(this.inputTab);
this.mainTabControl.Controls.Add(this.persistStatsTab);
this.mainTabControl.Controls.Add(this.statsTab);
this.mainTabControl.Controls.Add(this.awardsTab);
this.mainTabControl.Controls.Add(this.variablesTab);
this.mainTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
@ -181,7 +181,7 @@ namespace W4Gui
this.teamTab.Location = new System.Drawing.Point(4, 24);
this.teamTab.Name = "teamTab";
this.teamTab.Padding = new System.Windows.Forms.Padding(3);
this.teamTab.Size = new System.Drawing.Size(192, 72);
this.teamTab.Size = new System.Drawing.Size(905, 509);
this.teamTab.TabIndex = 1;
this.teamTab.Text = "Teams";
this.teamTab.UseVisualStyleBackColor = true;
@ -191,7 +191,7 @@ namespace W4Gui
this.teamsPage.Dock = System.Windows.Forms.DockStyle.Fill;
this.teamsPage.Location = new System.Drawing.Point(3, 3);
this.teamsPage.Name = "teamsPage";
this.teamsPage.Size = new System.Drawing.Size(182, 62);
this.teamsPage.Size = new System.Drawing.Size(895, 499);
this.teamsPage.TabIndex = 0;
//
// schemeTab
@ -201,7 +201,7 @@ namespace W4Gui
this.schemeTab.Location = new System.Drawing.Point(4, 24);
this.schemeTab.Name = "schemeTab";
this.schemeTab.Padding = new System.Windows.Forms.Padding(3);
this.schemeTab.Size = new System.Drawing.Size(192, 72);
this.schemeTab.Size = new System.Drawing.Size(905, 509);
this.schemeTab.TabIndex = 3;
this.schemeTab.Text = "Schemes";
this.schemeTab.UseVisualStyleBackColor = true;
@ -211,7 +211,7 @@ namespace W4Gui
this.schemesPage.Dock = System.Windows.Forms.DockStyle.Fill;
this.schemesPage.Location = new System.Drawing.Point(3, 3);
this.schemesPage.Name = "schemesPage";
this.schemesPage.Size = new System.Drawing.Size(182, 62);
this.schemesPage.Size = new System.Drawing.Size(895, 499);
this.schemesPage.TabIndex = 0;
//
// highscoreTab
@ -221,7 +221,7 @@ namespace W4Gui
this.highscoreTab.Location = new System.Drawing.Point(4, 24);
this.highscoreTab.Name = "highscoreTab";
this.highscoreTab.Padding = new System.Windows.Forms.Padding(3);
this.highscoreTab.Size = new System.Drawing.Size(192, 72);
this.highscoreTab.Size = new System.Drawing.Size(905, 509);
this.highscoreTab.TabIndex = 2;
this.highscoreTab.Text = "Highscores";
this.highscoreTab.UseVisualStyleBackColor = true;
@ -231,7 +231,7 @@ namespace W4Gui
this.highscoresPage.Dock = System.Windows.Forms.DockStyle.Fill;
this.highscoresPage.Location = new System.Drawing.Point(3, 3);
this.highscoresPage.Name = "highscoresPage";
this.highscoresPage.Size = new System.Drawing.Size(182, 62);
this.highscoresPage.Size = new System.Drawing.Size(895, 499);
this.highscoresPage.TabIndex = 0;
//
// unlockItemsTab
@ -241,7 +241,7 @@ namespace W4Gui
this.unlockItemsTab.Location = new System.Drawing.Point(4, 24);
this.unlockItemsTab.Name = "unlockItemsTab";
this.unlockItemsTab.Padding = new System.Windows.Forms.Padding(3);
this.unlockItemsTab.Size = new System.Drawing.Size(192, 72);
this.unlockItemsTab.Size = new System.Drawing.Size(905, 509);
this.unlockItemsTab.TabIndex = 6;
this.unlockItemsTab.Text = "Unlockable Items";
this.unlockItemsTab.UseVisualStyleBackColor = true;
@ -251,7 +251,7 @@ namespace W4Gui
this.unlockableItemsPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.unlockableItemsPanel.Location = new System.Drawing.Point(3, 3);
this.unlockableItemsPanel.Name = "unlockableItemsPanel";
this.unlockableItemsPanel.Size = new System.Drawing.Size(182, 62);
this.unlockableItemsPanel.Size = new System.Drawing.Size(895, 499);
this.unlockableItemsPanel.TabIndex = 0;
//
// inputTab
@ -259,21 +259,21 @@ namespace W4Gui
this.inputTab.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.inputTab.Location = new System.Drawing.Point(4, 24);
this.inputTab.Name = "inputTab";
this.inputTab.Size = new System.Drawing.Size(192, 72);
this.inputTab.Size = new System.Drawing.Size(905, 509);
this.inputTab.TabIndex = 4;
this.inputTab.Text = "Input Settings";
this.inputTab.UseVisualStyleBackColor = true;
//
// persistStatsTab
// statsTab
//
this.persistStatsTab.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.persistStatsTab.Location = new System.Drawing.Point(4, 24);
this.persistStatsTab.Name = "persistStatsTab";
this.persistStatsTab.Padding = new System.Windows.Forms.Padding(3);
this.persistStatsTab.Size = new System.Drawing.Size(192, 72);
this.persistStatsTab.TabIndex = 7;
this.persistStatsTab.Text = "Persistant Statistics";
this.persistStatsTab.UseVisualStyleBackColor = true;
this.statsTab.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.statsTab.Location = new System.Drawing.Point(4, 24);
this.statsTab.Name = "statsTab";
this.statsTab.Padding = new System.Windows.Forms.Padding(3);
this.statsTab.Size = new System.Drawing.Size(905, 509);
this.statsTab.TabIndex = 7;
this.statsTab.Text = "Statistics";
this.statsTab.UseVisualStyleBackColor = true;
//
// awardsTab
//
@ -281,7 +281,7 @@ namespace W4Gui
this.awardsTab.Location = new System.Drawing.Point(4, 24);
this.awardsTab.Name = "awardsTab";
this.awardsTab.Padding = new System.Windows.Forms.Padding(3);
this.awardsTab.Size = new System.Drawing.Size(192, 72);
this.awardsTab.Size = new System.Drawing.Size(905, 509);
this.awardsTab.TabIndex = 8;
this.awardsTab.Text = "Awards";
this.awardsTab.UseVisualStyleBackColor = true;
@ -293,7 +293,7 @@ namespace W4Gui
this.variablesTab.Location = new System.Drawing.Point(4, 24);
this.variablesTab.Name = "variablesTab";
this.variablesTab.Padding = new System.Windows.Forms.Padding(3);
this.variablesTab.Size = new System.Drawing.Size(192, 72);
this.variablesTab.Size = new System.Drawing.Size(905, 509);
this.variablesTab.TabIndex = 5;
this.variablesTab.Text = "Variables";
this.variablesTab.UseVisualStyleBackColor = true;
@ -304,7 +304,7 @@ namespace W4Gui
this.variablesPage.Dock = System.Windows.Forms.DockStyle.Fill;
this.variablesPage.Location = new System.Drawing.Point(3, 3);
this.variablesPage.Name = "variablesPage";
this.variablesPage.Size = new System.Drawing.Size(182, 62);
this.variablesPage.Size = new System.Drawing.Size(895, 499);
this.variablesPage.TabIndex = 0;
//
// Main
@ -358,7 +358,7 @@ namespace W4Gui
private TabPage unlockItemsTab;
private VariablesTabs variablesPage;
private UnlockableItemsTab unlockableItemsPanel;
private TabPage persistStatsTab;
private TabPage statsTab;
private TabPage awardsTab;
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>