replace manual file parsing with SMAPI's APIs
This commit is contained in:
parent
9257605595
commit
2a5c17ff2f
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.AutoSpeed.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -12,8 +12,8 @@ namespace Omegasis.AutoSpeed
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The speed multiplier.</summary>
|
||||
private int Speed = 5;
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -24,13 +24,7 @@ namespace Omegasis.AutoSpeed
|
|||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
|
||||
|
||||
string configLocation = Path.Combine(helper.DirectoryPath, "AutoSpeed_Data.txt");
|
||||
if (!File.Exists(configLocation))
|
||||
this.Speed = 1;
|
||||
|
||||
this.LoadConfig();
|
||||
this.Monitor.Log("AutoSpeed Initialization Completed", LogLevel.Info);
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,32 +37,7 @@ namespace Omegasis.AutoSpeed
|
|||
private void GameEvents_UpdateTick(object sender, EventArgs e)
|
||||
{
|
||||
if (Context.IsPlayerFree)
|
||||
Game1.player.addedSpeed = this.Speed;
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "AutoSpeed_data.txt");
|
||||
if (!File.Exists(path))
|
||||
this.WriteConfig();
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.Speed = Convert.ToInt32(text[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "AutoSpeed_data.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: AutoSpeed Config:";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Player Added Speed:";
|
||||
text[3] = Speed.ToString();
|
||||
File.WriteAllLines(path, text);
|
||||
Game1.player.addedSpeed = this.Config.Speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AutoSpeed.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.AutoSpeed.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The added speed.</summary>
|
||||
public int Speed { get; set; } = 1;
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
3. Run the game using SMAPI.
|
||||
|
||||
## Usage
|
||||
Launch the game with the mod installed to generate the config file, then edit the
|
||||
`AutoSpeed_data.txt` to set the speed you want (higher values are faster).
|
||||
Launch the game with the mod installed to generate the config file, then edit the `config.json` to
|
||||
set the speed you want (higher values are faster).
|
||||
|
||||
## Versions
|
||||
1.0
|
||||
|
@ -23,4 +23,5 @@ Launch the game with the mod installed to generate the config file, then edit th
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.4:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.BillboardAnywhere.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -13,8 +12,8 @@ namespace Omegasis.BillboardAnywhere
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The key which shows the billboard menu.</summary>
|
||||
private string KeyBinding = "B";
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -24,7 +23,8 @@ namespace Omegasis.BillboardAnywhere
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
}
|
||||
|
||||
|
@ -32,50 +32,14 @@ namespace Omegasis.BillboardAnywhere
|
|||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when the presses a keyboard button.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
|
||||
{
|
||||
// load menu if key pressed
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.KeyBinding)
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.Config.KeyBinding)
|
||||
Game1.activeClickableMenu = new Billboard();
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "Billboard_Anywhere_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.KeyBinding = "B";
|
||||
this.WriteConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.KeyBinding = Convert.ToString(text[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Billboard_Anywhere_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: Billboard_Anywhere. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Key binding for opening the billboard anywhere. Press this key to do so";
|
||||
text[3] = this.KeyBinding;
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="BillboardAnywhere.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.BillboardAnywhere.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the billboard menu.</summary>
|
||||
public string KeyBinding { get; set; } = "B";
|
||||
}
|
||||
}
|
|
@ -9,8 +9,7 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
3. Run the game using SMAPI.
|
||||
|
||||
## Usage
|
||||
Press `B` while in-game to show the billboard menu. Edit the `Billboard_Anywhere_Config.txt` file
|
||||
to change the key.
|
||||
Press `B` while in-game to show the billboard menu. Edit the `config.json` file to change the key.
|
||||
|
||||
## Versions
|
||||
1.0
|
||||
|
@ -23,4 +22,5 @@ to change the key.
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.4:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Omegasis.BuildEndurance.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
|
@ -13,45 +14,30 @@ namespace Omegasis.BuildEndurance
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The mod settings and player data.</summary>
|
||||
/// <summary>The relative path for the current player's data file.</summary>
|
||||
private string DataFilePath => Path.Combine("data", $"{Constants.SaveFolderName}.json");
|
||||
|
||||
/// <summary>The absolute path for the current player's legacy data file.</summary>
|
||||
private string LegacyDataFilePath => Path.Combine(this.Helper.DirectoryPath, "PlayerData", $"BuildEndurance_data_{Game1.player.name}.txt");
|
||||
|
||||
/// <summary>The mod settings.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>The data for the current player.</summary>
|
||||
private PlayerData PlayerData;
|
||||
|
||||
/// <summary>Whether the player has been exhausted today.</summary>
|
||||
private bool WasExhausted;
|
||||
|
||||
/// <summary>Whether the player has collapsed today.</summary>
|
||||
private bool WasCollapsed;
|
||||
|
||||
/// <summary>The XP points needed to reach the next endurance level.</summary>
|
||||
private double ExpToNextLevel = 20;
|
||||
|
||||
/// <summary>The player's current endurance XP points.</summary>
|
||||
private double CurrentExp;
|
||||
|
||||
/// <summary>The player's current endurance level.</summary>
|
||||
private int CurrentLevel;
|
||||
|
||||
/// <summary>The stamina points to add to the player's base stamina due to their current endurance level.</summary>
|
||||
private int CurrentLevelStaminaBonus;
|
||||
|
||||
/// <summary>The initial stamina bonus to apply regardless of the player's endurance level, from the config file.</summary>
|
||||
private int BaseStaminaBonus;
|
||||
|
||||
/// <summary>Whether to reset all changes by the mod to the default values (i.e. start over).</summary>
|
||||
private bool ClearModEffects;
|
||||
|
||||
/// <summary>The player's original stamina value, excluding mod effects.</summary>
|
||||
private int OriginalStamina;
|
||||
|
||||
/// <summary>Whether the player recently gained XP for tool use.</summary>
|
||||
private bool HasRecentToolExp;
|
||||
|
||||
/// <summary>Whether the player was eating last time we checked.</summary>
|
||||
private bool WasEating;
|
||||
|
||||
/// <summary>The player's stamina last time they slept.</summary>
|
||||
private int NightlyStamina;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -60,18 +46,22 @@ namespace Omegasis.BuildEndurance
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
|
||||
GameEvents.OneSecondTick += this.GameEvents_OneSecondTick;
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
TimeEvents.AfterDayStarted += this.TimeEvents_AfterDayStarted;
|
||||
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
SaveEvents.BeforeSave += this.SaveEvents_BeforeSave;
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked once per second during a game update.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void GameEvents_OneSecondTick(object sender, EventArgs e)
|
||||
private void GameEvents_OneSecondTick(object sender, EventArgs e)
|
||||
{
|
||||
// nerf how quickly tool xp is gained (I hope)
|
||||
if (this.HasRecentToolExp)
|
||||
|
@ -81,28 +71,31 @@ namespace Omegasis.BuildEndurance
|
|||
/// <summary>The method invoked when the game updates (roughly 60 times per second).</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void GameEvents_UpdateTick(object sender, EventArgs e)
|
||||
private void GameEvents_UpdateTick(object sender, EventArgs e)
|
||||
{
|
||||
if (!Context.IsWorldReady)
|
||||
return;
|
||||
|
||||
// give XP when player finishes eating
|
||||
if (Game1.isEating)
|
||||
this.WasEating = true;
|
||||
else if (this.WasEating)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForEating;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForEating;
|
||||
this.WasEating = false;
|
||||
}
|
||||
|
||||
// give XP when player uses tool
|
||||
if (!this.HasRecentToolExp && Game1.player.usingTool)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForToolUse;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForToolUse;
|
||||
this.HasRecentToolExp = true;
|
||||
}
|
||||
|
||||
// give XP when exhausted
|
||||
if (!this.WasExhausted && Game1.player.exhausted)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForExhaustion;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForExhaustion;
|
||||
this.WasExhausted = true;
|
||||
this.Monitor.Log("The player is exhausted");
|
||||
}
|
||||
|
@ -110,7 +103,7 @@ namespace Omegasis.BuildEndurance
|
|||
// give XP when player stays up too late or collapses
|
||||
if (!this.WasCollapsed && Game1.farmerShouldPassOut)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForCollapsing;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForCollapsing;
|
||||
this.WasCollapsed = true;
|
||||
this.Monitor.Log("The player has collapsed!");
|
||||
}
|
||||
|
@ -119,195 +112,100 @@ namespace Omegasis.BuildEndurance
|
|||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
// initialise
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
|
||||
// grab initial stamina
|
||||
var player = Game1.player;
|
||||
if (this.OriginalStamina == 0)
|
||||
this.OriginalStamina = player.MaxStamina;
|
||||
|
||||
// set nightly stamina
|
||||
player.MaxStamina = this.NightlyStamina;
|
||||
if (this.NightlyStamina == 0)
|
||||
player.MaxStamina = this.BaseStaminaBonus + this.CurrentLevelStaminaBonus + this.OriginalStamina;
|
||||
// load player data
|
||||
this.MigrateLegacyData();
|
||||
this.PlayerData = this.Helper.ReadJsonFile<PlayerData>(this.DataFilePath) ?? new PlayerData();
|
||||
if (this.PlayerData.OriginalMaxStamina == 0)
|
||||
this.PlayerData.OriginalMaxStamina = Game1.player.MaxStamina;
|
||||
|
||||
// reset if needed
|
||||
if (this.ClearModEffects)
|
||||
player.MaxStamina = this.OriginalStamina;
|
||||
if (this.PlayerData.ClearModEffects)
|
||||
{
|
||||
Game1.player.MaxStamina = this.PlayerData.OriginalMaxStamina;
|
||||
this.PlayerData.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.PlayerData.CurrentExp = this.Config.CurrentExp;
|
||||
this.PlayerData.CurrentLevelStaminaBonus = 0;
|
||||
this.PlayerData.OriginalMaxStamina = Game1.player.MaxStamina;
|
||||
this.PlayerData.BaseStaminaBonus = 0;
|
||||
this.PlayerData.CurrentLevel = 0;
|
||||
this.PlayerData.ClearModEffects = false;
|
||||
}
|
||||
|
||||
// save config
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
// else apply stamina
|
||||
else
|
||||
{
|
||||
Game1.player.MaxStamina = this.PlayerData.NightlyStamina <= 0
|
||||
? this.PlayerData.BaseStaminaBonus + this.PlayerData.CurrentLevelStaminaBonus + this.PlayerData.OriginalMaxStamina
|
||||
: this.PlayerData.NightlyStamina;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when a new day starts.</summary>
|
||||
/// <summary>The method invoked just before the game is saved.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void TimeEvents_AfterDayStarted(object sender, EventArgs e)
|
||||
private void SaveEvents_BeforeSave(object sender, EventArgs e)
|
||||
{
|
||||
// reset data
|
||||
this.WasExhausted = false;
|
||||
this.WasCollapsed = false;
|
||||
|
||||
// update settings
|
||||
this.Monitor.Log(this.CurrentExp.ToString());
|
||||
this.UpdateClearSetting();
|
||||
this.Monitor.Log(this.ClearModEffects.ToString());
|
||||
// update player data
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForSleeping;
|
||||
if (this.PlayerData.OriginalMaxStamina == 0)
|
||||
this.PlayerData.OriginalMaxStamina = Game1.player.MaxStamina; //grab the initial stamina value
|
||||
|
||||
var player = Game1.player;
|
||||
this.CurrentExp += this.Config.ExpForSleeping;
|
||||
if (this.OriginalStamina == 0)
|
||||
this.OriginalStamina = player.MaxStamina; //grab the initial stamina value
|
||||
|
||||
if (this.ClearModEffects)
|
||||
if (this.PlayerData.CurrentLevel < this.Config.MaxLevel)
|
||||
{
|
||||
this.LoadClearSettings();
|
||||
player.MaxStamina = this.OriginalStamina;
|
||||
this.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.CurrentExp = this.Config.CurrentExp;
|
||||
this.CurrentLevelStaminaBonus = 0;
|
||||
this.OriginalStamina = player.MaxStamina;
|
||||
this.BaseStaminaBonus = 0;
|
||||
this.CurrentLevel = 0;
|
||||
}
|
||||
|
||||
if (!this.ClearModEffects && this.CurrentLevel < this.Config.MaxLevel)
|
||||
{
|
||||
while (this.CurrentExp >= this.ExpToNextLevel)
|
||||
while (this.PlayerData.CurrentExp >= this.PlayerData.ExpToNextLevel)
|
||||
{
|
||||
this.CurrentLevel += 1;
|
||||
this.CurrentExp = this.CurrentExp - this.ExpToNextLevel;
|
||||
this.ExpToNextLevel = (this.Config.ExpCurve * this.ExpToNextLevel);
|
||||
player.MaxStamina += this.Config.StaminaIncreasePerLevel;
|
||||
this.CurrentLevelStaminaBonus += this.Config.StaminaIncreasePerLevel;
|
||||
|
||||
this.PlayerData.CurrentLevel += 1;
|
||||
this.PlayerData.CurrentExp = this.PlayerData.CurrentExp - this.PlayerData.ExpToNextLevel;
|
||||
this.PlayerData.ExpToNextLevel = (this.Config.ExpCurve * this.PlayerData.ExpToNextLevel);
|
||||
Game1.player.MaxStamina += this.Config.StaminaIncreasePerLevel;
|
||||
this.PlayerData.CurrentLevelStaminaBonus += this.Config.StaminaIncreasePerLevel;
|
||||
}
|
||||
}
|
||||
this.ClearModEffects = false;
|
||||
this.NightlyStamina = Game1.player.maxStamina;
|
||||
this.WriteConfig();
|
||||
this.PlayerData.ClearModEffects = false;
|
||||
this.PlayerData.NightlyStamina = Game1.player.maxStamina;
|
||||
|
||||
// save data
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, this.PlayerData);
|
||||
}
|
||||
|
||||
/// <summary>Update the settings needed for <see cref="ClearModEffects"/> from the latest config file on disk.</summary>
|
||||
void LoadClearSettings()
|
||||
/// <summary>Migrate the legacy settings for the current player.</summary>
|
||||
private void MigrateLegacyData()
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
// skip if no legacy data or new data already exists
|
||||
if (!File.Exists(this.LegacyDataFilePath) || File.Exists(this.DataFilePath))
|
||||
return;
|
||||
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildEndurance_data_{Game1.player.name}.txt");
|
||||
if (!File.Exists(path))
|
||||
// migrate to new file
|
||||
try
|
||||
{
|
||||
this.Monitor.Log("Clear Data Loaded could not find the correct file.");
|
||||
string[] text = File.ReadAllLines(this.LegacyDataFilePath);
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, new PlayerData
|
||||
{
|
||||
CurrentLevel = Convert.ToInt32(text[3]),
|
||||
CurrentExp = Convert.ToDouble(text[5]),
|
||||
ExpToNextLevel = Convert.ToDouble(text[7]),
|
||||
BaseStaminaBonus = Convert.ToInt32(text[9]),
|
||||
CurrentLevelStaminaBonus = Convert.ToInt32(text[11]),
|
||||
ClearModEffects = Convert.ToBoolean(text[14]),
|
||||
OriginalMaxStamina = Convert.ToInt32(text[16]),
|
||||
NightlyStamina = Convert.ToInt32(text[18])
|
||||
});
|
||||
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalStamina = 0;
|
||||
this.BaseStaminaBonus = 0;
|
||||
FileInfo file = new FileInfo(this.LegacyDataFilePath);
|
||||
file.Delete();
|
||||
if (!file.Directory.EnumerateFiles().Any())
|
||||
file.Directory.Delete();
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.BaseStaminaBonus = Convert.ToInt32(text[9]);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
this.OriginalStamina = Convert.ToInt32(text[16]);
|
||||
this.Monitor.Log($"Error migrating data from the legacy 'PlayerData' folder for the current player. Technical details:\n {ex}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Update <see cref="ClearModEffects"/> based on the latest config file on disk.</summary>
|
||||
private void UpdateClearSetting()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildEndurance_data_{Game1.player.name}.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.Monitor.Log("Clear Data Loaded could not find the correct file.");
|
||||
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalStamina = 0;
|
||||
this.BaseStaminaBonus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
void LoadConfig()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildEndurance_data_{Game1.player.name}.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.CurrentExp = this.Config.CurrentExp;
|
||||
this.CurrentLevel = this.Config.CurrentLevel;
|
||||
this.BaseStaminaBonus = this.Config.BaseStaminaBonus;
|
||||
this.CurrentLevelStaminaBonus = this.Config.CurrentLevelStaminaBonus;
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalStamina = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.CurrentLevel = Convert.ToInt32(text[3]);
|
||||
this.ExpToNextLevel = Convert.ToDouble(text[7]);
|
||||
this.CurrentExp = Convert.ToDouble(text[5]);
|
||||
this.BaseStaminaBonus = Convert.ToInt32(text[9]);
|
||||
this.CurrentLevelStaminaBonus = Convert.ToInt32(text[11]);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
this.OriginalStamina = Convert.ToInt32(text[16]);
|
||||
this.NightlyStamina = Convert.ToInt32(text[18]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
void WriteConfig()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildEndurance_data_{Game1.player.name}.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: Build Endurance Data. Modification can cause errors. Edit at your own risk.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Player Current Level:";
|
||||
text[3] = this.CurrentLevel.ToString();
|
||||
|
||||
text[4] = "Player Current XP:";
|
||||
text[5] = this.CurrentExp.ToString();
|
||||
|
||||
text[6] = "Xp to next Level:";
|
||||
text[7] = this.ExpToNextLevel.ToString();
|
||||
|
||||
text[8] = "Initial Stam Bonus:";
|
||||
text[9] = this.BaseStaminaBonus.ToString();
|
||||
|
||||
text[10] = "Additional Stam Bonus:";
|
||||
text[11] = this.CurrentLevelStaminaBonus.ToString();
|
||||
|
||||
text[12] = "=======================================================================================";
|
||||
text[13] = "RESET ALL MOD EFFECTS? This will effective start you back at square 1. Also good if you want to remove this mod.";
|
||||
text[14] = this.ClearModEffects.ToString();
|
||||
text[15] = "OLD STAMINA AMOUNT: This is the initial value of the Player's Stamina before this mod took over.";
|
||||
text[16] = this.OriginalStamina.ToString();
|
||||
|
||||
text[17] = "Nightly Stamina Value: This is the value of the player's stamina that was saved when the player slept.";
|
||||
text[18] = this.NightlyStamina.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
</Compile>
|
||||
<Compile Include="BuildEndurance.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Framework\PlayerData.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
namespace Omegasis.BuildEndurance.Framework
|
||||
{
|
||||
/// <summary>The data for the current player.</summary>
|
||||
internal class PlayerData
|
||||
{
|
||||
/// <summary>The player's current endurance level.</summary>
|
||||
public int CurrentLevel { get; set; }
|
||||
|
||||
/// <summary>The player's current endurance XP points.</summary>
|
||||
public double CurrentExp { get; set; }
|
||||
|
||||
/// <summary>The XP points needed to reach the next endurance level.</summary>
|
||||
public double ExpToNextLevel { get; set; } = 20;
|
||||
|
||||
/// <summary>The initial stamina bonus to apply regardless of the player's endurance level, from the config file.</summary>
|
||||
public int BaseStaminaBonus { get; set; }
|
||||
|
||||
/// <summary>The stamina points to add to the player's base stamina due to their current endurance level.</summary>
|
||||
public int CurrentLevelStaminaBonus { get; set; }
|
||||
|
||||
/// <summary>Whether to reset all changes by the mod to the default values (i.e. start over).</summary>
|
||||
public bool ClearModEffects { get; set; }
|
||||
|
||||
/// <summary>The player's original max stamina value, excluding mod effects.</summary>
|
||||
public int OriginalMaxStamina { get; set; }
|
||||
|
||||
/// <summary>The player's stamina last time they slept.</summary>
|
||||
public int NightlyStamina { get; set; }
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
2. Install [this mod from Nexus mods](http://www.nexusmods.com/stardewvalley/mods/445).
|
||||
3. Run the game using SMAPI.
|
||||
|
||||
**NOTE:** to undo the mod's changes to your player, edit the `PlayerData\BuildEndurance_data_*.txt`
|
||||
file and change the "RESET ALL MOD EFFECTS?" field to `True`.
|
||||
**NOTE:** to undo the mod's changes to your player, edit the `data\*.json` file for your save and
|
||||
change the "ClearModEffects" field to `true`.
|
||||
|
||||
## Usage
|
||||
You'll automatically get XP for...
|
||||
|
@ -22,7 +22,7 @@ You'll automatically get XP for...
|
|||
|
||||
Get enough XP, and your endurance will level up.
|
||||
|
||||
Edit `BuildEnduranceConfig.json` to configure the mod settings.
|
||||
Edit `config.json` to configure the mod settings.
|
||||
|
||||
## Versions
|
||||
1.0
|
||||
|
@ -36,4 +36,6 @@ Edit `BuildEnduranceConfig.json` to configure the mod settings.
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config & data files.
|
||||
* Fixed issue where saves with the same name would overwrite each other's endurance level data.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Omegasis.BuildHealth.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
|
@ -13,29 +14,17 @@ namespace Omegasis.BuildHealth
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The relative path for the current player's data file.</summary>
|
||||
private string DataFilePath => Path.Combine("data", $"{Constants.SaveFolderName}.json");
|
||||
|
||||
/// <summary>The absolute path for the current player's legacy data file.</summary>
|
||||
private string LegacyDataFilePath => Path.Combine(this.Helper.DirectoryPath, "PlayerData", $"BuildHealth_data_{Game1.player.name}.txt");
|
||||
|
||||
/// <summary>The mod settings and player data.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>The XP points needed to reach the next level.</summary>
|
||||
private double ExpToNextLevel = 20;
|
||||
|
||||
/// <summary>The player's current XP points.</summary>
|
||||
private double CurrentExp;
|
||||
|
||||
/// <summary>The player's current level.</summary>
|
||||
private int CurrentLevel;
|
||||
|
||||
/// <summary>The health points to add to the player's base health due to their current level.</summary>
|
||||
private int CurrentLevelHealthBonus;
|
||||
|
||||
/// <summary>The initial health bonus to apply regardless of the player's level, from the config file.</summary>
|
||||
private int BaseHealthBonus;
|
||||
|
||||
/// <summary>Whether to reset all changes by the mod to the default values (i.e. start over).</summary>
|
||||
private bool ClearModEffects;
|
||||
|
||||
/// <summary>The player's original max health value, excluding mod effects.</summary>
|
||||
private int OriginalMaxHealth;
|
||||
/// <summary>The data for the current player.</summary>
|
||||
private PlayerData PlayerData;
|
||||
|
||||
/// <summary>Whether the player recently gained XP for tool use.</summary>
|
||||
private bool HasRecentToolExp;
|
||||
|
@ -59,16 +48,20 @@ namespace Omegasis.BuildHealth
|
|||
{
|
||||
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
|
||||
GameEvents.OneSecondTick += this.GameEvents_OneSecondTick;
|
||||
TimeEvents.AfterDayStarted += this.TimeEvents_AfterDayStarted;
|
||||
TimeEvents.AfterDayStarted += this.SaveEvents_BeforeSave;
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoaded;
|
||||
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked once per second during a game update.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void GameEvents_OneSecondTick(object sender, EventArgs e)
|
||||
private void GameEvents_OneSecondTick(object sender, EventArgs e)
|
||||
{
|
||||
// nerf how quickly tool xp is gained (I hope)
|
||||
if (this.HasRecentToolExp)
|
||||
|
@ -78,21 +71,24 @@ namespace Omegasis.BuildHealth
|
|||
/// <summary>The method invoked when the game updates (roughly 60 times per second).</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void GameEvents_UpdateTick(object sender, EventArgs e)
|
||||
private void GameEvents_UpdateTick(object sender, EventArgs e)
|
||||
{
|
||||
if (!Context.IsWorldReady)
|
||||
return;
|
||||
|
||||
// give XP when player finishes eating
|
||||
if (Game1.isEating)
|
||||
this.WasEating = true;
|
||||
else if (this.WasEating)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForEating;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForEating;
|
||||
this.WasEating = false;
|
||||
}
|
||||
|
||||
// give XP when player uses tool
|
||||
if (!this.HasRecentToolExp && Game1.player.usingTool)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForToolUse;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForToolUse;
|
||||
this.HasRecentToolExp = true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +96,7 @@ namespace Omegasis.BuildHealth
|
|||
var player = Game1.player;
|
||||
if (this.LastHealth > player.health)
|
||||
{
|
||||
this.CurrentExp += this.LastHealth - player.health;
|
||||
this.PlayerData.CurrentExp += this.LastHealth - player.health;
|
||||
this.LastHealth = player.health;
|
||||
}
|
||||
else if (this.LastHealth < player.health)
|
||||
|
@ -109,195 +105,107 @@ namespace Omegasis.BuildHealth
|
|||
// give XP when player stays up too late or collapses
|
||||
if (!this.WasCollapsed && Game1.farmerShouldPassOut)
|
||||
{
|
||||
this.CurrentExp += this.Config.ExpForCollapsing;
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForCollapsing;
|
||||
this.WasCollapsed = true;
|
||||
this.Monitor.Log("The player has collapsed!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The method invoked after a new day starts.</summary>
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void TimeEvents_AfterDayStarted(object sender, EventArgs e)
|
||||
private void SaveEvents_AfterLoaded(object sender, EventArgs e)
|
||||
{
|
||||
// load player data
|
||||
this.MigrateLegacyData();
|
||||
this.PlayerData = this.Helper.ReadJsonFile<PlayerData>(this.DataFilePath) ?? new PlayerData();
|
||||
if (this.PlayerData.OriginalMaxHealth == 0)
|
||||
this.PlayerData.OriginalMaxHealth = Game1.player.maxHealth;
|
||||
|
||||
// reset if needed
|
||||
if (this.PlayerData.ClearModEffects)
|
||||
{
|
||||
Game1.player.maxHealth = this.PlayerData.OriginalMaxHealth;
|
||||
this.PlayerData.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.PlayerData.CurrentExp = this.Config.CurrentExp;
|
||||
this.PlayerData.CurrentLevelHealthBonus = 0;
|
||||
this.PlayerData.OriginalMaxHealth = Game1.player.maxHealth;
|
||||
this.PlayerData.BaseHealthBonus = 0;
|
||||
this.PlayerData.CurrentLevel = 0;
|
||||
this.PlayerData.ClearModEffects = false;
|
||||
}
|
||||
|
||||
// else apply health
|
||||
else
|
||||
{
|
||||
Game1.player.maxHealth = this.PlayerData.BaseHealthBonus + this.PlayerData.CurrentLevelHealthBonus + this.PlayerData.OriginalMaxHealth;
|
||||
this.LastHealth = Game1.player.health;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The method invoked just before the game saves.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_BeforeSave(object sender, EventArgs e)
|
||||
{
|
||||
// reset data
|
||||
this.LastHealth = Game1.player.maxHealth;
|
||||
this.WasCollapsed = false;
|
||||
|
||||
// update settings
|
||||
this.UpdateClearSetting();
|
||||
|
||||
var player = Game1.player;
|
||||
this.CurrentExp += this.Config.ExpForSleeping;
|
||||
if (this.OriginalMaxHealth == 0)
|
||||
this.OriginalMaxHealth = player.maxHealth; //grab the initial Health value
|
||||
this.PlayerData.CurrentExp += this.Config.ExpForSleeping;
|
||||
if (this.PlayerData.OriginalMaxHealth == 0)
|
||||
this.PlayerData.OriginalMaxHealth = player.maxHealth; //grab the initial Health value
|
||||
|
||||
if (this.ClearModEffects)
|
||||
if (this.PlayerData.CurrentLevel < this.Config.MaxLevel)
|
||||
{
|
||||
this.LoadClearSettings();
|
||||
//This will run when the character goes to sleep. It will increase their sleeping skill.
|
||||
player.maxHealth = this.OriginalMaxHealth;
|
||||
this.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.CurrentExp = this.Config.CurrentExp;
|
||||
this.CurrentLevelHealthBonus = 0;
|
||||
this.OriginalMaxHealth = player.maxHealth;
|
||||
this.BaseHealthBonus = 0;
|
||||
this.CurrentLevel = 0;
|
||||
this.Monitor.Log("BuildHealth Reset!");
|
||||
}
|
||||
|
||||
if (!this.ClearModEffects && this.CurrentLevel < this.Config.MaxLevel)
|
||||
{
|
||||
while (this.CurrentExp >= this.ExpToNextLevel)
|
||||
while (this.PlayerData.CurrentExp >= this.PlayerData.ExpToNextLevel)
|
||||
{
|
||||
this.CurrentLevel += 1;
|
||||
this.CurrentExp = this.CurrentExp - this.ExpToNextLevel;
|
||||
this.ExpToNextLevel =
|
||||
(this.Config.ExpCurve * this.ExpToNextLevel);
|
||||
this.PlayerData.CurrentLevel += 1;
|
||||
this.PlayerData.CurrentExp = this.PlayerData.CurrentExp - this.PlayerData.ExpToNextLevel;
|
||||
this.PlayerData.ExpToNextLevel =
|
||||
(this.Config.ExpCurve * this.PlayerData.ExpToNextLevel);
|
||||
player.maxHealth += this.Config.HealthIncreasePerLevel;
|
||||
this.CurrentLevelHealthBonus += this.Config.HealthIncreasePerLevel;
|
||||
this.PlayerData.CurrentLevelHealthBonus += this.Config.HealthIncreasePerLevel;
|
||||
}
|
||||
}
|
||||
this.ClearModEffects = false;
|
||||
|
||||
this.WriteConfig();
|
||||
// save data
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, this.PlayerData);
|
||||
}
|
||||
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void SaveEvents_AfterLoaded(object sender, EventArgs e)
|
||||
/// <summary>Migrate the legacy settings for the current player.</summary>
|
||||
private void MigrateLegacyData()
|
||||
{
|
||||
// initialise
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
// skip if no legacy data or new data already exists
|
||||
if (!File.Exists(this.LegacyDataFilePath) || File.Exists(this.DataFilePath))
|
||||
return;
|
||||
|
||||
// grab initial health
|
||||
var player = Game1.player;
|
||||
if (this.OriginalMaxHealth == 0)
|
||||
this.OriginalMaxHealth = player.maxHealth;
|
||||
|
||||
// set max health
|
||||
player.maxHealth = this.BaseHealthBonus + this.CurrentLevelHealthBonus + this.OriginalMaxHealth;
|
||||
|
||||
// reset if needed
|
||||
if (this.ClearModEffects)
|
||||
// migrate to new file
|
||||
try
|
||||
{
|
||||
player.maxHealth = this.OriginalMaxHealth;
|
||||
this.Monitor.Log("BuildHealth Reset!");
|
||||
string[] text = File.ReadAllLines(this.LegacyDataFilePath);
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, new PlayerData
|
||||
{
|
||||
CurrentLevel = Convert.ToInt32(text[3]),
|
||||
CurrentExp = Convert.ToDouble(text[5]),
|
||||
ExpToNextLevel = Convert.ToDouble(text[7]),
|
||||
BaseHealthBonus = Convert.ToInt32(text[9]),
|
||||
CurrentLevelHealthBonus = Convert.ToInt32(text[11]),
|
||||
ClearModEffects = Convert.ToBoolean(text[14]),
|
||||
OriginalMaxHealth = Convert.ToInt32(text[16])
|
||||
});
|
||||
|
||||
FileInfo file = new FileInfo(this.LegacyDataFilePath);
|
||||
file.Delete();
|
||||
if (!file.Directory.EnumerateFiles().Any())
|
||||
file.Directory.Delete();
|
||||
}
|
||||
|
||||
// save config
|
||||
this.LastHealth = Game1.player.maxHealth;
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
}
|
||||
|
||||
/// <summary>Update the settings needed for <see cref="ClearModEffects"/> from the latest config file on disk.</summary>
|
||||
void LoadClearSettings()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildHealth_data_{Game1.player.name}.txt");
|
||||
if (!File.Exists(path))
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalMaxHealth = 0;
|
||||
this.BaseHealthBonus = 0;
|
||||
this.Monitor.Log($"Error migrating data from the legacy 'PlayerData' folder for the current player. Technical details:\n {ex}", LogLevel.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.BaseHealthBonus = Convert.ToInt32(text[9]);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
this.OriginalMaxHealth = Convert.ToInt32(text[16]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Update <see cref="ClearModEffects"/> based on the latest config file on disk.</summary>
|
||||
private void UpdateClearSetting()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildHealth_data_{Game1.player.name}.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalMaxHealth = 0;
|
||||
this.BaseHealthBonus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildHealth_data_{Game1.player.name}.txr");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.ExpToNextLevel = this.Config.ExpToNextLevel;
|
||||
this.CurrentExp = this.Config.CurrentExp;
|
||||
this.CurrentLevel = this.Config.CurrentLevel;
|
||||
this.BaseHealthBonus = this.Config.BaseHealthBonus;
|
||||
this.CurrentLevelHealthBonus = this.Config.CurrentLevelHealthBonus;
|
||||
this.ClearModEffects = false;
|
||||
this.OriginalMaxHealth = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.CurrentLevel = Convert.ToInt32(text[3]);
|
||||
this.ExpToNextLevel = Convert.ToDouble(text[7]);
|
||||
this.CurrentExp = Convert.ToDouble(text[5]);
|
||||
this.BaseHealthBonus = Convert.ToInt32(text[9]);
|
||||
this.CurrentLevelHealthBonus = Convert.ToInt32(text[11]);
|
||||
this.ClearModEffects = Convert.ToBoolean(text[14]);
|
||||
this.OriginalMaxHealth = Convert.ToInt32(text[16]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
if (!Directory.Exists(Path.Combine(Helper.DirectoryPath, "PlayerData")))
|
||||
Directory.CreateDirectory(Path.Combine(Helper.DirectoryPath, "PlayerData"));
|
||||
|
||||
string path = Path.Combine(Helper.DirectoryPath, "PlayerData", $"BuildHealth_data_{Game1.player.name}.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: Build Health Data. Modification can cause errors. Edit at your own risk.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Player Current Level:";
|
||||
text[3] = this.CurrentLevel.ToString();
|
||||
|
||||
text[4] = "Player Current XP:";
|
||||
text[5] = this.CurrentExp.ToString();
|
||||
|
||||
text[6] = "Xp to next Level:";
|
||||
text[7] = this.ExpToNextLevel.ToString();
|
||||
|
||||
text[8] = "Initial Health Bonus:";
|
||||
text[9] = this.BaseHealthBonus.ToString();
|
||||
|
||||
text[10] = "Additional Health Bonus:";
|
||||
text[11] = this.CurrentLevelHealthBonus.ToString();
|
||||
|
||||
text[12] = "=======================================================================================";
|
||||
text[13] = "RESET ALL MOD EFFECTS? This will effective start you back at square 1. Also good if you want to remove this mod.";
|
||||
text[14] = this.ClearModEffects.ToString();
|
||||
text[15] = "OLD Health AMOUNT: This is the initial value of the Player's Health before this mod took over.";
|
||||
text[16] = this.OriginalMaxHealth.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
</Compile>
|
||||
<Compile Include="BuildHealth.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Framework\PlayerData.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
namespace Omegasis.BuildHealth.Framework
|
||||
{
|
||||
/// <summary>The data for the current player.</summary>
|
||||
internal class PlayerData
|
||||
{
|
||||
/// <summary>The player's current endurance level.</summary>
|
||||
public int CurrentLevel { get; set; }
|
||||
|
||||
/// <summary>The player's current endurance XP points.</summary>
|
||||
public double CurrentExp { get; set; }
|
||||
|
||||
/// <summary>The XP points needed to reach the next endurance level.</summary>
|
||||
public double ExpToNextLevel { get; set; } = 20;
|
||||
|
||||
/// <summary>The initial health bonus to apply regardless of the player's endurance level, from the config file.</summary>
|
||||
public int BaseHealthBonus { get; set; }
|
||||
|
||||
/// <summary>The health points to add to the player's base health due to their current endurance level.</summary>
|
||||
public int CurrentLevelHealthBonus { get; set; }
|
||||
|
||||
/// <summary>Whether to reset all changes by the mod to the default values (i.e. start over).</summary>
|
||||
public bool ClearModEffects { get; set; }
|
||||
|
||||
/// <summary>The player's original maximum health value, excluding mod effects.</summary>
|
||||
public int OriginalMaxHealth { get; set; }
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
2. Install [this mod from Nexus mods](http://www.nexusmods.com/stardewvalley/mods/445).
|
||||
3. Run the game using SMAPI.
|
||||
|
||||
**NOTE:** to undo the mod's changes to your player, edit the `PlayerData\BuildEndurance_data_*.txt`
|
||||
file and change the "RESET ALL MOD EFFECTS?" field to `True`.
|
||||
**NOTE:** to undo the mod's changes to your player, edit the `data\*.json` file for your save and
|
||||
change the "ClearModEffects" field to `true`.
|
||||
|
||||
## Usage
|
||||
You'll automatically get XP for...
|
||||
|
@ -23,7 +23,7 @@ You'll automatically get XP for...
|
|||
|
||||
Get enough XP, and your health will level up.
|
||||
|
||||
Edit `BuildHealthConfig.json` to configure the mod settings.
|
||||
Edit `config.json` to configure the mod settings.
|
||||
|
||||
## Versions
|
||||
1.0
|
||||
|
@ -37,4 +37,6 @@ Edit `BuildHealthConfig.json` to configure the mod settings.
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config & data files.
|
||||
* Fixed issue where saves with the same name would overwrite each other's endurance level data.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.BuyBackCollectables.Framework;
|
||||
using Omegasis.BuyBackCollectables.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -13,11 +11,8 @@ namespace Omegasis.BuyBackCollectables
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
private string KeyBinding = "B";
|
||||
|
||||
/// <summary>The multiplier applied to the cost of buying back a collectable.</summary>
|
||||
private double CostMultiplier = 3.0;
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -27,7 +22,8 @@ namespace Omegasis.BuyBackCollectables
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
}
|
||||
|
||||
|
@ -35,55 +31,13 @@ namespace Omegasis.BuyBackCollectables
|
|||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when the presses a keyboard button.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
public void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
|
||||
{
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.KeyBinding)
|
||||
Game1.activeClickableMenu = new BuyBackMenu(this.CostMultiplier);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
//loads the data to the variables upon loading the game.
|
||||
string path = Path.Combine(Helper.DirectoryPath, "BuyBack_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.KeyBinding = "B";
|
||||
this.CostMultiplier = 3.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.KeyBinding = Convert.ToString(text[3]);
|
||||
this.CostMultiplier = Convert.ToDouble(text[5]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
//write all of my info to a text file.
|
||||
string path = Path.Combine(Helper.DirectoryPath, "BuyBack_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: Buy Back Collections. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Key binding";
|
||||
text[3] = this.KeyBinding;
|
||||
text[4] = "Collectables Multiplier Cost: Sell Value * value listed below";
|
||||
text[5] = this.CostMultiplier.ToString();
|
||||
File.WriteAllLines(path, text);
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.Config.KeyBinding)
|
||||
Game1.activeClickableMenu = new BuyBackMenu(this.Config.CostMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="BuyBackCollectables.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Framework\BuyBackMenu.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace Omegasis.BuyBackCollectables.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
public string KeyBinding { get; set; } = "B";
|
||||
|
||||
/// <summary>The multiplier applied to the cost of buying back a collectable.</summary>
|
||||
public double CostMultiplier { get; set; } = 3.0;
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
3. Run the game using SMAPI.
|
||||
|
||||
## Usage
|
||||
Press `B` to open the buy-collectibles menu. Edit `BuildHealthConfig.json` to change the key or the
|
||||
price markup.
|
||||
Press `B` to open the buy-collectibles menu. Edit `config.json` to change the key or the price
|
||||
markup.
|
||||
|
||||
## Versions
|
||||
1.0:
|
||||
|
@ -31,4 +31,5 @@ price markup.
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.4:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Omegasis.CustomShopsRedux.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -31,17 +32,17 @@ namespace Omegasis.CustomShopsRedux
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>The prices for the items to list.</summary>
|
||||
private readonly Dictionary<Item, int[]> ListPrices = new Dictionary<Item, int[]>();
|
||||
|
||||
/// <summary>The folder path containing shop data files.</summary>
|
||||
private string DataPath;
|
||||
|
||||
/// <summary>The configured shop options.</summary>
|
||||
private readonly List<string> Options = new List<string>();
|
||||
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
private string KeyBinding = "U";
|
||||
/// <summary>The folder path containing shop data files.</summary>
|
||||
private string DataPath => Path.Combine(this.Helper.DirectoryPath, "Custom_Shops");
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -51,7 +52,8 @@ namespace Omegasis.CustomShopsRedux
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterDayStarted;
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
}
|
||||
|
||||
|
@ -59,58 +61,20 @@ namespace Omegasis.CustomShopsRedux
|
|||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked after a new day starts.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterDayStarted(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when the presses a keyboard button.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
|
||||
{
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.KeyBinding)
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.Config.KeyBinding)
|
||||
this.OpenSelectFileMenu();
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
this.DataPath = Path.Combine(this.Helper.DirectoryPath, "Custom_Shops");
|
||||
Directory.CreateDirectory(this.DataPath);
|
||||
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "Custom_Shop_Redux_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
this.KeyBinding = "U";
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.KeyBinding = Convert.ToString(text[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "Custom_Shop_Redux_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: Custom_Shop_Redux. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Key binding for saving anywhere. Press this key to save anywhere!";
|
||||
text[3] = this.KeyBinding;
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Open the menu which lets the player choose a file.</summary>
|
||||
private void OpenSelectFileMenu()
|
||||
{
|
||||
// get mod folder
|
||||
Directory.CreateDirectory(this.DataPath);
|
||||
DirectoryInfo modFolder = new DirectoryInfo(this.DataPath);
|
||||
this.Monitor.Log(modFolder.FullName);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="CustomShopsRedux.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.CustomShopsRedux.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
public string KeyBinding { get; set; } = "U";
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ Make a custom shop by copying & editing one of the included custom shop template
|
|||
[Custom Shops Creation Tool](https://myscccd-my.sharepoint.com/personal/0703280_my_scccd_edu/_layouts/15/guestaccess.aspx?guestaccesstoken=ZYxG9Cs8S0q%2bxCVV3fEnc8MI4SfVfe07919rhFUhRiA%3d&docid=0e51dae1da2eb43988f77f5c54ec3ee58)
|
||||
(see [demo video](https://youtu.be/bSvNTZmgeZE)).
|
||||
|
||||
You can access the custom shops by pressing `U` in-game (configurable via `Custom_Shop_Redux_Config.txt`).
|
||||
You can access the custom shops by pressing `U` in-game (configurable via `config.json`).
|
||||
|
||||
Supported item types:
|
||||
|
||||
|
@ -60,4 +60,5 @@ Supported item types:
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.DailyQuestAnywhere.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -13,8 +12,8 @@ namespace Omegasis.DailyQuestAnywhere
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
private string KeyBinding = "H";
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -24,7 +23,8 @@ namespace Omegasis.DailyQuestAnywhere
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
}
|
||||
|
||||
|
@ -32,49 +32,13 @@ namespace Omegasis.DailyQuestAnywhere
|
|||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when the presses a keyboard button.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
|
||||
{
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.KeyBinding)
|
||||
if (Context.IsPlayerFree && e.KeyPressed.ToString() == this.Config.KeyBinding)
|
||||
Game1.activeClickableMenu = new Billboard(true);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "DailyQuest_Anywhere_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
this.KeyBinding = "H";
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.KeyBinding = Convert.ToString(text[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "DailyQuest_Anywhere_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: DailyQuest_Anywhere Info. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Key binding for opening the billboard for quests anywhere. Press this key to do so";
|
||||
text[3] = this.KeyBinding;
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="DailyQuestAnywhere.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.DailyQuestAnywhere.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
public string KeyBinding { get; set; } = "H";
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
3. Run the game using SMAPI.
|
||||
|
||||
## Usage
|
||||
Press `H` to open the daily quest menu. Edit `DailyQuest_Anywhere_Config.txt` to change the key.
|
||||
Press `H` to open the daily quest menu. Edit `config.json` to change the key.
|
||||
|
||||
## Versions
|
||||
1.0:
|
||||
|
@ -22,4 +22,5 @@ Press `H` to open the daily quest menu. Edit `DailyQuest_Anywhere_Config.txt` to
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.4:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.HappyBirthday.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
public string KeyBinding { get; set; } = "O";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace Omegasis.HappyBirthday.Framework
|
||||
{
|
||||
/// <summary>The data for the current player.</summary>
|
||||
internal class PlayerData
|
||||
{
|
||||
/// <summary>The player's current birthday day.</summary>
|
||||
public int BirthdayDay;
|
||||
|
||||
/// <summary>The player's current birthday season.</summary>
|
||||
public string BirthdaySeason;
|
||||
}
|
||||
}
|
|
@ -18,11 +18,20 @@ namespace Omegasis.HappyBirthday
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The key which shows the menu.</summary>
|
||||
private string KeyBinding = "O";
|
||||
/// <summary>The relative path for the current player's data file.</summary>
|
||||
private string DataFilePath => Path.Combine("data", $"{Constants.SaveFolderName}.json");
|
||||
|
||||
/// <summary>The absolute path for the current player's legacy data file.</summary>
|
||||
private string LegacyDataFilePath => Path.Combine(this.Helper.DirectoryPath, "Player_Birthdays", $"HappyBirthday_{Game1.player.name}.txt");
|
||||
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>The data for the current player.</summary>
|
||||
private PlayerData PlayerData;
|
||||
|
||||
/// <summary>Whether the player has chosen a birthday.</summary>
|
||||
private bool HasChosenBirthday;
|
||||
private bool HasChosenBirthday => !string.IsNullOrEmpty(this.PlayerData.BirthdaySeason) && this.PlayerData.BirthdayDay != 0;
|
||||
|
||||
/// <summary>The queue of villagers who haven't given a gift yet.</summary>
|
||||
private List<string> VillagerQueue;
|
||||
|
@ -38,18 +47,6 @@ namespace Omegasis.HappyBirthday
|
|||
//private Dictionary<string, Dialogue> Dialogue;
|
||||
//private bool SeenEvent;
|
||||
|
||||
/// <summary>The name of the folder containing birthday data files.</summary>
|
||||
private readonly string FolderName = "Player_Birthdays";
|
||||
|
||||
/// <summary>The full path to the folder containing birthday data files.</summary>
|
||||
private string BirthdayFolderPath;
|
||||
|
||||
/// <summary>The player's current birthday day.</summary>
|
||||
public int BirthdayDay;
|
||||
|
||||
/// <summary>The player's current birthday season.</summary>
|
||||
public string BirthdaySeason;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -58,17 +55,16 @@ namespace Omegasis.HappyBirthday
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
TimeEvents.AfterDayStarted += this.TimeEvents_AfterDayStarted;
|
||||
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
SaveEvents.BeforeSave += this.SaveEvents_BeforeSave;
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
|
||||
this.VillagerQueue = new List<string>();
|
||||
this.PossibleBirthdayGifts = new List<Item>();
|
||||
this.BirthdayFolderPath = Path.Combine(Helper.DirectoryPath, this.FolderName);
|
||||
|
||||
if (!Directory.Exists(this.BirthdayFolderPath))
|
||||
Directory.CreateDirectory(this.BirthdayFolderPath);
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,9 +76,6 @@ namespace Omegasis.HappyBirthday
|
|||
/// <param name="e">The event data.</param>
|
||||
private void TimeEvents_AfterDayStarted(object sender, EventArgs e)
|
||||
{
|
||||
if (this.HasChosenBirthday)
|
||||
this.WriteBirthday();
|
||||
this.WriteConfig();
|
||||
this.CheckedForBirthday = false;
|
||||
}
|
||||
|
||||
|
@ -92,8 +85,8 @@ namespace Omegasis.HappyBirthday
|
|||
private void ControlEvents_KeyPressed(object sender, EventArgsKeyPressed e)
|
||||
{
|
||||
// show birthday selection menu
|
||||
if (Context.IsPlayerFree && !this.HasChosenBirthday && e.KeyPressed.ToString() == this.KeyBinding)
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.BirthdaySeason, this.BirthdayDay, this.SetBirthday);
|
||||
if (Context.IsPlayerFree && !this.HasChosenBirthday && e.KeyPressed.ToString() == this.Config.KeyBinding)
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.PlayerData.BirthdaySeason, this.PlayerData.BirthdayDay, this.SetBirthday);
|
||||
}
|
||||
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
|
@ -101,12 +94,21 @@ namespace Omegasis.HappyBirthday
|
|||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadBirthday();
|
||||
this.LoadConfig();
|
||||
this.MigrateLegacyData();
|
||||
this.PlayerData = this.Helper.ReadJsonFile<PlayerData>(this.DataFilePath) ?? new PlayerData();
|
||||
//this.SeenEvent = false;
|
||||
//this.Dialogue = new Dictionary<string, Dialogue>();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked just before the game updates the saves.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_BeforeSave(object sender, EventArgs e)
|
||||
{
|
||||
if (this.HasChosenBirthday)
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, this.PlayerData);
|
||||
}
|
||||
|
||||
/// <summary>The method invoked when the game updates (roughly 60 times per second).</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
|
@ -159,9 +161,9 @@ namespace Omegasis.HappyBirthday
|
|||
}
|
||||
|
||||
// ask for birthday date
|
||||
if (string.IsNullOrEmpty(this.BirthdaySeason) || this.BirthdayDay == 0)
|
||||
if (!this.HasChosenBirthday)
|
||||
{
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.BirthdaySeason, this.BirthdayDay, this.SetBirthday);
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.PlayerData.BirthdaySeason, this.PlayerData.BirthdayDay, this.SetBirthday);
|
||||
this.CheckedForBirthday = false;
|
||||
}
|
||||
}
|
||||
|
@ -223,14 +225,6 @@ namespace Omegasis.HappyBirthday
|
|||
Game1.player.addItemByMenuIfNecessaryElseHoldUp(this.BirthdayGiftToReceive);
|
||||
this.BirthdayGiftToReceive = null;
|
||||
}
|
||||
|
||||
// update settings
|
||||
if (!this.HasChosenBirthday && !string.IsNullOrEmpty(this.BirthdaySeason) && this.BirthdayDay != 0)
|
||||
{
|
||||
this.WriteConfig();
|
||||
this.WriteBirthday();
|
||||
this.HasChosenBirthday = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the player's birtday/</summary>
|
||||
|
@ -238,8 +232,8 @@ namespace Omegasis.HappyBirthday
|
|||
/// <param name="day">The birthday day.</param>
|
||||
private void SetBirthday(string season, int day)
|
||||
{
|
||||
this.BirthdaySeason = season;
|
||||
this.BirthdayDay = day;
|
||||
this.PlayerData.BirthdaySeason = season;
|
||||
this.PlayerData.BirthdayDay = day;
|
||||
}
|
||||
|
||||
/// <summary>Reset the queue of villager names.</summary>
|
||||
|
@ -495,63 +489,36 @@ namespace Omegasis.HappyBirthday
|
|||
private bool IsBirthday()
|
||||
{
|
||||
return
|
||||
this.BirthdayDay == Game1.dayOfMonth
|
||||
&& this.BirthdaySeason == Game1.currentSeason;
|
||||
this.PlayerData.BirthdayDay == Game1.dayOfMonth
|
||||
&& this.PlayerData.BirthdaySeason == Game1.currentSeason;
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
/// <summary>Migrate the legacy settings for the current player.</summary>
|
||||
private void MigrateLegacyData()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "HappyBirthday_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
this.KeyBinding = "O";
|
||||
else
|
||||
// skip if no legacy data or new data already exists
|
||||
if (!File.Exists(this.LegacyDataFilePath) || File.Exists(this.DataFilePath))
|
||||
return;
|
||||
|
||||
// migrate to new file
|
||||
try
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.KeyBinding = Convert.ToString(text[3]);
|
||||
string[] text = File.ReadAllLines(this.LegacyDataFilePath);
|
||||
this.Helper.WriteJsonFile(this.DataFilePath, new PlayerData
|
||||
{
|
||||
BirthdaySeason = text[3],
|
||||
BirthdayDay = Convert.ToInt32(text[5])
|
||||
});
|
||||
|
||||
FileInfo file = new FileInfo(this.LegacyDataFilePath);
|
||||
file.Delete();
|
||||
if (!file.Directory.EnumerateFiles().Any())
|
||||
file.Directory.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "HappyBirthday_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: HappyBirthday Info. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Key binding for opening the birthday menu. Press this key to do so.";
|
||||
text[3] = this.KeyBinding;
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Load the player's birthday from the config file.</summary>
|
||||
private void LoadBirthday()
|
||||
{
|
||||
string path = Path.Combine(this.BirthdayFolderPath, $"HappyBirthday_{Game1.player.name}.txt");
|
||||
if (File.Exists(path))
|
||||
catch (Exception ex)
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.BirthdaySeason = Convert.ToString(text[3]);
|
||||
this.BirthdayDay = Convert.ToInt32(text[5]);
|
||||
this.Monitor.Log($"Error migrating data from the legacy 'Player_Birthdays' folder for the current player. Technical details:\n {ex}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Write the player's birthday to the config file.</summary>
|
||||
private void WriteBirthday()
|
||||
{
|
||||
string path = Path.Combine(this.BirthdayFolderPath, $"HappyBirthday_{Game1.player.name}.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player Info: Modifying these values could be considered cheating or an exploit. Edit at your own risk.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Player's Birthday Season";
|
||||
text[3] = this.BirthdaySeason;
|
||||
text[4] = "Player's Birthday Date";
|
||||
text[5] = this.BirthdayDay.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\BirthdayMenu.cs" />
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="Framework\PlayerData.cs" />
|
||||
<Compile Include="HappyBirthday.cs" />
|
||||
<Compile Include="Framework\Messages.cs" />
|
||||
<Compile Include="Framework\ObjectUtility.cs" />
|
||||
|
|
|
@ -54,4 +54,6 @@ change based on your friendship with them. Check your mailbox for letters from y
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config & data files.
|
||||
* Fixed issue where saves with the same name would overwrite each other's birthdays.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
namespace Omegasis.MoreRain.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's spring.</summary>
|
||||
public int SpringRainChance { get; set; } = 15;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's spring.</summary>
|
||||
public int SpringThunderChance { get; set; } = 5;
|
||||
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's summer.</summary>
|
||||
public int SummerRainChance { get; set; } = 5;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's summer.</summary>
|
||||
public int SummerThunderChance { get; set; } = 10;
|
||||
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's fall.</summary>
|
||||
public int FallRainChance { get; set; } = 15;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's fall.</summary>
|
||||
public int FallThunderChance { get; set; } = 5;
|
||||
|
||||
/// <summary>The chance out of 100 that it will snow tomorrow if it's winter.</summary>
|
||||
public int WinterSnowChance { get; set; } = 15;
|
||||
|
||||
/// <summary>Whether to suppress verbose logging.</summary>
|
||||
public bool SuppressLog { get; set; } = true;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Omegasis.MoreRain.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -16,29 +16,8 @@ namespace Omegasis.MoreRain
|
|||
/// <summary>The weathers that can be safely overridden.</summary>
|
||||
private readonly HashSet<int> NormalWeathers = new HashSet<int> { Game1.weather_sunny, Game1.weather_rain, Game1.weather_lightning, Game1.weather_debris, Game1.weather_snow };
|
||||
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's spring.</summary>
|
||||
private int SpringRainChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's spring.</summary>
|
||||
private int SpringThunderChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's summer.</summary>
|
||||
private int SummerRainChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's summer.</summary>
|
||||
private int SummerThunderChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will rain tomorrow if it's fall.</summary>
|
||||
private int FallRainChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will storm tomorrow if it's fall.</summary>
|
||||
private int FallThunderChance;
|
||||
|
||||
/// <summary>The chance out of 100 that it will snow tomorrow if it's winter.</summary>
|
||||
private int WinterSnowChance;
|
||||
|
||||
/// <summary>Whether to suppress verbose logging.</summary>
|
||||
private bool SuppressLog;
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -48,9 +27,10 @@ namespace Omegasis.MoreRain
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
SaveEvents.BeforeSave += this.SaveEvents_BeforeSave;
|
||||
this.LoadConfig();
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +75,7 @@ namespace Omegasis.MoreRain
|
|||
{
|
||||
case "spring":
|
||||
// set rain
|
||||
if (chance <= this.SpringRainChance)
|
||||
if (chance <= this.Config.SpringRainChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_rain;
|
||||
this.VerboseLog("It will rain tomorrow.");
|
||||
|
@ -109,7 +89,7 @@ namespace Omegasis.MoreRain
|
|||
// set storm
|
||||
if (Game1.weatherForTomorrow == Game1.weather_rain)
|
||||
{
|
||||
if (chance <= this.SpringThunderChance)
|
||||
if (chance <= this.Config.SpringThunderChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_lightning;
|
||||
this.VerboseLog("It will be stormy tomorrow.");
|
||||
|
@ -124,7 +104,7 @@ namespace Omegasis.MoreRain
|
|||
|
||||
case "summer":
|
||||
// set rain
|
||||
if (chance <= this.SummerRainChance)
|
||||
if (chance <= this.Config.SummerRainChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_rain;
|
||||
this.VerboseLog("It will rain tomorrow.");
|
||||
|
@ -138,7 +118,7 @@ namespace Omegasis.MoreRain
|
|||
// set storm
|
||||
if (Game1.weatherForTomorrow == Game1.weather_rain)
|
||||
{
|
||||
if (chance <= this.SummerThunderChance)
|
||||
if (chance <= this.Config.SummerThunderChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_lightning;
|
||||
this.VerboseLog("It will be stormy tomorrow.");
|
||||
|
@ -154,7 +134,7 @@ namespace Omegasis.MoreRain
|
|||
case "fall":
|
||||
case "autumn":
|
||||
// set rain
|
||||
if (chance <= this.FallRainChance)
|
||||
if (chance <= this.Config.FallRainChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_rain;
|
||||
this.VerboseLog("It will rain tomorrow.");
|
||||
|
@ -168,7 +148,7 @@ namespace Omegasis.MoreRain
|
|||
// set storm
|
||||
if (Game1.weatherForTomorrow == Game1.weather_rain)
|
||||
{
|
||||
if (chance <= this.FallThunderChance)
|
||||
if (chance <= this.Config.FallThunderChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_lightning;
|
||||
this.VerboseLog("It will be stormy tomorrow.");
|
||||
|
@ -183,7 +163,7 @@ namespace Omegasis.MoreRain
|
|||
|
||||
case "winter":
|
||||
// set snow
|
||||
if (chance <= this.WinterSnowChance)
|
||||
if (chance <= this.Config.WinterSnowChance)
|
||||
{
|
||||
Game1.weatherForTomorrow = Game1.weather_snow;
|
||||
this.VerboseLog("It will snow tomorrow.");
|
||||
|
@ -197,91 +177,11 @@ namespace Omegasis.MoreRain
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void SaveConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "More_Rain_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: More Rain Config. Feel free to edit.";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Spring Rain chance: The chance out of 100 that it will rain tomorrow.";
|
||||
text[3] = this.SpringRainChance.ToString();
|
||||
text[4] = "Spring Storm chance: The chance out of 100 that it will be stormy tomorrow.";
|
||||
text[5] = this.SpringThunderChance.ToString();
|
||||
|
||||
text[6] = "Summer Rain chance: The chance out of 100 that it will rain tomorrow.";
|
||||
text[7] = this.SummerRainChance.ToString();
|
||||
text[8] = "Summer Storm chance: The chance out of 100 that it will be stormy tomorrow.";
|
||||
text[9] = this.SummerThunderChance.ToString();
|
||||
|
||||
text[10] = "Fall Rain chance: The chance out of 100 that it will rain tomorrow.";
|
||||
text[11] = this.FallRainChance.ToString();
|
||||
text[12] = "Fall Storm chance: The chance out of 100 that it will be stormy tomorrow.";
|
||||
text[13] = this.FallThunderChance.ToString();
|
||||
|
||||
text[14] = "Winter Snow chance: The chance out of 100 that it will rain tomorrow.";
|
||||
text[15] = this.WinterSnowChance.ToString();
|
||||
|
||||
text[16] = "Supress Log: If true, the mod won't output any messages to the console.";
|
||||
text[17] = this.SuppressLog.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, $"More_Rain_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.SpringRainChance = 15;
|
||||
this.SummerRainChance = 5;
|
||||
this.FallRainChance = 15;
|
||||
this.WinterSnowChance = 15;
|
||||
|
||||
this.SpringThunderChance = 5;
|
||||
this.SummerThunderChance = 10;
|
||||
this.FallThunderChance = 5;
|
||||
|
||||
this.SuppressLog = true;
|
||||
this.SaveConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.SpringRainChance = Convert.ToInt32(text[3]);
|
||||
this.SpringThunderChance = Convert.ToInt32(text[5]);
|
||||
this.SummerRainChance = Convert.ToInt32(text[7]);
|
||||
this.SummerThunderChance = Convert.ToInt32(text[9]);
|
||||
this.FallRainChance = Convert.ToInt32(text[11]);
|
||||
this.FallThunderChance = Convert.ToInt32(text[13]);
|
||||
this.WinterSnowChance = Convert.ToInt32(text[15]);
|
||||
this.SuppressLog = Convert.ToBoolean(text[17]);
|
||||
}
|
||||
catch (Exception) //something dun goofed
|
||||
{
|
||||
this.SpringRainChance = 15;
|
||||
this.SummerRainChance = 5;
|
||||
this.FallRainChance = 15;
|
||||
this.WinterSnowChance = 15;
|
||||
|
||||
this.SpringThunderChance = 5;
|
||||
this.SummerThunderChance = 10;
|
||||
this.FallThunderChance = 5;
|
||||
|
||||
this.SuppressLog = true;
|
||||
this.SaveConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Log a message if <see cref="SuppressLog"/> is <c>false</c>.</summary>
|
||||
/// <param name="message">The message to log.</param>
|
||||
private void VerboseLog(string message)
|
||||
{
|
||||
if (!this.SuppressLog)
|
||||
if (!this.Config.SuppressLog)
|
||||
this.Monitor.Log(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="MoreRain.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -9,8 +9,8 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
3. Run the game using SMAPI.
|
||||
|
||||
## Usage
|
||||
Edit `More_Rain_Config.txt` to change the chance of rain, storms, or snow. Each value is a
|
||||
percentage (0 to 100).
|
||||
Edit `config.json` to change the chance of rain, storms, or snow. Each value is a percentage (0
|
||||
to 100).
|
||||
|
||||
It won't rain on days where a wedding or a festival would take place.
|
||||
|
||||
|
@ -29,4 +29,5 @@ It won't rain on days where a wedding or a festival would take place.
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace Omegasis.MuseumRearranger.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The key which shows the museum rearranging menu.</summary>
|
||||
public string ShowMenuKey { get; set; } = "R";
|
||||
|
||||
/// <summary>The key which toggles the inventory box when the menu is open.</summary>
|
||||
public string ToggleInventoryKey { get; set; } = "T";
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.MuseumRearranger.Framework;
|
||||
using Omegasis.MuseumRearranger.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -14,11 +12,8 @@ namespace Omegasis.MuseumRearranger
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The key which shows the museum rearranging menu.</summary>
|
||||
private string ShowMenuKey = "R";
|
||||
|
||||
/// <summary>The key which toggles the inventory box when the menu is open.</summary>
|
||||
private string ToggleInventoryKey = "T";
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>The open museum menu (if any).</summary>
|
||||
private NewMuseumMenu OpenMenu;
|
||||
|
@ -31,7 +26,8 @@ namespace Omegasis.MuseumRearranger
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
ControlEvents.KeyPressed += this.ControlEvents_KeyPressed;
|
||||
}
|
||||
|
||||
|
@ -48,7 +44,7 @@ namespace Omegasis.MuseumRearranger
|
|||
return;
|
||||
|
||||
// open menu
|
||||
if (e.KeyPressed.ToString() == this.ShowMenuKey)
|
||||
if (e.KeyPressed.ToString() == this.Config.ShowMenuKey)
|
||||
{
|
||||
if (Game1.activeClickableMenu != null)
|
||||
return;
|
||||
|
@ -59,48 +55,8 @@ namespace Omegasis.MuseumRearranger
|
|||
}
|
||||
|
||||
// toggle inventory box
|
||||
if (e.KeyPressed.ToString() == this.ToggleInventoryKey)
|
||||
if (e.KeyPressed.ToString() == this.Config.ToggleInventoryKey)
|
||||
this.OpenMenu?.ToggleInventory();
|
||||
}
|
||||
|
||||
/// <summary>The method invoked after the player loads a save.</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Museum_Rearrange_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.ShowMenuKey = "R";
|
||||
this.ToggleInventoryKey = "T";
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.ShowMenuKey = Convert.ToString(text[3]);
|
||||
this.ToggleInventoryKey = Convert.ToString(text[5]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Museum_Rearrange_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Config: Museum_Rearranger. Feel free to mess with these settings.";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Key binding for rearranging the museum.";
|
||||
text[3] = this.ShowMenuKey;
|
||||
text[4] = "Key binding for showing the menu when rearranging the museum.";
|
||||
text[5] = this.ToggleInventoryKey;
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="MuseumRearranger.cs" />
|
||||
<Compile Include="Framework\NewMuseumMenu.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -10,7 +10,7 @@ Compatible with Stardew Valley 1.2+ on Linux, Mac, and Windows.
|
|||
|
||||
## Usage
|
||||
Press `R` while in the museum to open the rearranging menu. Press `T` while the menu is open to
|
||||
toggle the inventory box. Edit `Museum_Rearrange_Config.txt` to change the keys.
|
||||
toggle the inventory box. Edit `config.json` to change the keys.
|
||||
|
||||
## Versions
|
||||
1.0:
|
||||
|
@ -28,4 +28,5 @@ toggle the inventory box. Edit `Museum_Rearrange_Config.txt` to change the keys.
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.4:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
namespace Omegasis.NightOwl.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>Whether lighting should transition to day from 2am to 6am. If <c>false</c>, the world will stay dark until the player passes out or goes to bed.</summary>
|
||||
public bool MorningLightTransition { get; set; } = true;
|
||||
|
||||
/// <summary>Whether the player can stay up until 6am.</summary>
|
||||
public bool StayUp { get; set; } = true;
|
||||
|
||||
/// <summary>Whether to remove the mail received for collapsing like 'we charged X gold for your health fees'.</summary>
|
||||
public bool SkipCollapseMail { get; set; } = true;
|
||||
|
||||
/// <summary>Whether to restore the player's position after they collapse.</summary>
|
||||
public bool KeepPositionAfterCollapse { get; set; } = true;
|
||||
|
||||
/// <summary>Whether to restore the player's money after they collapse (i.e. prevent the automatic deduction).</summary>
|
||||
public bool KeepMoneyAfterCollapse { get; set; } = true;
|
||||
|
||||
/// <summary>Whether to keep stamina as-is after the player collapses.</summary>
|
||||
public bool KeepHealthAfterCollapse { get; set; } = true;
|
||||
|
||||
/// <summary>Whether to keep stamina as-is after the player collapses.</summary>
|
||||
public bool KeepStaminaAfterCollapse { get; set; } = true;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using Omegasis.NightOwl.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -24,6 +24,9 @@ namespace Omegasis.NightOwl
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/****
|
||||
** Context
|
||||
****/
|
||||
|
@ -57,29 +60,6 @@ namespace Omegasis.NightOwl
|
|||
/// <summary>The player's health before they collapsed.</summary>
|
||||
private int PreCollapseHealth;
|
||||
|
||||
/****
|
||||
** Settings
|
||||
****/
|
||||
/// <summary>Whether lighting should transition to day from 2am to 6am. If <c>false</c>, the world will stay dark until the player passes out or goes to bed.</summary>
|
||||
private bool MorningLightTransition;
|
||||
|
||||
/// <summary>Whether the player can stay up until 6am.</summary>
|
||||
private bool StayUp;
|
||||
|
||||
/// <summary>Whether to remove the mail received for collapsing like 'we charged X gold for your health fees'.</summary>
|
||||
private bool SkipCollapseMail;
|
||||
|
||||
/// <summary>Whether to restore the player's position after they collapse.</summary>
|
||||
private bool KeepPositionAfterCollapse;
|
||||
|
||||
/// <summary>Whether to restore the player's money after they collapse (i.e. prevent the automatic deduction).</summary>
|
||||
private bool KeepMoneyAfterCollapse;
|
||||
|
||||
/// <summary>Whether to keep stamina as-is after the player collapses.</summary>
|
||||
private bool KeepHealthAfterCollapse;
|
||||
|
||||
/// <summary>Whether to keep stamina as-is after the player collapses.</summary>
|
||||
private bool KeepStaminaAfterCollapse;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -89,6 +69,8 @@ namespace Omegasis.NightOwl
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
TimeEvents.TimeOfDayChanged += this.TimeEvents_TimeOfDayChanged;
|
||||
TimeEvents.AfterDayStarted += this.TimeEvents_AfterDayStarted;
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
|
@ -107,7 +89,7 @@ namespace Omegasis.NightOwl
|
|||
try
|
||||
{
|
||||
// reset position after collapse
|
||||
if (Context.IsWorldReady && this.JustStartedNewDay && this.KeepPositionAfterCollapse)
|
||||
if (Context.IsWorldReady && this.JustStartedNewDay && this.Config.KeepPositionAfterCollapse)
|
||||
{
|
||||
if (this.PreCollapseMap != null)
|
||||
Game1.warpFarmer(this.PreCollapseMap, this.PreCollapseTile.X, this.PreCollapseTile.Y, false);
|
||||
|
@ -129,8 +111,6 @@ namespace Omegasis.NightOwl
|
|||
/// <param name="e">The event data.</param>
|
||||
public void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
this.IsUpLate = false;
|
||||
this.JustStartedNewDay = false;
|
||||
this.JustCollapsed = false;
|
||||
|
@ -144,8 +124,6 @@ namespace Omegasis.NightOwl
|
|||
try
|
||||
{
|
||||
// reset data
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
this.IsUpLate = false;
|
||||
Game1.farmerShouldPassOut = false;
|
||||
|
||||
|
@ -154,18 +132,18 @@ namespace Omegasis.NightOwl
|
|||
{
|
||||
this.ShouldResetPlayerAfterCollapseNow = false;
|
||||
|
||||
if (this.KeepStaminaAfterCollapse)
|
||||
if (this.Config.KeepStaminaAfterCollapse)
|
||||
Game1.player.stamina = this.PreCollapseStamina;
|
||||
if (this.KeepHealthAfterCollapse)
|
||||
if (this.Config.KeepHealthAfterCollapse)
|
||||
Game1.player.health = this.PreCollapseHealth;
|
||||
if (this.KeepMoneyAfterCollapse)
|
||||
if (this.Config.KeepMoneyAfterCollapse)
|
||||
Game1.player.money = this.PreCollapseMoney;
|
||||
if (this.KeepPositionAfterCollapse)
|
||||
if (this.Config.KeepPositionAfterCollapse)
|
||||
Game1.warpFarmer(this.PreCollapseMap, this.PreCollapseTile.X, this.PreCollapseTile.Y, false);
|
||||
}
|
||||
|
||||
// delete annoying charge messages (if only I could do this with mail IRL)
|
||||
if (this.SkipCollapseMail)
|
||||
if (this.Config.SkipCollapseMail)
|
||||
{
|
||||
string[] validMail = Game1.mailbox
|
||||
.Where(p => !p.Contains("passedOut"))
|
||||
|
@ -196,14 +174,14 @@ namespace Omegasis.NightOwl
|
|||
try
|
||||
{
|
||||
// transition morning light more realistically
|
||||
if (this.MorningLightTransition && Game1.timeOfDay > 400 && Game1.timeOfDay < 600)
|
||||
if (this.Config.MorningLightTransition && Game1.timeOfDay > 400 && Game1.timeOfDay < 600)
|
||||
{
|
||||
float colorMod = (1300 - Game1.timeOfDay) / 1000f;
|
||||
Game1.outdoorLight = Game1.ambientLight * colorMod;
|
||||
}
|
||||
|
||||
// transition to next morning
|
||||
if (this.StayUp && Game1.timeOfDay == 2550)
|
||||
if (this.Config.StayUp && Game1.timeOfDay == 2550)
|
||||
{
|
||||
Game1.isRaining = false; // remove rain, otherwise lighting gets screwy
|
||||
Game1.updateWeatherIcon();
|
||||
|
@ -236,83 +214,24 @@ namespace Omegasis.NightOwl
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Night_Owl_Config_.txt");
|
||||
string[] text = new string[20];
|
||||
|
||||
text[0] = "Player: Night Owl Config. Feel free to edit.";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Whether you can stay up until 6am.";
|
||||
text[3] = this.StayUp.ToString();
|
||||
text[4] = "Whether the lighting should transition to daytime from 2am to 6am. Setting this to false will keep the world dark until the player passes out or goes to bed.";
|
||||
text[5] = this.MorningLightTransition.ToString();
|
||||
text[6] = "Whether to keep your position as-is after you collapse at 6am. If false, you'll warp back home.";
|
||||
text[7] = this.KeepPositionAfterCollapse.ToString();
|
||||
text[8] = "Whether to prevent money from being deducted after you collapse at 6am.";
|
||||
text[9] = this.KeepMoneyAfterCollapse.ToString();
|
||||
text[10] = "Whether to keep your stamina as-is after you collapse at 6am.";
|
||||
text[11] = this.KeepStaminaAfterCollapse.ToString();
|
||||
text[12] = "Whether to keep your health as-is after you collapse at 6am.";
|
||||
text[13] = this.KeepHealthAfterCollapse.ToString();
|
||||
text[14] = "Whether to remove the mail you receive for collapsing like 'we charged X gold for your health fees'.";
|
||||
text[15] = this.SkipCollapseMail.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Night_Owl_Config_.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.MorningLightTransition = true;
|
||||
this.KeepPositionAfterCollapse = true;
|
||||
this.StayUp = true;
|
||||
|
||||
this.KeepHealthAfterCollapse = true;
|
||||
this.KeepStaminaAfterCollapse = true;
|
||||
this.SkipCollapseMail = true;
|
||||
this.KeepMoneyAfterCollapse = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.StayUp = Convert.ToBoolean(text[3]);
|
||||
this.MorningLightTransition = Convert.ToBoolean(text[5]);
|
||||
this.KeepPositionAfterCollapse = Convert.ToBoolean(text[7]);
|
||||
this.KeepMoneyAfterCollapse = Convert.ToBoolean(text[9]);
|
||||
this.KeepStaminaAfterCollapse = Convert.ToBoolean(text[11]);
|
||||
this.KeepHealthAfterCollapse = Convert.ToBoolean(text[13]);
|
||||
this.SkipCollapseMail = text[15] == "" || Convert.ToBoolean(text[15]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Write the current mod state to the error log file.</summary>
|
||||
private void WriteErrorLog()
|
||||
{
|
||||
try
|
||||
var state = new
|
||||
{
|
||||
JsonSerializer serializer = new JsonSerializer
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
TypeNameHandling = TypeNameHandling.All,
|
||||
Formatting = Formatting.Indented,
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
||||
};
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "Error_Logs", "Mod_State.json");
|
||||
using (StreamWriter sw = new StreamWriter(path))
|
||||
{
|
||||
using (JsonWriter writer2 = new JsonTextWriter(sw))
|
||||
serializer.Serialize(writer2, this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log(ex.ToString(), LogLevel.Error);
|
||||
}
|
||||
this.Config,
|
||||
this.IsUpLate,
|
||||
this.ShouldResetPlayerAfterCollapseNow,
|
||||
this.JustStartedNewDay,
|
||||
this.JustCollapsed,
|
||||
this.PreCollapseMap,
|
||||
this.PreCollapseTile,
|
||||
this.PreCollapseMoney,
|
||||
this.PreCollapseStamina,
|
||||
this.PreCollapseHealth
|
||||
};
|
||||
string path = Path.Combine(this.Helper.DirectoryPath, "Error_Logs", "Mod_State.json");
|
||||
this.Helper.WriteJsonFile(path, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
@ -41,6 +37,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="NightOwl.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -14,7 +14,7 @@ Simply stay up past 2am, and you won't collapse. The lighting will gradually bri
|
|||
rises. At 6am you'll temporarily collapse so the game can save, but you won't lose anything and
|
||||
you'll stay where you are.
|
||||
|
||||
Edit the `Night_Owl_Config_.txt` to change the mod settings.
|
||||
Edit the `config.json` to change the mod settings.
|
||||
|
||||
## Versions
|
||||
1.0:
|
||||
|
@ -25,4 +25,5 @@ Edit the `Night_Owl_Config_.txt` to change the mod settings.
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net45" />
|
||||
<package id="Pathoschild.Stardew.ModBuildConfig" version="1.7.0" targetFramework="net45" />
|
||||
</packages>
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Omegasis.SaveAnywhere.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace Omegasis.SaveBackup.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The number of save backups to keep for each type.</summary>
|
||||
public int SaveCount { get; set; } = 30;
|
||||
}
|
||||
}
|
|
@ -24,4 +24,5 @@ configure that.
|
|||
|
||||
1.3:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using Omegasis.SaveBackup.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
|
||||
|
@ -25,8 +26,8 @@ namespace Omegasis.SaveBackup
|
|||
/// <summary>The folder path containing nightly backups of the save.</summary>
|
||||
private static readonly string NightlyBackupsPath = Path.Combine(SaveBackup.AppDataPath, "Backed_Up_Saves", "Nightly_InGame_Saves");
|
||||
|
||||
/// <summary>The number of save backups to keep for each type.</summary>
|
||||
private int SaveCount = 30;
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -36,8 +37,7 @@ namespace Omegasis.SaveBackup
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
this.BackupSaves(SaveBackup.PrePlayBackupsPath);
|
||||
|
||||
|
@ -68,33 +68,9 @@ namespace Omegasis.SaveBackup
|
|||
new DirectoryInfo(folderPath)
|
||||
.EnumerateFiles()
|
||||
.OrderByDescending(f => f.CreationTime)
|
||||
.Skip(this.SaveCount)
|
||||
.Skip(this.Config.SaveCount)
|
||||
.ToList()
|
||||
.ForEach(file => file.Delete());
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
var path = Path.Combine(Helper.DirectoryPath, "AutoBackup_data.txt");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.SaveCount = Convert.ToInt32(text[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "AutoBackup_data.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: AutoBackup Config:";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Number of Backups to Keep:";
|
||||
text[3] = this.SaveCount.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="SaveBackup.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
namespace Omegasis.StardewSymphony.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>The minimum delay (in milliseconds) to pass before playing the next song, or 0 for no delay.</summary>
|
||||
public int MinSongDelay { get; set; } = 10000;
|
||||
|
||||
/// <summary>The maximum delay (in milliseconds) to pass before playing the next song, or 0 for no delay.</summary>
|
||||
public int MaxSongDelay { get; set; } = 30000;
|
||||
|
||||
/// <summary>Whether to disable ambient rain audio when music is playing. If false, plays ambient rain audio alongside whatever songs are set in rain music.</summary>
|
||||
public bool SilentRain { get; set; }
|
||||
|
||||
/// <summary>Whether to play seasonal music from the music packs, instead of defaulting to the Stardew Valley Soundtrack.</summary>
|
||||
public bool PlaySeasonalMusic { get; set; } = true;
|
||||
}
|
||||
}
|
|
@ -34,4 +34,5 @@ This won't mute the music for in-game events or festivals.
|
|||
|
||||
1.4:
|
||||
* Updated for SMAPI 2.0.
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -25,6 +25,9 @@ namespace Omegasis.StardewSymphony
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
/// <summary>All of the music/soundbanks and their locations.</summary>
|
||||
private IList<MusicManager> MasterList = new List<MusicManager>();
|
||||
|
||||
|
@ -60,21 +63,6 @@ namespace Omegasis.StardewSymphony
|
|||
/// <summary>A timer used to create random pauses between songs.</summary>
|
||||
private Timer SongDelayTimer = new Timer();
|
||||
|
||||
/****
|
||||
** Config
|
||||
****/
|
||||
/// <summary>The minimum delay (in milliseconds) to pass before playing the next song, or 0 for no delay.</summary>
|
||||
private int MinSongDelay;
|
||||
|
||||
/// <summary>The maximum delay (in milliseconds) to pass before playing the next song, or 0 for no delay.</summary>
|
||||
private int MaxSongDelay;
|
||||
|
||||
/// <summary>Whether to disable ambient rain audio when music is playing. If false, plays ambient rain audio alongside whatever songs are set in rain music.</summary>
|
||||
private bool SilentRain;
|
||||
|
||||
/// <summary>Whether to play seasonal music from the music packs, instead of defaulting to the Stardew Valley Soundtrack.</summary>
|
||||
private bool PlaySeasonalMusic;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -83,6 +71,7 @@ namespace Omegasis.StardewSymphony
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
this.HexProcessor = new MusicHexProcessor(this.MasterList, this.Reset);
|
||||
|
||||
SaveEvents.AfterLoad += this.SaveEvents_AfterLoad;
|
||||
|
@ -122,7 +111,7 @@ namespace Omegasis.StardewSymphony
|
|||
return; // replace with festival
|
||||
if (Game1.eventUp)
|
||||
return; // replace with event music
|
||||
if (Game1.isRaining && !this.SilentRain)
|
||||
if (Game1.isRaining && !this.Config.SilentRain)
|
||||
return; // play the rain ambience soundtrack
|
||||
|
||||
Game1.currentSong.Stop(AudioStopOptions.Immediate); //stop the normal songs from playing over the new songs
|
||||
|
@ -135,9 +124,6 @@ namespace Omegasis.StardewSymphony
|
|||
private void TimeEvents_AfterDayStarted(object sender, EventArgs e)
|
||||
{
|
||||
this.StopSound(); //if my music player is called and I forget to clean up sound before hand, kill the old sound.
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
|
||||
this.SelectMusic();
|
||||
}
|
||||
|
||||
|
@ -146,10 +132,6 @@ namespace Omegasis.StardewSymphony
|
|||
/// <param name="e">The event data.</param>
|
||||
private void SaveEvents_AfterLoad(object sender, EventArgs e)
|
||||
{
|
||||
// init config
|
||||
this.LoadConfig();
|
||||
this.WriteConfig();
|
||||
|
||||
// init context
|
||||
this.Random = new Random();
|
||||
this.MasterList = new List<MusicManager>();
|
||||
|
@ -192,7 +174,7 @@ namespace Omegasis.StardewSymphony
|
|||
{
|
||||
// reset timer
|
||||
this.SongDelayTimer.Dispose();
|
||||
this.SongDelayTimer = new Timer(this.Random.Next(this.MinSongDelay, this.MaxSongDelay));
|
||||
this.SongDelayTimer = new Timer(this.Random.Next(this.Config.MinSongDelay, this.Config.MaxSongDelay));
|
||||
|
||||
// start timer
|
||||
this.SongDelayTimer.Elapsed += (sender, args) =>
|
||||
|
@ -364,7 +346,7 @@ namespace Omegasis.StardewSymphony
|
|||
|
||||
if (this.HasNoMusic) //if there is valid music playing
|
||||
{
|
||||
if (!this.PlaySeasonalMusic)
|
||||
if (!this.Config.PlaySeasonalMusic)
|
||||
return;
|
||||
|
||||
if (this.CurrentSong != null && this.CurrentSong.IsPlaying)
|
||||
|
@ -1185,49 +1167,5 @@ namespace Omegasis.StardewSymphony
|
|||
Game1.waveBank = this.DefaultWavebank;
|
||||
Game1.soundBank = this.DefaultSoundbank;
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Music_Expansion_Config.txt");
|
||||
string[] text = new string[20];
|
||||
text[0] = "Player: Stardew Valley Music Expansion Config. Feel free to edit.";
|
||||
text[1] = "====================================================================================";
|
||||
|
||||
text[2] = "Minimum delay time: This is the minimal amout of time(in miliseconds!!!) that will pass before another song will play. 0 means a song will play immediately, 1000 means a second will pass, etc. Used in RNG to determine a random delay between songs.";
|
||||
text[3] = this.MinSongDelay.ToString();
|
||||
|
||||
text[4] = "Maximum delay time: This is the maximum amout of time(in miliseconds!!!) that will pass before another song will play. 0 means a song will play immediately, 1000 means a second will pass, etc. Used in RNG to determine a random delay between songs.";
|
||||
text[5] = this.MaxSongDelay.ToString();
|
||||
|
||||
text[6] = "Silent rain? Setting this value to false plays the default ambient rain music along side whatever songs are set in rain music. Setting this to true will disable the ambient rain music. It's up to the soundpack creators wither or not they want to mix their music with rain prior to loading it in here.";
|
||||
text[7] = this.SilentRain.ToString();
|
||||
|
||||
text[8] = "Seasonal_Music? Setting this value to true will play the seasonal music from the music packs instead of defaulting to the Stardew Valley Soundtrack.";
|
||||
text[9] = this.PlaySeasonalMusic.ToString();
|
||||
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "Music_Expansion_Config.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.MinSongDelay = 10000;
|
||||
this.MaxSongDelay = 30000;
|
||||
this.SilentRain = false;
|
||||
this.PlaySeasonalMusic = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.MinSongDelay = Convert.ToInt32(text[3]);
|
||||
this.MaxSongDelay = Convert.ToInt32(text[5]);
|
||||
this.SilentRain = Convert.ToBoolean(text[7]);
|
||||
this.PlaySeasonalMusic = Convert.ToBoolean(text[9]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="StardewSymphony.cs" />
|
||||
<Compile Include="Framework\MusicHexProcessor.cs" />
|
||||
<Compile Include="Framework\MusicManager.cs" />
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace Omegasis.TimeFreeze.Framework
|
||||
{
|
||||
/// <summary>The mod configuration.</summary>
|
||||
internal class ModConfig
|
||||
{
|
||||
/// <summary>Whether time should be unfrozen while the player is swimming.</summary>
|
||||
public bool PassTimeWhileSwimming { get; set; } = true;
|
||||
|
||||
/// <summary>Whether time should be unfrozen while the player is swimming in the vanilla bathhouse.</summary>
|
||||
public bool PassTimeWhileSwimmingInBathhouse { get; set; } = true;
|
||||
}
|
||||
}
|
|
@ -20,4 +20,5 @@ but you can edit `ModConfig.txt` to change that.
|
|||
* Updated to Stardew Valley 1.2 and SMAPI 1.12.
|
||||
|
||||
1.2:
|
||||
* Switched to standard JSON config file.
|
||||
* Internal refactoring.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Omegasis.TimeFreeze.Framework;
|
||||
using StardewModdingAPI;
|
||||
using StardewModdingAPI.Events;
|
||||
using StardewValley;
|
||||
|
@ -13,11 +13,8 @@ namespace Omegasis.TimeFreeze
|
|||
/*********
|
||||
** Properties
|
||||
*********/
|
||||
/// <summary>Whether time should be unfrozen while the player is swimming.</summary>
|
||||
private bool PassTimeWhileSwimming = true;
|
||||
|
||||
/// <summary>Whether time should be unfrozen while the player is swimming in the vanilla bathhouse.</summary>
|
||||
private bool PassTimeWhileSwimmingInBathhouse = true;
|
||||
/// <summary>The mod configuration.</summary>
|
||||
private ModConfig Config;
|
||||
|
||||
|
||||
/*********
|
||||
|
@ -27,8 +24,9 @@ namespace Omegasis.TimeFreeze
|
|||
/// <param name="helper">Provides simplified APIs for writing mods.</param>
|
||||
public override void Entry(IModHelper helper)
|
||||
{
|
||||
this.Config = helper.ReadConfig<ModConfig>();
|
||||
|
||||
GameEvents.UpdateTick += this.GameEvents_UpdateTick;
|
||||
this.LoadConfig();
|
||||
}
|
||||
|
||||
/*********
|
||||
|
@ -55,44 +53,12 @@ namespace Omegasis.TimeFreeze
|
|||
return false;
|
||||
if (player.swimming)
|
||||
{
|
||||
if (this.PassTimeWhileSwimmingInBathhouse && location is BathHousePool)
|
||||
if (this.Config.PassTimeWhileSwimmingInBathhouse && location is BathHousePool)
|
||||
return false;
|
||||
if (this.PassTimeWhileSwimming)
|
||||
if (this.Config.PassTimeWhileSwimming)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Save the configuration settings.</summary>
|
||||
private void WriteConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "ModConfig.txt");
|
||||
string[] text = new string[6];
|
||||
text[0] = "Player: TimeFreeze Config";
|
||||
text[1] = "====================================================================================";
|
||||
text[2] = "Whether to unfreeze time while swimming in the vanilla bathhouse.";
|
||||
text[3] = this.PassTimeWhileSwimmingInBathhouse.ToString();
|
||||
text[4] = "Whether to unfreeze time while swimming anywhere.";
|
||||
text[5] = this.PassTimeWhileSwimming.ToString();
|
||||
File.WriteAllLines(path, text);
|
||||
}
|
||||
|
||||
/// <summary>Load the configuration settings.</summary>
|
||||
private void LoadConfig()
|
||||
{
|
||||
string path = Path.Combine(Helper.DirectoryPath, "ModConfig.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
this.PassTimeWhileSwimming = true;
|
||||
this.PassTimeWhileSwimmingInBathhouse = true;
|
||||
this.WriteConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] text = File.ReadAllLines(path);
|
||||
this.PassTimeWhileSwimming = Convert.ToBoolean(text[3]);
|
||||
this.PassTimeWhileSwimmingInBathhouse = Convert.ToBoolean(text[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Framework\ModConfig.cs" />
|
||||
<Compile Include="TimeFreeze.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue